如何正确使用data.table中的ifelse()?

时间:2018-02-21 14:02:33

标签: r datatable data.table

我的目标是执行以下操作:

我有一个带有>的data.table 100万行和4列。我想添加第五列,其中包含' 1'或者' 0',取决于以下条件:如果第3列中有零,后面是第3列的下一行中的任何非零值(如长度为2的滑动窗口),则为& #39; 1'应添加到第5列,否则为' 0'。第5列中此二进制文件的行位置应与非零值相同。此外,我想基于一个键(即列的子集)执行此操作,如下面的代码所示。

我无法在data.table中实现它(我刚刚开始使用它)。我写了下面的代码,它做了我想要的,但它的速度非常慢(> 5秒/迭代):

# 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
}

在此之后,我会将DT_list的所有条目绑定到一个data.table中,该条目包含所有data.tables。这段代码如此慢的原因如下:

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()函数返回无法分配给启动列的单个值。

1 个答案:

答案 0 :(得分:3)

你已经走了一个兔子洞。以上就是这样:

DT[, col5:= shift(col3, fill = -1) == 0 & col3 != 0]

# or
DT[, col5:= shift(col3, fill = -1) == 0 & col3 != 0, keyby = key(DT)]