加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

r – 在列中定义的窗口内的求和

发布时间:2020-12-14 01:38:06 所属栏目:Windows 来源:网络整理
导读:我想为组中的每个data.table行实现N个下一行的和(x),其中N是来自window列的值. 用于生成样本数据的代码: set.seed(100)ids - 1:100x - floor(runif(100,1,100))groups - floor(runif(100,10)) * 10window - floor(runif(100,5))library('data.table')data -
我想为组中的每个data.table行实现N个下一行的和(x),其中N是来自window列的值.

用于生成样本数据的代码:

set.seed(100)
ids <- 1:100
x <- floor(runif(100,1,100))
groups <- floor(runif(100,10)) * 10
window <- floor(runif(100,5))

library('data.table')
data <- data.table(ids,x,groups,window)
setkey(data,ids)

顶行:

ids  x groups window
 1:   3 55     10      4
 2:   9 55     10      1
 3:  13 28     10      1
 4:  16 67     10      3
 5:  26 17     10      3
 6:  30 28     10      2
 7:  36 89     10      2
 8:  38 63     10      3
 9:  42 86     10      3
10:  48 88     10      1
11:  49 21     10      1
12:  59 60     10      3
13:  65 45     10      4
14:  67 46     10      2
15:  88 25     10      4
16:  19 36     20      2

因此,对于第一行,将根据当前行和下一行的总和计算结果值:res = 55 55 28 67 17 = 222

对于组结束的第15行,我只需要当前行的值:res = 25 0(无行)= 25.

这是此逻辑的伪代码:

res <- data[,.(ids,window,result = sum(.SD[.CurrentRow:(.CurrentRow + Window)],na.rm = T)),by = groups,.SDcols = c("x")]

我希望这可以通过data.table实现.我想避免为此循环实现.

解决方法

我不确定如果不迭代所有行就可以这样做,所以这里有一个这样的解决方案:

data[,end := pmin(.I + window,.I[.N]),by = groups][,res := sum(data$x[.I:end]),by = 1:nrow(data)][1:16]
#    ids  x groups window end res
# 1:   3 55     10      4   5 222
# 2:   9 55     10      1   3  83
# 3:  13 28     10      1   4  95
# 4:  16 67     10      3   7 201
# 5:  26 17     10      3   8 197
# 6:  30 28     10      2   8 180
# 7:  36 89     10      2   9 238
# 8:  38 63     10      3  11 258
# 9:  42 86     10      3  12 255
#10:  48 88     10      1  11 109
#11:  49 21     10      1  12  81
#12:  59 60     10      3  15 176
#13:  65 45     10      4  15 116
#14:  67 46     10      2  15  71
#15:  88 25     10      4  15  25
#16:  19 36     20      2  18 173

正如alexis_laz指出的那样,你可以通过计算一次cumsum然后再减去额外的部分来做得更好,从而避免显式迭代行:

data[,res := { cs <- cumsum(x); 
                cs[pmin(1:.N + window,.N)] - shift(cs,fill = 0)},by = groups]

我将尝试解释这里发生的事情:

> res:= {…}在我们的data.table中添加一列,括号内有R计算;
> cs = cumsum(x)计算组内所有行的运行总和;
> cs [pmin(1:.N window,.N)]获取窗口末尾或组最后一行的运行总和的值;
> shift(cs,fill = 0)获取前一行的运行总和;
>两者的差异给出窗口内的项目总和.

由于这个问题有几个可行的答案,我认为值得提供基准测试:

library(microbenchmark)
m <- microbenchmark(
               "tapply(rawr)" = tapplyWay(dd),"data.table(eddi)" = data[,by = 1:nrow(data)],"data.table(alexis_laz)" = data[,res := {cs = cumsum(x); cs[pmin(1:.N + window,by = groups],times = 10)
print(m)
boxplot(m)

10 ^ 5行样本的结果:

Unit: milliseconds
            expr     min     lq      mean    median      uq    max        neval
       tapply(rawr) 2575.12 2761.365 2898.63 2905.77  3041.08  3127.86    10
   data.table(eddi) 1418.92 1570.230 1758.70 1656.14  1977.59  2358.85    10
     dt(alexis_laz) 6.82    7.73     8.78    8.09     10.37    12.37119    10

benchmarking of solutions

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读