【问题标题】:R: avoiding "for": running sum with changing beginning in panel dataR:避免“for”:在面板数据中改变开头运行总和
【发布时间】:2014-12-18 16:51:58
【问题描述】:

这里的主要问题是如何在将函数应用于面板子集时避免循环。

我想要这样的数据:

id  year   w    pdvw
1   1930   2    10
1   1940   3    15.5
1   1950   5    23.5
1   1960   7.5  27.5
1   1970   11   NA
1   1980   9    NA
2   1930   NA   NA
2   1940   NA   NA
2   1950   1    10
2   1960   3    17
2   1970   6    NA
2   1980   8    NA

实际数据要多得多,而且稍微复杂一些。我正在尝试从其他列中生成最后一列(pdvw)。 pdvw 是 w 的下一个(及时)三个条目的总和(例如 pdvw[1] = 2+3+5)。我很容易写

for(t in seq(from=1930,to=1960,by=10)){
  for(i in c(1,2)){
    if(is.na(w[id==i & t==year])==FALSE){
      pdvw[id==i & year==t] = sum(w[id==i & t<=year & year<=t+21])
    }
  }
}

我的应用程序不是很大(年份为 20 个值,id 为 150 个值),但我被告知要尽可能避免此类循环,所以我想看看是否有更好的方法。我不太关心多年来避免循环,因为 20 次迭代可以忽略不计,但我确实想学习成为更好的编码器。我认为 by 可能会有所帮助,但我不确定具体是什么。

我上面的解决方案利用(可能很危险)这样一个事实,即 w 的缺失值永远不会出现在非缺失值之前(仅仅是历史的巧合——因此,“可能是危险的”)。我包括了缺失值,因为任何解决方案都可以处理这样一个事实,即一旦给定面板的数据可用,就必须开始 pdvw 计算,这一点很重要。

【问题讨论】:

  • 可能有用Q&A

标签: r for-loop


【解决方案1】:

您不需要for 循环,但可以使用filter

transform(dat, pdvw2 = ave(w, id, FUN = function(x) c(filter(x, c(1, 1, 1))[-1], NA)))

dat 是您的数据框的名称。

结果:

   id year    w pdvw pdvw2
1   1 1930  2.0 10.0  10.0
2   1 1940  3.0 15.5  15.5
3   1 1950  5.0 23.5  23.5
4   1 1960  7.5 27.5  27.5
5   1 1970 11.0   NA    NA
6   1 1980  9.0   NA    NA
7   2 1930   NA   NA    NA
8   2 1940   NA   NA    NA
9   2 1950  1.0 10.0  10.0
10  2 1960  3.0 17.0  17.0
11  2 1970  6.0   NA    NA
12  2 1980  8.0   NA    NA

【讨论】:

  • @randy 目前的做法是独立应用于不同的ids。
  • 感谢您的解决方案。它确实产生了所需的输出。我遇到的主要问题是它需要一些手动微调([-1],NA)才能将矢量分量放在正确的位置,这可能是错误的来源。我认为lead() 可能会更好,但我是新手。
  • @randy filter 方法非常有效。当然,您必须选择自己喜欢的方式来生成结果。
【解决方案2】:

dplyr 的一个选项是:

library(dplyr)
df %>%                                       # take the data frame
  group_by(id) %>%                           # group the data by "id"
  mutate(pdvw2 = w + lead(w) + lead(w,2))    # compute a new column with the sum of 3 values. "lead" takes the next value
#Source: local data frame [12 x 5]
#Groups: id
#
#   id year    w pdvw pdvw2
#1   1 1930  2.0 10.0  10.0
#2   1 1940  3.0 15.5  15.5
#3   1 1950  5.0 23.5  23.5
#4   1 1960  7.5 27.5  27.5
#5   1 1970 11.0   NA    NA
#6   1 1980  9.0   NA    NA
#7   2 1930   NA   NA    NA
#8   2 1940   NA   NA    NA
#9   2 1950  1.0 10.0  10.0
#10  2 1960  3.0 17.0  17.0
#11  2 1970  6.0   NA    NA
#12  2 1980  8.0   NA    NA

(其中df 是您的数据框的名称)

【讨论】:

  • 对于阅读本文的任何其他人,dplyr::mutate() 的这种用法与使用 plyr 包中的 mutate() 和(在此应用程序中)base 中的 transform() 相同。
  • 如果你自己使用了变异,是的。但我也使用 group_by 将函数应用于每组 id。如果 w 中的数据具有较少的 NA 条目,您会注意到差异。看看这个。 @兰迪
猜你喜欢
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-19
  • 2021-05-09
相关资源
最近更新 更多