快速矩阵子集计算

时间:2019-11-26 11:45:55

标签: r performance indexing mean

我有一个按ID,开始(某些ID具有多个起点)和年份排序的大约一百万行的数据集,并想计算两个变量的5年平均值(从5开始)。每个ID中包含var1和var2)。

例如,var1的5年平均值为243.2 =(47 + 99 + 1000 + 60 + 10)/ 5和46 =(133 + 13 + 88-50)/ 4(4年平均值数据范围限制)分别针对id == 1和id == 2。有什么可以替代下面的代码吗?

样本数据:

id  start  year  var1  var2
1   2005   2000  500   333
1   2005   2001  10    444
1   2005   2002  60    555
1   2005   2003  1000  99
1   2005   2004  99    15
1   2005   2005  47    0
1   2005   2006  180   NA
2   2003   2000  -50   NA
2   2003   2001  88    17
2   2003   2002  13    77
2   2003   2003  133   55
2   2003   2004  86    30
2   2003   2005  10    100

代码:

  # Find startpoint per id
  idx <- which(year==start)

  # Compute 
  sapply(idx, function(x){
    with( dat, c(id[x],
                  start[x],
                  mean( var1[id==id[x] & (year>=max(2000,year[x]-4) & year<=year[x])], na.rm=T ),
                  mean( var2[id==id[x] & (year>=max(2000,year[x]-4) & year<=year[x])], na.rm=T )) )
  })

基于以下公认的解决方案进行了调整的版本:

data <- setDT(data)[, .(var1_avg5 = mean(var1[year > start-5 & year <= start], na.rm = T),
                        var2_avg5 = mean(var2[year > start-5 & year <= start], na.rm = T),
                        start, 
                        year), 
               by=id]

2 个答案:

答案 0 :(得分:1)

这是您想要的吗?

library(data.table)

# data simulation
n = 7e6
data = data.table(
  id = sample(seq(1,n / 7), n, replace = TRUE),
  year = sample(seq(2000, 2010), n, replace = TRUE),
  var1 = rnorm(n),
  var2 = rexp(n)
)
data[, start := max(year) - sample(c(1,2), 1), id]


# calculation
t1 = Sys.time()
data = data[year > start - 5 & year <= start]
data[, .(var1 = mean(var1, na.rm = T),
         var2 = mean(var2, na.rm = T)), id]
t2 = Sys.time()
print(t2 - t1)

Time difference of 0.511766 secs

答案 1 :(得分:0)

考虑通过client = python_http_client.Client(host='https://www.google.com', timeout=30) 传递的zoo(众所周知的时间序列数据包)中的rollmean

tapply

但是,您表示根据数据可用性,更动态地需要运行多种滚动方式。因此,请考虑使用library(zoo) ... df$var1_five_yr_avg <- with(df, unlist(tapply(var1, id, function(x) rollmeanr(x, k=5, fill=NA)))) df$var2_five_yr_avg <- with(df, unlist(tapply(var2, id, function(x) rollmeanr(x, k=5, fill=NA)))) df # id start year var1 var2 var1_five_yr_avg var2_five_yr_avg # 1 1 2005 2000 500 333 NA NA # 2 1 2005 2001 10 444 NA NA # 3 1 2005 2002 60 555 NA NA # 4 1 2005 2003 1000 99 NA NA # 5 1 2005 2004 99 15 333.8 289.2 # 6 1 2005 2005 47 0 243.2 222.6 # 7 1 2005 2006 180 NA 277.2 NA # 8 2 2003 2000 -50 NA NA NA # 9 2 2003 2001 88 17 NA NA # 10 2 2003 2002 13 77 NA NA # 11 2 2003 2003 133 55 NA NA # 12 2 2003 2004 86 30 54.0 NA # 13 2 2003 2005 10 100 66.0 55.8 逻辑运行多个滚动方式。

ifelse