R中的组内运算(非滚动求和)

R中的组内运算(非滚动求和),r,data.table,rolling-computation,sliding-window,longitudinal,R,Data.table,Rolling Computation,Sliding Window,Longitudinal,我有一个由学生(id)和他们每年所在的年级组成的数据集: library(data.table) set.seed(1) students <- data.table("id" = rep(1:10, each = 10), "year" = rep(2000:2009, 10), "grade" = sample(c(9:11, rep(NA, 5)), 100, replace = T)) 我想有一个方法来访问每个学生之

我有一个由学生(
id
)和他们每年所在的年级组成的数据集:

library(data.table)
set.seed(1)
students <- data.table("id" = rep(1:10, each = 10),
                "year" = rep(2000:2009, 10),
                "grade" = sample(c(9:11, rep(NA, 5)), 100, replace = T))
我想有一个方法来访问每个学生之前和未来的成绩,以执行不同的操作。例如,将学生的最后三个年级相加。这将产生如下数据集:

    id year grade sum_lag_3
 1:  1 2000     9         9 # 1st window, size 1: 9
 2:  1 2001    NA         9 
 3:  1 2002    NA         9
 4:  1 2003     9        18 # 2nd, size 2: 9 + 9 = 18 
 5:  1 2004    10        28 # 3rd, size 3: 9 + 9 + 10 = 28
 6:  1 2005    NA        28
 7:  1 2006    NA        28
 8:  1 2007    11        30 # 4th, size 3: 9 + 10 + 11 = 30 
 9:  1 2008    NA        30
10:  1 2009    10        31 # 5th, size 3: 10 + 11 + 10 = 31

11:  2 2001    11        11 # 1st window, size 1: 11 
(所有结果都是这样的)

  • 然而,这不是一篇关于滚动求和的帖子
  • 我希望能够更普遍地在每个小组内进行操作,为此,我需要找到一种方法来参考所有学生过去和未来的成绩
因此,在第一行的情况下,由于没有先前的观测,这意味着“过去”向量为空,而“未来”向量为
NA NA 9 10 NA 11 NA 10

类似地,对于第二行,“过去”向量为
9
,“未来”向量为:

NA 9 10 NA 11 NA 10

对于第三行,“过去”向量为
9NA
,“未来”向量为:

9 10 NA 11 NA 10

这是我希望参考的信息,以便进行不同的计算。仅在每个组中进行的计算,根据上下文的不同而有所不同。我最好使用
data.table
来完成这项工作,而不必将数据重新格式化为宽格式

我试着做了以下几点:

students[, .SD[, sum_last_3:= ...], by = id]
但我收到一条错误消息,说此功能在
data.table
(其中…是任何操作的占位符)上尚不可用

谢谢大家



这里有一个选项,在
数据中使用
frollsum
。表
在进行最后一次观察之前,首先将其应用于非NA值:

students[!is.na(grade), sum_lag_3 := 
    fcoalesce(frollsum(grade, 3L), as.double(cumsum(grade))), id]
