在两个因子水平或时间点滚动加权平均值

问题描述 投票:2回答:1

我想创造阿尔法,布拉沃和查理滚动2季度平均(和很多其他变数。研究带我去动物园和润滑包,但似乎总是回到一个变量或分组内滚动

set.seed(123)

dates <-  c("Q4'15", "Q1'16", "Q2'16","Q3'16", "Q4'16", "Q1'17", "Q2'17" ,"Q3'17", "Q4'17","Q1'18")

df <- data.frame(dates = sample(dates, 100,  replace = TRUE, prob=rep(c(.03,.07,.03,.08, .05),2)), 
                           alpha = rnorm(100, 5), bravo = rnorm(100, 10), charlie = rnorm(100, 15))

我在寻找类似的东西

x <- df %>% mutate_if(is.numeric, funs(rollmean(., 2, align='right', fill=NA)))

期望的结果:横跨“Q4'15”&“Q1'16”,“Q1'16”&“Q2'16”等的加权平均值用于数据的每一列(α,喝彩,查理)。不找的平均配对季度平均值。

这里是平均会是怎样的Q4'15&“Q1'16”时间点

df %>% filter(dates %in% c("Q4'15", "Q1'16")) %>%  select(-dates) %>% summarise_all(mean)
r dplyr weighted summarize rolling-computation
1个回答
3
投票

我喜欢data.table对于这一点,我要给你一个解决方案,但有可能是一个更优雅的一个。以下是我有:

Data

现在,作为data.table

R> suppressMessages(library(data.table))
R> set.seed(123)
R> datesvec <- c("Q4'15", "Q1'16", "Q2'16","Q3'16", "Q4'16",
+               "Q1'17", "Q2'17" ,"Q3'17", "Q4'17","Q1'18")
R> df <- data.table(dates = sample(dates, 100,  replace = TRUE,
+                                 prob=rep(c(.03,.07,.03,.08, .05),2)),
+                  alpha = rnorm(100, 5),
+                  bravo = rnorm(100, 10),
+                  charlie = rnorm(100, 15))
R> df[ , ind := which(datesvec==dates), by=dates]
R> setkey(df, ind)  # optional but may as well
R> head(df)
   dates   alpha    bravo charlie ind
1: Q4'15 5.37964 11.05271 14.4789   1
2: Q4'15 7.05008 10.36896 15.0892   1
3: Q4'15 4.29080 12.12845 13.6047   1
4: Q4'15 5.00576  8.93667 13.3325   1
5: Q4'15 3.53936  9.81707 13.6360   1
6: Q1'16 3.45125 10.56299 16.0808   2
R> 

这里的关键是,我们需要恢复/保持你宿舍,你的数据表示不具有时间排序。

Average by quarter

这是很容易与data.table

R> ndf <- df[ ,
+           .(qtr=head(dates,1),          # label of quarter
+             sa=sum(alpha),              # sum of a in quarter
+             sb=sum(bravo),              # sum of b in quarter
+             sc=sum(charlie),            # sum of c in quarter
+             n=.N),                      # number of observations
+           by=ind]
R> ndf
    ind   qtr      sa       sb       sc  n
 1:   1 Q4'15 25.2656  52.3039  70.1413  5
 2:   2 Q1'16 65.8562 132.6650 192.7921 13
 3:   3 Q2'16 10.3422  17.8061  31.3404  2
 4:   4 Q3'16 84.6664 168.1914 256.9010 17
 5:   5 Q4'16 41.3268  87.8253 139.5873  9
 6:   6 Q1'17 42.6196  85.4059 134.8205  9
 7:   7 Q2'17 76.5190 162.0784 241.2597 16
 8:   8 Q3'17 42.8254  83.2483 127.2600  8
 9:   9 Q4'17 68.1357 133.5794 198.1920 13
10:  10 Q1'18 37.0685  78.4107 120.2808  8
R> 

Lag those averages once

R> ndf[, `:=`(psa=shift(sa),               # previous sum of a
+            psb=shift(sb),               # previous sum of b
+            psc=shift(sc),                # previous sum of c
+            pn=shift(n))]                # previous nb of obs
R> ndf
    ind   qtr      sa       sb       sc  n     psa      psb      psc pn
 1:   1 Q4'15 25.2656  52.3039  70.1413  5      NA       NA       NA NA
 2:   2 Q1'16 65.8562 132.6650 192.7921 13 25.2656  52.3039  70.1413  5
 3:   3 Q2'16 10.3422  17.8061  31.3404  2 65.8562 132.6650 192.7921 13
 4:   4 Q3'16 84.6664 168.1914 256.9010 17 10.3422  17.8061  31.3404  2
 5:   5 Q4'16 41.3268  87.8253 139.5873  9 84.6664 168.1914 256.9010 17
 6:   6 Q1'17 42.6196  85.4059 134.8205  9 41.3268  87.8253 139.5873  9
 7:   7 Q2'17 76.5190 162.0784 241.2597 16 42.6196  85.4059 134.8205  9
 8:   8 Q3'17 42.8254  83.2483 127.2600  8 76.5190 162.0784 241.2597 16
 9:   9 Q4'17 68.1357 133.5794 198.1920 13 42.8254  83.2483 127.2600  8
10:  10 Q1'18 37.0685  78.4107 120.2808  8 68.1357 133.5794 198.1920 13
R> 

Average over current and previous quarter

R> ndf[is.finite(psa),                     # where we have valid data
+     `:=`(ra=(sa+psa)/(n+pn),            # total sum / total n == avg
+          rb=(sb+psb)/(n+pn),
+          rc=(sc+psc)/(n+pn))]
R> ndf[,c(1:2, 11:13)]
    ind   qtr      ra       rb      rc
 1:   1 Q4'15      NA       NA      NA
 2:   2 Q1'16 5.06233 10.27605 14.6074
 3:   3 Q2'16 5.07989 10.03141 14.9422
 4:   4 Q3'16 5.00045  9.78935 15.1706
 5:   5 Q4'16 4.84589  9.84680 15.2496
 6:   6 Q1'17 4.66369  9.62395 15.2449
 7:   7 Q2'17 4.76554  9.89937 15.0432
 8:   8 Q3'17 4.97268 10.22195 15.3550
 9:   9 Q4'17 5.28386 10.32513 15.4977
10:  10 Q1'18 5.00972 10.09476 15.1654
R> 

采取的事实,即在两个季度总和除以观察总数除以优点是相同的两个季度的平均值。 (这反映了以下矿井的早期thinko编辑)。

Spot check

我们可以用data.table的选择功能来计算两个手的那些行的,我挑那些指数<1,2><4,5>这里:

R> df[ ind <= 2, .(a=mean(alpha), b=mean(bravo), c=mean(charlie))]
         a      b       c
1: 5.06233 10.276 14.6074
R> df[ ind == 4 | ind == 5, .(a=mean(alpha), b=mean(bravo), c=mean(charlie))]
         a      b       c
1: 4.84589 9.8468 15.2496
R> 

这平底锅了罚款,并且该方法应该很容易扩展到数百万的感谢行至data.table

PS: All in One

至于你提到的管道等,你可以用链data.table操作写了这一切。不是我喜欢的风格,但有可能。下面创建一个完全一样的出来而没有创建ndf临时如上:

## All in one
df[ , ind := which(datesvec==dates), by=dates][
   ,
    .(qtr=head(dates,1),          # label of quarter
      sa=sum(alpha),              # sum of a in quarter
      sb=sum(bravo),              # sum of b in quarter
      sc=sum(charlie),            # sum of c in quarter
      n=.N),                      # number of observations
    by=ind][
   ,
    `:=`(psa=shift(sa),               # previous sum of a
         psb=shift(sb),               # previous sum of b
         psc=shift(sc),                # previous sum of c
         pn=shift(n))][
    is.finite(psa),                     # where we have valid data
    `:=`(ra=(sa+psa)/(n+pn),            # total sum / total n == avg
         rb=(sb+psb)/(n+pn),
         rc=(sc+psc)/(n+pn))][
    ,c(1:2, 11:13)][]
© www.soinside.com 2019 - 2024. All rights reserved.