在长格式数据集中创建%更改列

时间:2015-10-20 18:01:43

标签: r vectorization

我试图找到一种最有效的方法来计算长数据集中从一个时段到下一个时段的%变化。以下是格式示例:

set.seed(1234)
df <- data.frame(Date=c(2001:2010),CompanyA=rnorm(10,0,1),CompanyB=rnorm(10,1,2),CompanyC=rnorm(10,-1,2))
longdf <- melt(df,id.vars="Date")

结果表如下所示:

   Date variable       value
1  2001 CompanyA -1.20706575
2  2002 CompanyA  0.27742924
3  2003 CompanyA  1.08444118
4  2004 CompanyA -2.34569770
5  2005 CompanyA  0.42912469
6  2006 CompanyA  0.50605589
7  2007 CompanyA -0.57473996
8  2008 CompanyA -0.54663186
9  2009 CompanyA -0.56445200
10 2010 CompanyA -0.89003783
11 2001 CompanyB  0.04561460
12 2002 CompanyB -0.99677289
13 2003 CompanyB -0.55250779
14 2004 CompanyB  1.12891763
15 2005 CompanyB  2.91898812
16 2006 CompanyB  0.77942901
17 2007 CompanyB -0.02201901
18 2008 CompanyB -0.82239083
19 2009 CompanyB -0.67434336
20 2010 CompanyB  5.83167036
21 2001 CompanyC -0.73182356
22 2002 CompanyC -1.98137179
23 2003 CompanyC -1.88109574
24 2004 CompanyC -0.08082112
25 2005 CompanyC -2.38744049
26 2006 CompanyC -3.89640982
27 2007 CompanyC  0.14951144
28 2008 CompanyC -3.04731145
29 2009 CompanyC -1.03027660
30 2010 CompanyC -2.87189720

我想要的是添加第4列,显示每个公司从一个时期到下一个时期的得分百分比变化。

我可以使用以下代码创建此列:

for (c in unique(longdf$variable)) {
  for (y in unique(longdf$Date)[-1]){
longdf$change[longdf$variable==c & longdf$Date==y] <- (longdf[longdf$variable==c & longdf$Date==y,"value"]-longdf[longdf$variable==c & longdf$Date==y-1,"value"])/abs(longdf[longdf$variable==c & longdf$Date==y-1,"value"])
  }
}
longdf

结果表如下所示:

   Date variable       value       change
1  2001 CompanyA -1.20706575           NA
2  2002 CompanyA  0.27742924   1.22983772
3  2003 CompanyA  1.08444118   2.90889283
4  2004 CompanyA -2.34569770  -3.16304743
5  2005 CompanyA  0.42912469   1.18294117
6  2006 CompanyA  0.50605589   0.17927471
7  2007 CompanyA -0.57473996  -2.13572427
8  2008 CompanyA -0.54663186   0.04890578
9  2009 CompanyA -0.56445200  -0.03259990
10 2010 CompanyA -0.89003783  -0.57681757
11 2001 CompanyB  0.04561460           NA
12 2002 CompanyB -0.99677289 -22.85205787
13 2003 CompanyB -0.55250779   0.44570343
14 2004 CompanyB  1.12891763   3.04326103
15 2005 CompanyB  2.91898812   1.58565198
16 2006 CompanyB  0.77942901  -0.73297972
17 2007 CompanyB -0.02201901  -1.02825018
18 2008 CompanyB -0.82239083 -36.34912573
19 2009 CompanyB -0.67434336   0.18002082
20 2010 CompanyB  5.83167036   9.64792433
21 2001 CompanyC -0.73182356           NA
22 2002 CompanyC -1.98137179  -1.70744467
23 2003 CompanyC -1.88109574   0.05060941
24 2004 CompanyC -0.08082112   0.95703509
25 2005 CompanyC -2.38744049 -28.53981030
26 2006 CompanyC -3.89640982  -0.63204479
27 2007 CompanyC  0.14951144   1.03837159
28 2008 CompanyC -3.04731145 -21.38179426
29 2009 CompanyC -1.03027660   0.66190637
30 2010 CompanyC -2.87189720  -1.78750114

上述代码的问题似乎效率极低。我正在使用的数据框将有数百万行。是否有更有效的方法为longform数据创建%更改列?

1 个答案:

答案 0 :(得分:1)

使用dplyr,您可以在lag因素分组后使用variable功能:

library(dplyr)

longdf %>%
  group_by(variable) %>%
  mutate(change = value / lag(value) - 1)

# Source: local data frame [30 x 4]
# Groups: variable [3]
# 
#     Date variable      value      change
#    (int)   (fctr)      (dbl)       (dbl)
# 1   2001 CompanyA -1.2070657          NA
# 2   2002 CompanyA  0.2774292 -1.22983772
# 3   2003 CompanyA  1.0844412  2.90889283
# 4   2004 CompanyA -2.3456977 -3.16304743
# 5   2005 CompanyA  0.4291247 -1.18294117
# 6   2006 CompanyA  0.5060559  0.17927471
# 7   2007 CompanyA -0.5747400 -2.13572427
# 8   2008 CompanyA -0.5466319 -0.04890578
# 9   2009 CompanyA -0.5644520  0.03259990
# 10  2010 CompanyA -0.8900378  0.57681757
# ..   ...      ...        ...         ...