在R中没有for循环的情况下,如何在非常大的数据帧中计算累积的非零变量?
我有一个巨大的df,试图执行下面的代码需要太长时间。无论如何,要加快速度吗在R中没有for循环的情况下,如何在非常大的数据帧中计算累积的非零变量?,r,R,我有一个巨大的df,试图执行下面的代码需要太长时间。无论如何,要加快速度吗 df$col2 <- 0 for (i in 2:nrow(df)) { if (df$col1 > 0) { df$col2[i] <- df$col2[i-1] + 1 } else { df$col2[i] <- 0 } } 我试图使用col2对col1中的累积非零变量进行计数,并在col1中点击0时重置计数。我将注释我认为是
df$col2 <- 0
for (i in 2:nrow(df)) {
if (df$col1 > 0) {
df$col2[i] <- df$col2[i-1] + 1
}
else {
df$col2[i] <- 0
}
}
我试图使用
col2
对col1
中的累积非零变量进行计数,并在col1
中点击0
时重置计数。我将注释我认为是错误的内容,并显示我认为是更快的等效内容:
df$col2 <- 0
for (i in 2:nrow(df)) {
if (df$col1 > 0) { # at least a "semantic" error
df$col2[i] <- df$col2[i-1] + 1}
else { df$col2[i] <- 0 }
}
这将构造您要求的运行计数,然后将没有增量的条目归零。中有一个快速(但棘手)的解决方案
因此,在你的情况下:
df <- data.frame(col1 = c(1, 0, 10, 28, 0, 0, 2))
f7 <- function(x) { tmp <- cumsum(x) ; tmp - cummax((!x)*tmp) }
df$col2 <- f7(df$col1 > 0)
df
# col1 col2
# 1 1 1
# 2 0 0
# 3 10 1
# 4 28 2
# 5 0 0
# 6 0 0
# 7 2 1
df这是一个使用数据中的rleid()函数的解决方案。表
包:
library(data.table)
setDT(df)[, .(col1, col2 = cumsum(col1 != 0)), by = rleid(col1 != 0)][, rleid := NULL][]
# col1 col2
#1: 1 1
#2: 0 0
#3: 10 1
#4: 28 2
#5: 0 0
#6: 0 0
#7: 2 1
rleid()
函数是一个方便的函数,用于生成用于分组操作的运行长度类型id列(?rleid
)。它应用于由col1!=0
用于区分零值和非零值。在每个组中,cumsum()
用于计算非零值。最后,从结果中删除rleid
列
作为替代方案,cumsum()
setDT(df)[, .(col1, col2 = seq_len(.N)), by = rleid(col1 != 0)][col1 == 0, col2 := 0][
, rleid := NULL][]
但是,这也会计算未请求的后续零值。因此,对于col1
为零的所有行,col2
中的这些计数必须重置为零。感谢您指出语义错误。我想输入的是df$col1[I]>0@42-你的第二行好像有个打字错误。(OP已经澄清了他的问题)@42-似乎当col1
中出现零时,运行计数没有按照OP在澄清评论中的要求重置。谢谢。这很有帮助。你说你有一个巨大的数据帧。有多少行和列?
df <- data.frame(col1 = c(1, 0, 10, 28, 0, 0, 2))
f7 <- function(x) { tmp <- cumsum(x) ; tmp - cummax((!x)*tmp) }
df$col2 <- f7(df$col1 > 0)
df
# col1 col2
# 1 1 1
# 2 0 0
# 3 10 1
# 4 28 2
# 5 0 0
# 6 0 0
# 7 2 1
library(data.table)
setDT(df)[, .(col1, col2 = cumsum(col1 != 0)), by = rleid(col1 != 0)][, rleid := NULL][]
# col1 col2
#1: 1 1
#2: 0 0
#3: 10 1
#4: 28 2
#5: 0 0
#6: 0 0
#7: 2 1
setDT(df)[, .(col1, col2 = seq_len(.N)), by = rleid(col1 != 0)][col1 == 0, col2 := 0][
, rleid := NULL][]