web-dev-qa-db-ja.com

dplyr:mutateコマンド内からfilter、group_byを使用

Yの各値をx(1または2)の対応する条件の平均で割った値(x2 = 1)を含む列をデータテーブルに追加したいと思います。次のデータでは、x = 1yを1.4で割る必要があります。ここで、x = 2yは1で割る必要があります。

dt1 <- data.table(x=c("1","1","1","1","1","1","1","1","1","1","2","2","2","2","2","2","2","2","2","2"),
       x2=c("1","1","2","2","2","2","3","3","3","3","1","1","2","2","2","2","3","3","3","3"), 
       y=c(1.41,1.39,1.9,2.1,0.9,1.1,3.1,2.9,3.9,4.1,0.9,1.1,1.9,2.1,0.9,1.1,3.1,2.9,3.9,4.1))

X * x2 = 1の平均を新しいファイルに書き込むことができます。

mean <- dt1 %>% filter(x2==1) %>% group_by(x) %>% summarise(mean(y))

しかし、正しい値を呼び出すようにコマンドにメッシュ命令する方法を理解することはできません。 dt1%>%mutate(z = y/'平均'への参照)

除算したい値で満たされた新しい列を作成しようと思いましたが、コマンド内からグループ化基準を呼び出す方法をもう一度理解することはできません。

t <- dt1 %>% mutate(T=ifelse(x==1,(filter(x2==1) %>% group_by(x=1) %>%
     summarise(mean(y))),ifelse(x==1,(filter(x2==2) %>% group_by(x=2) %>% 
     summarise(mean(y))),NA)

私はdplyrだけを使うことに固執していませんが、最近それをたくさん使っています。私は最も単純な解決策を受け入れています。

7
Michael_A

試してみてください

  left_join(dt1,
            dt1 %>% 
                 filter(x2==1) %>%
                 group_by(x) %>%
                 summarise(a=mean(y)), by='x') %>%
                 mutate(z=y/a)%>%
                 head()

  #  x x2    y   a         z
  #1 1  1 1.41 1.4 1.0071429
  #2 1  1 1.39 1.4 0.9928571
  #3 1  2 1.90 1.4 1.3571429
  #4 1  2 2.10 1.4 1.5000000
  #5 1  2 0.90 1.4 0.6428571
  #6 1  2 1.10 1.4 0.7857143

またはdata.tableを使用する

library(data.table)
dt2 <- dt1[x2==1,list(a=mean(y)) , by=x]
setkey(dt1, x)
res <- dt1[dt2][,z:=y/a]
head(res)
#   x x2    y   a         z
#1: 1  1 1.41 1.4 1.0071429
#2: 1  1 1.39 1.4 0.9928571
#3: 1  2 1.90 1.4 1.3571429
#4: 1  2 2.10 1.4 1.5000000
#5: 1  2 0.90 1.4 0.6428571
#6: 1  2 1.10 1.4 0.7857143

更新

@aosmithによって提案されたdplyrのよりコンパクトなオプションは

  dt1 %>%
      group_by(x) %>% 
      mutate(a=mean(y[x2==1]), z=y/a)
19
akrun