2017-08-03 8 views
3

複数のIDで1つのデータフレーム内のデータに対してローリング平均を計算したいと考えています。私の下の私の例のデータセットを見てください。インデックスでデータベースにローリング平均を適用する

date <- as.Date(c("2015-02-01", "2015-02-02", "2015-02-03", "2015-02-04", 
      "2015-02-05", "2015-02-06", "2015-02-07", "2015-02-08", 
      "2015-02-09", "2015-02-10", "2015-02-01", "2015-02-02", 
      "2015-02-03", "2015-02-04", "2015-02-05", "2015-02-06", 
      "2015-02-07", "2015-02-08", "2015-02-09", "2015-02-10")) 
index <- c("a","a","a","a","a","a","a","a","a","a", 
      "b","b","b","b","b","b","b","b","b","b") 
x <- runif(20,1,100) 
y <- runif(20,50,150) 
z <- runif(20,100,200) 

df <- data.frame(date, index, x, y, z) 

x、y、zのローリング平均をaとbで計算したいと思います。

私は以下を試みましたが、エラーが発生しています。

test <- tapply(df, df$index, FUN = rollmean(df, 5, fill=NA)) 

エラー:

Error in xu[k:n] - xu[c(1, seq_len(n - k))] : 
    non-numeric argument to binary operator 

...インデックスが文字であるという事実に問題があるようだが、私は手段を計算するためにそれを必要とする

答えて

2

これは、ライブラリdplyrzooを使用してトリックを行うべき:

library(dplyr) 
library(zoo) 

df %>% 
    group_by(index) %>% 
    mutate(x_mean = rollmean(x, 5, fill = NA), 
     y_mean = rollmean(y, 5, fill = NA), 
     z_mean = rollmean(z, 5, fill = NA)) 

あなたは可能性がありprobaこれは、mutate_eachやその他の形式のmutateを使用してさらに整理してください。

ます。また、このようなalign = "right"na.pad = TRUE

3

1のように、あなたのニーズに合わせてrollmean内の引数を変更することができます)AVEむしろtapplyよりaveを試してみて、それが唯一の関心の列の上に適用されていることを確認し、すなわち与え列3、4、5

roll <- function(x) rollmean(x, 5, fill = NA) 
cbind(df[1:2], lapply(df[3:5], function(x) ave(x, df$index, FUN = roll))) 

  date index  x   y  z 
1 2015-02-01  a  NA  NA  NA 
2 2015-02-02  a  NA  NA  NA 
3 2015-02-03  a 66.50522 127.45650 129.8472 
4 2015-02-04  a 61.71320 123.83633 129.7673 
5 2015-02-05  a 56.56125 120.86158 126.1371 
6 2015-02-06  a 66.13340 119.93428 127.1819 
7 2015-02-07  a 59.56807 105.83208 125.1244 
8 2015-02-08  a 49.98779 95.66024 139.2321 
9 2015-02-09  a  NA  NA  NA 
10 2015-02-10  a  NA  NA  NA 
11 2015-02-01  b  NA  NA  NA 
12 2015-02-02  b  NA  NA  NA 
13 2015-02-03  b 55.71327 117.52219 139.3961 
14 2015-02-04  b 54.58450 107.81763 142.6101 
15 2015-02-05  b 50.48102 104.94084 136.3167 
16 2015-02-06  b 37.89790 95.45489 135.4044 
17 2015-02-07  b 33.05259 85.90916 150.8673 
18 2015-02-08  b 49.91385 90.04940 147.1376 
19 2015-02-09  b  NA  NA  NA 
20 2015-02-10  b  NA  NA  NA 

2)byを別の方法で使用します。 roll2が1つのグループを処理した場合、byはそれを各グループに適用してbyリストを作成し、do.call("rbind", ...)はそれを戻します。

与える
roll2 <- function(x) cbind(x[1:2], rollmean(x[3:5], 5, fill = NA)) 
do.call("rbind", by(df, df$index, roll2)) 

  date index  x   y  z 
a.1 2015-02-01  a  NA  NA  NA 
a.2 2015-02-02  a  NA  NA  NA 
a.3 2015-02-03  a 66.50522 127.45650 129.8472 
a.4 2015-02-04  a 61.71320 123.83633 129.7673 
a.5 2015-02-05  a 56.56125 120.86158 126.1371 
a.6 2015-02-06  a 66.13340 119.93428 127.1819 
a.7 2015-02-07  a 59.56807 105.83208 125.1244 
a.8 2015-02-08  a 49.98779 95.66024 139.2321 
a.9 2015-02-09  a  NA  NA  NA 
a.10 2015-02-10  a  NA  NA  NA 
b.11 2015-02-01  b  NA  NA  NA 
b.12 2015-02-02  b  NA  NA  NA 
b.13 2015-02-03  b 55.71327 117.52219 139.3961 
b.14 2015-02-04  b 54.58450 107.81763 142.6101 
b.15 2015-02-05  b 50.48102 104.94084 136.3167 
b.16 2015-02-06  b 37.89790 95.45489 135.4044 
b.17 2015-02-07  b 33.05259 85.90916 150.8673 
b.18 2015-02-08  b 49.91385 90.04940 147.1376 
b.19 2015-02-09  b  NA  NA  NA 
b.20 2015-02-10  b  NA  NA  NA 

3)広いフォーム別のアプローチは、プレーンrollmeanはそれを行います。その場合には広い形に長いフォームからdfを変換することです。

rollmean(read.zoo(df, split = 2), 5, fill = NA) 

与える:日付が両方のグループで同じであるため

   x.a  y.a  z.a  x.b  y.b  z.b 
2015-02-01  NA  NA  NA  NA  NA  NA 
2015-02-02  NA  NA  NA  NA  NA  NA 
2015-02-03 66.50522 127.45650 129.8472 55.71327 117.52219 139.3961 
2015-02-04 61.71320 123.83633 129.7673 54.58450 107.81763 142.6101 
2015-02-05 56.56125 120.86158 126.1371 50.48102 104.94084 136.3167 
2015-02-06 66.13340 119.93428 127.1819 37.89790 95.45489 135.4044 
2015-02-07 59.56807 105.83208 125.1244 33.05259 85.90916 150.8673 
2015-02-08 49.98779 95.66024 139.2321 49.91385 90.04940 147.1376 
2015-02-09  NA  NA  NA  NA  NA  NA 
2015-02-10  NA  NA  NA  NA  NA  NA 

これは動作します。日付が異なると、NAを導入する可能性があり、rollmeanはそれらを処理できません。その場合には

rollapply(read.zoo(df, split = 2), 5, mean, fill = NA) 

注意を使用します。を入力し、それが再現可能な、我々は最初のset.seedを発行する必要があります作るために、その定義に乱数を使用しているため。これを使用しました:

set.seed(123) 
date <- as.Date(c("2015-02-01", "2015-02-02", "2015-02-03", "2015-02-04", 
      "2015-02-05", "2015-02-06", "2015-02-07", "2015-02-08", 
      "2015-02-09", "2015-02-10", "2015-02-01", "2015-02-02", 
      "2015-02-03", "2015-02-04", "2015-02-05", "2015-02-06", 
      "2015-02-07", "2015-02-08", "2015-02-09", "2015-02-10")) 
index <- c("a","a","a","a","a","a","a","a","a","a", 
      "b","b","b","b","b","b","b","b","b","b") 
x <- runif(20,1,100) 
y <- runif(20,50,150) 
z <- runif(20,100,200) 
関連する問題