elsur.jpn.org >

« 読了:Richarson, et al. (2018) 共変量のある多項回帰モデルを、共変量で予測した曝露確率の逆数でウェイティングして共変量なしで済ませる | メイン | 読了:Qi, Wang, Li, & Gao (2018) 機械学習におけるデータの「汚れ」の影響 »

2018年5月 5日 (土)

 これは私による私のためのメモでございます。まあ、そう云ってしまえば全部そうなんですけど。

 Rのdplyrパッケージにはscoped variantsと呼ばれる関数(dplyr風にいうと、verb)がある。使い方がいまいちわかっておらず、毎回イライラするので、きちんと調べてみることにした。

 scoped variantsを持つverbは、mutate(), transmute(), summarize(), filter(), group_by(), rename(), select(), arrange()の8つ。
 verbのscoped variantsには all, at, ifの三種類がある。mutate()の場合には、mutate_all(), mutate_at(), mutate_if()があるわけだ。

mutate(), transmute(), summarize()
 以下、変数変換のverbであるmutate()を例に、3つのvariantsについて使い方をメモしておく。transmute(), summarize()も同様である。

_all() variant
 mutate_all(.tbl, .funs, ...)
 オブジェクト.tblに含まれているすべての変数について、.funsに指定した変換を行う。

 さて、このfuns()の書式がちょっと不思議である(そうそう、ここでいつもとまどうのだ)。
 funs(..., .args=list())
 ...に関数を指定する。たとえば変数の平均を求めるとして、...のとこには単にmeanと書いてもいいし、関数名の文字列"mean"と書いてもいいし、mean(., na.rm=T)という風に書いてもいい。しかし無名関数はだめ。function(x) mean(., na.rm=T)というのは許してもらえない。

 funsの中に複数の関数をならべてもよい。ただし、文字列ベクトルは受け取れない。つまり、funs("min", "max")はありだがfuns(c("min", "max"))はなし。後者の場合にはfuns_(c("min", "max"))と書く。
 複数の関数を並べるとなにが起きるかというと...
 data.frame(v1=1:10, v2=1:10) %>% mutate_all(funs(min, max))
 返ってくるデータフレームには、v1, v2, v1_min, v1_max, v2_min, v2_maxが含まれる。接尾辞("min", "max")は勝手につけてくれるけど、明示的にfuns(a =min, b=max)とすれば"a", "b"になる。

_at() variant
 mutate_at(.tbl, .vars, .funs, ...)
 mutate_all()との違いは、.varsに指定した変数だけについて変換が行われるという点である。

 vars()の書式は
 vars(...)
 ...で変数名を指定する。select()と同じように書ける。よってvars(starts_with("hoge"))という風に書ける。

_if() variant
 mutate_if(.tbl, .predicate, .funs, ...)
 mutate_all()との違いは、.predicateに該当する変数だけについて変換が行われるという点である。(そうか... 引数.varsはないのか...)

 試してみたところ、どうやら引数.predicateを無名関数にするのはありらしい。mutate_if(df, function(x) is.numeric(x), as.factor)とか。

 さて、他のverbだとどうなるか。特にわかりにくいのは、引数.funsの意味である。mutate(), transmute(), summarize()は変数変換のverbなので、引数.funsの役割ははっきりしている。他のverbではなにを意味するのか。

filter()
 filter()のscoped variantsは引数.funsを持たない。かわりに引数.vars_predicateを持つ。この引数はall_vars(expr)かany_vars(expr)で生成する。exprは条件式。
 わけわかんなくなって参りましたが、たとえば
 filter_all(df, all_vars(. > 100))
とすると、すべての変数の値が100より大である行が選択される、ということである。

group_by()
 引数.funsを持つ。グループ化変数が変数変換の引数を持つというのも変な感じだが、これはgroup_by()のあとにmutate()するのと同じことになる。たとえば
 group_by_all(df, as.factor)
とすると、すべての変数でのグループ化が行われ、かつそのグループがfactorになる。

select(), rename()
 引数.funsを持つが、これは変数に適用する関数ではなく、変数名に適用する関数となる。ここが直観に反するんだけど、rename()のscoped variantsだけでなく、select()のscoped variantsも引数.funsを持つのである。たとえば
 select_all(df, toupper)
とすると、全ての変数が大文字になるんじゃなくて、全ての変数名が大文字になる。(あれ? じゃあ結局、select_all()とrename_all()って全く同じなの?)

 試してみたところ、無名関数が使える。たとえば
 select_all(df, function(x) paste0("hoge", x))
とすると、全変数の変数名の頭に"hoge"がつく。
 ということはだ。たとえば質問紙調査のデータで、Q1S1, Q2S2, ... に5件法の回答(1,2,3,4,5)がはいっている。これを反転した変数 nImage1, nImage2, ...と、T2Bのとき1になるダミー変数bImage1, bImage2, ..をつくりたい。この場合、
 df %>%
  mutate_at(vars(starts_with("Q1S"), funs(n = 6 - ., b = if_else(. %in% 1:2, 1, 0))) %>%
  rename_at(vars(starts_with("Q1S"), sub("Q1S(.+)_(.+)", "\\2Image_\\1", .))
とすればいいわけ? それとも
  rename_at(vars(starts_with("Q1S"), function(x) sub("Q1S(.+)_(.+)", "\\2Image_\\1", x))
と無名関数にするわけ? 試してみたところ、後者のみOKであった。

arrange()
 引数.funsを持つ。たとえば
 arrange_all(df, desc)
とすると、左の変数から順に降順になる。

雑記:データ解析 - 覚え書き: Rのdplyrパッケージのhogehoge_{all, if, at} 動詞の使い方

rebuilt: 2020年4月20日 18:53
validate this page