students[, sum_lag_3 := nafill(sum_lag_3, "locf"), id]
输出:

     id year grade sum_lag_3
  1:  1 2000     9         9
  2:  1 2001    NA         9
  3:  1 2002    NA         9
  4:  1 2003     9        18
  5:  1 2004    10        28
  6:  1 2005    NA        28
  7:  1 2006    NA        28
  8:  1 2007    11        30
  9:  1 2008    NA        30
 10:  1 2009    10        31
 11:  2 2000    11        11    <-----
 12:  2 2001    11        22
 13:  2 2002     9        31
 14:  2 2003    NA        31
 15:  2 2004    NA        31
 16:  2 2005    10        30
 17:  2 2006    NA        30
 18:  2 2007    NA        30
 19:  2 2008    10        29
 20:  2 2009    NA        29
 21:  3 2000     9         9
 22:  3 2001    NA         9
 23:  3 2002    NA         9
 24:  3 2003    NA         9
 25:  3 2004     9        18
 26:  3 2005     9        27
 27:  3 2006    NA        27
 28:  3 2007    NA        27
 29:  3 2008    NA        27
 30:  3 2009    10        28
 31:  4 2000    10        10
 32:  4 2001    NA        10
 33:  4 2002     9        19
 34:  4 2003    NA        19
 35:  4 2004    NA        19
 36:  4 2005     9        28
 37:  4 2006    NA        28
 38:  4 2007    11        29
 39:  4 2008    NA        29
 40:  4 2009    10        30
 41:  5 2000    10        10
 42:  5 2001    NA        10
 43:  5 2002    NA        10
 44:  5 2003    NA        10
 45:  5 2004    NA        10
 46:  5 2005    NA        10
 47:  5 2006    10        20
 48:  5 2007    NA        20
 49:  5 2008     9        29
 50:  5 2009    NA        29
 51:  6 2000    NA        NA
 52:  6 2001     9         9
 53:  6 2002    NA         9
 54:  6 2003    NA         9
 55:  6 2004     9        18
 56:  6 2005    NA        18
 57:  6 2006    NA        18
 58:  6 2007    NA        18
 59:  6 2008    10        28
 60:  6 2009    NA        28
 61:  7 2000    11        11
 62:  7 2001    10        21
 63:  7 2002    NA        21
 64:  7 2003    NA        21
 65:  7 2004    NA        21
 66:  7 2005    NA        21
 67:  7 2006    10        31
 68:  7 2007    NA        31
 69:  7 2008    10        30
 70:  7 2009    NA        30
 71:  8 2000    NA        NA
 72:  8 2001    NA        NA
 73:  8 2002     9         9
 74:  8 2003    11        20
 75:  8 2004    11        31
 76:  8 2005    NA        31
 77:  8 2006    NA        31
 78:  8 2007    NA        31
 79:  8 2008    NA        31
 80:  8 2009    NA        31
 81:  9 2000    NA        NA
 82:  9 2001    NA        NA
 83:  9 2002    NA        NA
 84:  9 2003    11        11
 85:  9 2004     9        20
 86:  9 2005    NA        20
 87:  9 2006    NA        20
 88:  9 2007    NA        20
 89:  9 2008     9        29
 90:  9 2009    NA        29
 91: 10 2000     9         9
 92: 10 2001    NA         9
 93: 10 2002    NA         9
 94: 10 2003    NA         9
 95: 10 2004    NA         9
 96: 10 2005    NA         9
 97: 10 2006    NA         9
 98: 10 2007    NA         9
 99: 10 2008    NA         9
100: 10 2009    NA         9
     id year grade sum_lag_3
id年份等级总和\u滞后\u 3
1:  1 2000     9         9
2:2001年1月9日
3:12002NA 9
4:  1 2003     9        18
5:  1 2004    10        28
6:1 2005 NA 28
7:2006年1月28日
8:  1 2007    11        30
9:1 2008 NA 30
10:  1 2009    10        31

11:2 2000 11 11类似于@chinsoon12,但使用
zoo::rollapply
可以轻松地将
sum
应用于部分窗口

d[!is.na(grade), rs := rollapply(grade, 3, sum, align = "right", partial = TRUE), by = id]
d[ , rs := nafill(rs, type = "locf"), by = id]

#     id year grade sum_lag_3 rs
#  1:  1 2000     9         9  9
#  2:  1 2001    NA         9  9
#  3:  1 2002    NA         9  9
#  4:  1 2003     9        18 18
#  5:  1 2004    10        28 28
#  6:  1 2005    NA        28 28
#  7:  1 2006    NA        28 28
#  8:  1 2007    11        30 30
#  9:  1 2008    NA        30 30
# 10:  1 2009    10        31 31
# 11:  2 2001    11        11 11

data.table::frollsum
中,不支持“
partial
窗口功能,尽管它可以通过使用
adaptive=TRUE
”和自适应滚动函数来实现(请参见
?frollsum
):

