【发布时间】:2018-08-01 03:34:03
【问题描述】:
我的目标是做到以下几点:
我有一个超过 100 万行和 4 列的 data.table。我想添加带有“1”或“0”的第五列,具体取决于以下条件:如果第 3 列为零,后跟第 3 列的下一行中的任何非零值(如滑动长度为 2) 的窗口,则应将“1”添加到第 5 列,否则应添加“0”。此二进制在第 5 列中的行位置应与非零值相同。此外,我想根据一个键(即列的子集)来执行此操作,如下面的代码所示。
我无法在 data.table 中实现这一点(我刚刚开始使用它)。我编写了以下代码,它可以满足我的要求,但是速度非常慢(> 5 s /迭代):
# all_movement_fit_tidy is a data.table with dim 1.2 mio x 4
# set key "fly" in all_movement_fit_tidy
setkey(all_movement_fit_tidy, fly)
genotypes <- unique(all_movement_fit_tidy$fly)
DT_list <- list()
i <- 1
for(genotype in genotypes){
# Get subset of data.table by genotype
genotype_movement <- all_movement_fit_tidy[genotype]
# Calculate initiation list - figure out how to do this in data.table
initiation <- list()
for(j in 1:(nrow(genotype_movement) - 1)){
initiation[j] <- ifelse(genotype_movement[j, "mm"] == 0 &
genotype_movement[j + 1, "mm"] != 0, 1, 0)
}
# Add a 0 to the end of the list to equal number of rows,
# then bind it to genotype_movement
initiation[length(initiation) + 1] <- 0
genotype_movement <- cbind(genotype_movement, as.numeric(initiation))
colnames(genotype_movement)[5] <- "initiation"
# Save this data table in a list of data.tables (DT_list)
DT_list[[i]] <- genotype_movement
i <- i + 1
}
之后,我会将携带所有data.tables的DT_list的所有条目绑定到一个data.table中。这段代码这么慢的原因是以下部分:
initiation <- list()
for(j in 1:(nrow(genotype_movement) - 1)){
initiation[j] <- ifelse(genotype_movement[j, "mm"] == 0 &
genotype_movement[j + 1, "mm"] != 0, 1, 0)
}
在这里,我循环遍历 data.table 子集的每一行,并将 ifelse() 函数的结果分配给一个列表。如何在 data.table 的 j 参数中执行此操作?我尝试过类似的方法:
genotype_movement[, initiation := function(x) for(i in
1:nrow(genotype_movement) ifelse(.SD[i, "mm"] == 0 & .SD[i + 1, "mm" !=
0, 1, 0)]
但这不起作用,因为 ifelse() 函数返回无法分配给初始列的单个值。
【问题讨论】:
-
DT[, col5:= shift(col3) ==0 & col3 != 0]? -
我不知道 shift,这很棒,谢谢,它有效。我为实现这一点而编写的代码显然很荒谬。
-
仅供参考,可能还有其他方法可以解决此问题,但是由于您没有提供可重现的示例,因此无法进行调查。对于您的下一个问题,请查看stackoverflow.com/a/28481250
-
@Frank 谢谢你,非常有用的评论,我会记住的。
标签: r datatable data.table