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