arf=函数(n,len)if(len

关于:

我希望能够利用学生的过去和未来进行各种运算,而不仅仅是求和


zoo::rollappy
中,可以将其他函数放入
FUN
参数中。当前,
data.table
等效的
frollapply
,没有
自适应
参数。因此,我在上面用于
frollsum
的方法还不能应用于
frollapply

我认为您需要最后3个分数的滚动总和。在生成数据时,分数和等级需要一起变化。e、 2000年g=9,2001年g=10。。。他们不能独立。年和年级的范围必须相同。。。2000:2009的范围相当于元素PreK,K,1-8。。。或者2001:2004可能是HS 9-12。@Henrik,我添加了一个小样本result@Nate,更重要的是,我希望能够利用学生的过去和未来进行各种操作,而不仅仅是求和。当您有许多组时,设置
setdthreads(1)
可能会加快速度。或者,如果组的长度相等,那么您可以
dcast
一次计算所有数据,而不是按组并行计算。谢谢@chinsoon12,这篇文章不仅仅是关于滚动求和的,而是关于如何在组内执行上下文操作的。此外,虽然您的代码适用于学生1,但在滚动求和的情况下,它不适用于其他学生。但是我很感激你的兴趣。嗨@cachdies,你能告诉我哪个学生错了,还有你的实际公式吗?当然,看第11行,学生2的第一行是31而不是11。Henrik的回答复制了求和示例所需的输出数据。@cachdies我没有得到31,正如你提到的,我得到11。哦,我看错了行,非常抱歉。非常感谢你,你说得对。谢谢Henrik,这个解决方案非常好,我使用
zoo::rollappy
没有问题。使用
FUN=c
购买我想要的东西,但是
width
参数每年都会变化,函数需要调用两次(一次用于过去,一次用于未来)。然而,我不能给它一个正确的答案,因为我没有正确地实现这个函数来获得这些结果。我不知道为什么。
#for example using sum on past grades and mean on future grades
pastFunc <- sum
futureFunc <- mean

students[, {
  vapply(1L:.N, function(n) {
    past <- grade[seq_len(n-1)]
    future <- grade[seq_len(.N-n)+n]
    sum(past, na.rm=TRUE) + mean(future, na.rm=TRUE)
  }, numeric(1L))  
}, id]
d[!is.na(grade), rs := rollapply(grade, 3, sum, align = "right", partial = TRUE), by = id]
d[ , rs := nafill(rs, type = "locf"), by = id]

#     id year grade sum_lag_3 rs
#  1:  1 2000     9         9  9
#  2:  1 2001    NA         9  9
#  3:  1 2002    NA         9  9
#  4:  1 2003     9        18 18
#  5:  1 2004    10        28 28
#  6:  1 2005    NA        28 28
#  7:  1 2006    NA        28 28
#  8:  1 2007    11        30 30
#  9:  1 2008    NA        30 30
# 10:  1 2009    10        31 31
# 11:  2 2001    11        11 11
arf = function(n, len) if(len < n) seq.int(len) else c(seq.int(n), rep(n, len - n))
# if no 'grade' is shorter than n (the full window width), you only need: 
# c(seq.int(n), rep(n, len - n))

d[!is.na(grade) , rs2 := frollsum(grade, n = arf(3, .N), align = "right", adaptive = TRUE),
 by = id]
d[ , rs2 := nafill(rs, type = "locf"), by = id]

#     id year grade sum_lag_3 rs rs2
#  1:  1 2000     9         9  9   9
#  2:  1 2001    NA         9  9   9
#  3:  1 2002    NA         9  9   9
#  4:  1 2003     9        18 18  18
#  5:  1 2004    10        28 28  28
#  6:  1 2005    NA        28 28  28
#  7:  1 2006    NA        28 28  28
#  8:  1 2007    11        30 30  30
#  9:  1 2008    NA        30 30  30
# 10:  1 2009    10        31 31  31
# 11:  2 2001    11        11 11  11