r - R中的组内操作(不是滚动总和)
问题描述
我有一个数据集,由学生 ( 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))
这是学生 1 的示例:
id year grade
1: 1 2000 9
2: 1 2001 NA
3: 1 2002 NA
4: 1 2003 9
5: 1 2004 10
6: 1 2005 NA
7: 1 2006 NA
8: 1 2007 11
9: 1 2008 NA
我想有一种方法可以访问每个学生之前和未来的成绩以执行不同的操作。例如,添加学生的最后三个成绩。这将产生一个像这样的数据集:
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 NA 11 NA 10
。
同样,对于第二行,“过去”向量将是9
,“未来”向量将是:
NA 9 10 NA NA 11 NA 10
对于第三行,“过去”向量将是9 NA
,“未来”向量将是:
9 10 NA NA 11 NA 10
这是我想要参考以进行不同计算的信息。仅在每个组内的计算,并因上下文而异。最好我想使用data.table
并且不将我的数据重塑为宽格式来做到这一点。
我尝试过执行以下操作:
students[, .SD[, sum_last_3:= ...], by = id]
但我收到一条错误消息,指出此功能尚不可用data.table
(其中 ... 是任何操作的占位符。)。
谢谢你们。
解决方案
这是一个使用frollsum
in的选项data.table
,在进行最后一次观察之前先将其应用于非 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
要解决 OP 的编辑问题:您可以遍历每个学生的每一行以获得过去的向量和未来的向量:
#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]
推荐阅读
- session - 如何使用 FLASK 临时存储上传的文件
- windows - 如果指针的最高位作为符号位会发生什么,有人可以举个例子来解释吗?
- c# - 通过C#在word文档中查找分栏符的位置
- node.js - 如何填充存在于猫鼬地图类型模式中的字段?
- scala - 显式指定泛型 apply 方法的类型有什么影响?
- svg - 用弧线填充 SVG 路径不正确
- php - Checkout-PHP-SDK 中的 PayPal Orders V2 收款人对象因金额错误而失败
- go - 内存没有被释放
- postgresql - 根据 Postgres 中一列(每组)的不同值选择行
- angular - 为什么 [ngClass]="{enable-dot: event.isDisable === false, disable-dot: event.isDisable === true}" 不能在角度工作?