R——如何有条件地对大型数据帧的二进制时间序列数据求和
R -- How to conditionally sum binary time series data for large data frames
我已经尝试解决这个问题太久了。我有 300 多年(行)和 70 多棵树(列)的年度时间序列格式的二进制昆虫爆发数据。
我想有条件地用累积和填充相同维度的数据框/矩阵/数据table,并在每个爆发期结束时将其重置为0。我发现了很多类似的问题/答案,但我似乎无法将其转化为我的问题。
我将有一个数据框的片段,例如,它看起来像这样:
t1 t2 t3 t4 t5
2000 1 0 0 1 0
2001 1 0 0 0 1
2002 1 1 0 0 1
2003 0 1 0 1 1
2004 1 1 1 1 1
我想创建一个新的 df,如下所示:
t1 t2 t3 t4 t5
2000 1 0 0 1 0
2001 2 0 0 0 1
2002 3 1 0 0 2
2003 0 2 0 1 3
2004 1 3 1 2 4
我觉得我已经接近 data.table
和 rle
包,尽管我也绕了很多圈子(很确定我这样做是为了曾经是一个列,但现在不记得我做了什么,或者为什么我不能让它在所有列中循环工作...)。
我一直使用以下方法在一些范围内工作,通常只是一列,或者在移动的 df 之上添加一个 1 df,所以单个列可能看起来像 0 1 2 2 1 0
而不是 0 1 2 3 4 0
。一些尝试,如果这有帮助的话,是代码的变体,如下所示:
setDT(dt)[, new := t1 + shift(t1, fill = 0)]
apply(
rle( matrix)$lengths
, 2, seq)
rle( matrix[,1])$lengths
for( i in 1:dim(dt)[1]) {
for( j in 1:dim(dt)[2]) {
cols <- names(dt) # tried in place of .SD with negative results
if( dt[i,j] == 1) {
dt[, new := .SD + shift(.SD, 1L, fill = 0, type = "lag", give.names = TRUE)]
} else { dt }
}
}
我使用的一些主要 SO 源包括以下页面:data.table, ,
如果我遗漏了任何重要信息,请告诉我(我是新手!)。非常感谢您的帮助!
您可以使用 data.table
结合 ave
函数来计算按列本身的 rleid
分组的每列的累积和:
library(data.table)
setDT(dt)[, names(dt) := lapply(.SD, function(col) ave(col, rleid(col), FUN = cumsum))][]
# t1 t2 t3 t4 t5
#1: 1 0 0 1 0
#2: 2 0 0 0 1
#3: 3 1 0 0 2
#4: 0 2 0 1 3
#5: 1 3 1 2 4
我们可以使用 rle
和 base R
中的 sequence
df2 <- df1 #create a copy of df1
#loop through the columns of 'df2', apply the `rle`, get the 'sequence'
#of 'lengths' and multiply with the column values.
df2[] <- lapply(df2, function(x) sequence(rle(x)$lengths)*x)
df2
# t1 t2 t3 t4 t5
#2000 1 0 0 1 0
#2001 2 0 0 0 1
#2002 3 1 0 0 2
#2003 0 2 0 1 3
#2004 1 3 1 2 4
我已经尝试解决这个问题太久了。我有 300 多年(行)和 70 多棵树(列)的年度时间序列格式的二进制昆虫爆发数据。
我想有条件地用累积和填充相同维度的数据框/矩阵/数据table,并在每个爆发期结束时将其重置为0。我发现了很多类似的问题/答案,但我似乎无法将其转化为我的问题。
我将有一个数据框的片段,例如,它看起来像这样:
t1 t2 t3 t4 t5
2000 1 0 0 1 0
2001 1 0 0 0 1
2002 1 1 0 0 1
2003 0 1 0 1 1
2004 1 1 1 1 1
我想创建一个新的 df,如下所示:
t1 t2 t3 t4 t5
2000 1 0 0 1 0
2001 2 0 0 0 1
2002 3 1 0 0 2
2003 0 2 0 1 3
2004 1 3 1 2 4
我觉得我已经接近 data.table
和 rle
包,尽管我也绕了很多圈子(很确定我这样做是为了曾经是一个列,但现在不记得我做了什么,或者为什么我不能让它在所有列中循环工作...)。
我一直使用以下方法在一些范围内工作,通常只是一列,或者在移动的 df 之上添加一个 1 df,所以单个列可能看起来像 0 1 2 2 1 0
而不是 0 1 2 3 4 0
。一些尝试,如果这有帮助的话,是代码的变体,如下所示:
setDT(dt)[, new := t1 + shift(t1, fill = 0)]
apply(
rle( matrix)$lengths
, 2, seq)
rle( matrix[,1])$lengths
for( i in 1:dim(dt)[1]) {
for( j in 1:dim(dt)[2]) {
cols <- names(dt) # tried in place of .SD with negative results
if( dt[i,j] == 1) {
dt[, new := .SD + shift(.SD, 1L, fill = 0, type = "lag", give.names = TRUE)]
} else { dt }
}
}
我使用的一些主要 SO 源包括以下页面:data.table,
如果我遗漏了任何重要信息,请告诉我(我是新手!)。非常感谢您的帮助!
您可以使用 data.table
结合 ave
函数来计算按列本身的 rleid
分组的每列的累积和:
library(data.table)
setDT(dt)[, names(dt) := lapply(.SD, function(col) ave(col, rleid(col), FUN = cumsum))][]
# t1 t2 t3 t4 t5
#1: 1 0 0 1 0
#2: 2 0 0 0 1
#3: 3 1 0 0 2
#4: 0 2 0 1 3
#5: 1 3 1 2 4
我们可以使用 rle
和 base R
sequence
df2 <- df1 #create a copy of df1
#loop through the columns of 'df2', apply the `rle`, get the 'sequence'
#of 'lengths' and multiply with the column values.
df2[] <- lapply(df2, function(x) sequence(rle(x)$lengths)*x)
df2
# t1 t2 t3 t4 t5
#2000 1 0 0 1 0
#2001 2 0 0 0 1
#2002 3 1 0 0 2
#2003 0 2 0 1 3
#2004 1 3 1 2 4