gpt4 book ai didi

r - 子集数据表而不是 for 循环 R 的更快方法

转载 作者:行者123 更新时间:2023-12-04 11:02:34 26 4
gpt4 key购买 nike

我在 R 中有一个数据表(您需要安装数据表包),它使用 X 和 Y 坐标以及来自正态分布和均匀分布的随机数据值生成。坐标表示 2000x1600 阵列上的点,必须分成 16 个较小的“扇区”,每个 500x400。这些部门需要采用正态分布值的平均值,除以均匀分布值的 min^2。我还使用提供的函数 startstop 创建了两个变量 x 和 y,它们具有 16 个扇区的坐标和一个计算每个扇区数字的函数。

library(data.table)
DT <- data.table(X = rep(1:2000, times = 1600), Y = rep(1:1600, each = 2000), Norm =rnorm(1600*2000), Unif = runif(1600*2000))

sectorCalc <- function(x,y,DT) {
sector <- numeric(length = 16)
for (i in 1:length(sector)) {
sect <- DT[X %between% c(x[[1]][i],x[[2]][i]) & Y %between% c(y[[1]][i],y[[2]][i])]
sector[i] <- sCalc(sect)
}
return(sector)
}

startstop <- function(width, y = FALSE) {
startend <- width - (width/4 - 1)
start <- round(seq(0, startend, length.out = 4))
stop <- round(seq(width/4, width, length.out = 4))
if (length(c(start,stop)[anyDuplicated(c(start,stop))]) != 0) {
dup <- anyDuplicated(c(start,stop))
stop[which(stop == c(start,stop)[dup])] <- stop[which(stop == c(start,stop)[dup])] - 1
}
if (y == TRUE) {
coord <- list(rep(start, each = 4), rep(stop, each = 4))
} else if (y == FALSE) {
coord <- list(rep(start, times = 4), rep(stop, times = 4))
}
return(coord)
}

x <- startstop(2000)
y <- startstop(1600, T)

sectorNos <- sectorCalc(x,y,DT)

startstop 函数并不是真正的问题,但我需要一种更快的方法来对数据表进行子集化。必须对“sectorCalc”函数进行一些修改。 for 循环是我能想到的最好的方法,但我对数据表没有太多经验。关于更快地分解数据表的方法有什么想法吗?

最佳答案

不仅使用包 data.table 还使用 cut 函数构建间隔“组”的解决方案:

# Create your test data
library(data.table)

set.seed(123) # make random numbers reproducible to allow comparison of different answers
DT <- data.table(X = rep(1:2000, times = 1600), Y = rep(1:1600, each = 2000), Norm =rnorm(1600*2000), Unif = runif(1600*2000))

# calculate the sector by cutting the x and y values into groups defined by the interval breaks
DT[, x.sect := cut(DT[, X], c(0, 499, 1000, 1500, 2000), dig.lab=10)] # Intervals should be: seq(0, 2000, by=500) lower bound is less one since it is not included in the interval (see help for cut function)
DT[, y.sect := cut(DT[, Y], c(0, 399, 800, 1200, 1600), dig.lab=10)] # Intervals should be: seq(0, 1600, by=400)

# Now calculate per group (calculation logic "stolen" from the working answer of user "Symbolix"
DT[, .(sect = mean(Norm)/min(Unif)^2), by=.(x.sect, y.sect)]

请注意:我认为原始解决方案中第一个和第二个间隔的大小是错误的(x 是 499 而不是 500,y 是 399 而不是 400,所以我无法使用seq 函数来重现您想要的间隔,但必须手动枚举间隔中断)。

编辑 1: 我已将添加 x.sect 和 y.sect 列的原始代码替换为通过引用添加列的改进解决方案 (:=) .

编辑 2:如果您想对结果进行排序,您有(至少)两个选择:

# "Chaining" (output is input of next)
DT[, .(sect = mean(Norm)/min(Unif)^2), by=.(x.sect, y.sect)][order(x.sect, y.sect),]
# Or: Use the "keyby" param instead of "by"
DT[, .(sect = mean(Norm)/min(Unif)^2), keyby=.(x.sect, y.sect)]

编辑 3:为上面代码中的 cut 函数添加了 dig.lab=10 参数,以避免间隔中断的科学记数法。

关于r - 子集数据表而不是 for 循环 R 的更快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35618570/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com