我想替换下面的for
循环,因为必须有一种更简单的方法,如果数据帧很大,for
循环会花费很多时间来计算。
示例数据帧df
由几列组成。每列的长度为1,000个条目。列ID
包含字母数字标识符,而所有其他列包含数字NA
。
ID <- c(rep("ID1", 400), rep("ID2", 400), rep("ID3", 200))
set.seed(264060397)
A <- round((runif(1000, 1.0, 1000.0)), digits = 2)
A[sort(sample(c(1:1000), 50, replace = TRUE))] <- NA
B <- round((runif(1000, 1.0, 1000.0)), digits = 2)
B[sort(sample(c(1:1000), 35, replace = TRUE))] <- NA
C <- round((runif(1000, 1.0, 1000.0)), digits = 2)
C[sort(sample(c(1:1000), 243, replace = TRUE))] <- NA
df <- data.table(ID, A, B, C)
我现在想添加一个名为D
的新列,其中应包含计算值。 for
循环完成了应做的工作,但是如果数据帧很大,则需要花费一些时间才能完成。但是,1,000应该不是计算问题。另一方面,15,000可能会导致非常繁忙的for
循环。
df[, D := NA]
df$D = as.numeric(as.character(df$D))
df <- as.data.frame(df)
for(i in 2:length(df$ID)) {
if(df$ID[i] == df$ID[i - 1]) {
if(is.na(df$C[i])) {
df$D[i] <-
df$A[i] - df$A[i - 1] -
df$B[i] - df$B[i - 1]
} else {
df$D[i] <-
df$A[i] - df$A[i - 1]
}
}
}
View(df)
显示D
的某些值是NA
,但这无关紧要。
接下来,我尝试通过完全避免for
循环来加快计算速度。但是,这不起作用。
df$D <- NULL
i = c(1:length(df$ID))
df[, D := ifelse(i == 1 || !(df$ID[i] == df$ID[i - 1]), NA,
ifelse(is.na(df$C[i]),
df$A[i] - df$A[i - 1] -
df$B[i] - df$B[i - 1],
df$A[i] - df$A[i - 1]
))]
在此示例中,R引发以下错误消息:
Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(":=").
如果我没有通过写入df
将df <- as.data.frame(df)
从数据表转换为数据帧,R不会抛出错误消息。但是,列D
仅包含NA
。这些不是for
循环计算的预期结果。 (请注意,我的真实代码针对的是数据帧。因此,该解决方案应该适用于数据帧。)