纵向数据集中的累积变量构造

时间:2013-12-05 05:33:24

标签: r

问题: 我想构建一个变量来衡量一年人纵向数据集中的累积工作经验。这个问题适用于各种纵向数据集,许多变量可能以这种累积方式构建(例如,儿童人数,累积教育,累积的假期花费等)

案例: 我有一个大的纵向数据集,其中每一行构成一个人年。该数据集包含数千个人(变量“ID”),这些人在其生命中(变量“年龄”),导致具有大约120万行的数据框。一个变量表示一个人每个人每年工作的月数(变量“工作”)。例如,当丹15岁时,他工作了3个月。

     ID age work
1   Dan  10    0
2   Dan  11    0
3   Dan  12    0
4   Dan  13    0
5   Dan  14    0
6   Dan  15    3
7   Dan  16    5
8   Dan  17    8
9   Dan  18    5
10  Dan  19   12
11 Jeff  20    0
12 Jeff  16    0
13 Jeff  17    0
14 Jeff  18    0
15 Jeff  19    0
16 Jeff  20    0
17 Jeff  21    8
18 Jeff  22   10
19 Jeff  23   12
20 Jeff  24   12
21 Jeff  25   12
22 Jeff  26   12
23 Jeff  27   12
24 Jeff  28   12
25 Jeff  29   12

我现在想构建一个累积工作经验变量,它将年x的值添加到年x + 1。目标是在每个年龄段了解他们在整个运营商中工作了多少个月。该变量应该看起来像“cumwork”。

     ID age work cumwork
1   Dan  10    0       0
2   Dan  11    0       0
3   Dan  12    0       0
4   Dan  13    0       0
5   Dan  14    0       0
6   Dan  15    3       3
7   Dan  16    5       8
8   Dan  17    8      16
9   Dan  18    5      21
10  Dan  19   12      33
11 Jeff  20    0       0
12 Jeff  16    0       0
13 Jeff  17    0       0
14 Jeff  18    0       0
15 Jeff  19    0       0
16 Jeff  20    0       0
17 Jeff  21    8       8
18 Jeff  22   10      18
19 Jeff  23   12      30
20 Jeff  24   12      42
21 Jeff  25   12      54
22 Jeff  26   12      66
23 Jeff  27   12      78
24 Jeff  28   12      90
25 Jeff  29   12     102

糟糕的解决方案:我可以使用以下简单循环构建这样的累积变量:

# Generate test data set
x=data.frame(ID=c(rep("Dan",times=10),rep("Jeff",times=15)),age=c(10:20,16:29),work=c(rep(0,times=5),3,5,8,5,12,rep(0,times=6),8,10,rep(12,times=7)),stringsAsFactors=F)

# Generate cumulative work experience variable
x$cumwork=x$work

for(r in 2:nrow(x)){
  if(x$ID[r]==x$ID[r-1]){
    x$cumwork[r]=x$cumwork[r-1]+x$cumwork[r]
  }
}

但是,我的数据集有120万行,并且每行循环效率非常低,运行此循环需要数小时。有没有出色的程序员有建议如何最有效地构建这种累积量度?

非常感谢提前!

最佳, 圣拉斐尔

1 个答案:

答案 0 :(得分:2)

ave对于这些类型的任务很方便。您要使用的功能是cumsum

x$cumwork <- ave(x$work, x$ID, FUN = cumsum)
x
#      ID age work cumwork
# 1   Dan  10    0       0
# 2   Dan  11    0       0
# 3   Dan  12    0       0
# 4   Dan  13    0       0
# 5   Dan  14    0       0
# 6   Dan  15    3       3
# 7   Dan  16    5       8
# 8   Dan  17    8      16
# 9   Dan  18    5      21
# 10  Dan  19   12      33
# 11 Jeff  20    0       0
# 12 Jeff  16    0       0
# 13 Jeff  17    0       0
# 14 Jeff  18    0       0
# 15 Jeff  19    0       0
# 16 Jeff  20    0       0
# 17 Jeff  21    8       8
# 18 Jeff  22   10      18
# 19 Jeff  23   12      30
# 20 Jeff  24   12      42
# 21 Jeff  25   12      54
# 22 Jeff  26   12      66
# 23 Jeff  27   12      78
# 24 Jeff  28   12      90
# 25 Jeff  29   12     102

但是,考虑到您的数据规模,我还强烈建议使用“data.table”包,它还可以让您访问方便的语法:

library(data.table)
DT <- data.table(x)
DT[, cumwork := cumsum(work), by = ID]