用途
ggplotなどtidyverse系列で列名に対して
繰り返し処理や関数を作成したいことがある。
一筋縄でいけないことが多いので、ここに攻略法をまとめた。
そもそも、mapやfacet、acrossでうまくいくことが多いので、それらでは本当にだめか確認する。
Code
- R / 4.1.0
- Install packages
- tidyverse
テストCode
irisについて、各指標で箱ひげ図を得たいとする
一つならこう書ける
iris %>%
ggplot(aes(x = Species, y = Sepal.Length)) +
geom_boxplot()
ミス Code
あるあるケース
sp_boxplot <- function(var) {
iris %>%
ggplot(aes(x = Species, y = var)) +
geom_boxplot()
}
sp_boxplot("Sepal.Length")
クリアCode
いくつか列挙する出力の図はどれも同じ
aesのパワープレイ
aesは ... を介すると受け取った引数をいい感じに処理するのでうまくいく
sp_boxplot <- function(...) {
iris %>%
ggplot(aes(x=Species,...)) +
geom_boxplot()
}
sp_boxplot(y=Sepal.Length)
aes_string
引数を文字列で与える
""との組合せのみうまくいく
sp_boxplot <- function(var) {
iris %>%
ggplot(aes_string(x = "Species", y = var)) +
geom_boxplot()
}
sp_boxplot("Sepal.Length")
aes_
引数を列名として宣言する
quote と as.name の適用のみうまくいく
sp_boxplot <- function(var) {
iris %>%
ggplot(aes_(x = quote(Species), y = as.name(var))) +
geom_boxplot()
}
sp_boxplot("Sepal.Length")
!!のアンクォートとquo
クォージャーとして与えて、関数内部で!!によってアンクォート
使うときに、quoで包む必要があるがうまくいく
sp_boxplot <- function(var) {
iris %>%
ggplot(aes(x = Species, y = !!var)) +
geom_boxplot()
}
sp_boxplot(quo(Sepal.Length))
enquo
上のquo処理を関数内部に移管したイメージ
使うときに裸の変数名となるがうまくいく
sp_boxplot <- function(var) {
var <- enquo(var)
iris %>%
ggplot(aes(x = Species, y = !!var)) +
geom_boxplot()
}
sp_boxplot(Sepal.Length)
{{ }} curly-curly
enquoの後継としてでてきたらしい
使うときに裸の変数名となるがうまくいく
sp_boxplot <- function(var) {
iris %>%
ggplot(aes(x = Species, y = {{ var }})) +
geom_boxplot()
}
sp_boxplot(Sepal.Length)
データ要素として指定
.data(ここではパイプで渡されたiris)の要素ということを明示的にかく
sp_boxplot <- function(var) {
iris %>%
ggplot(aes(x = Species, y =.data[[ var ]])) +
geom_boxplot()
}
sp_boxplot("Sepal.Length")
結論
公文書に従うなら、
aes()
か{{
でやっていくのが妥当だが、
普段使いには、文字列を渡すことが多いので、文字指定できるものが便利
あとがき
基本的に問題は2つ
- 引数を変数名か、定数(文字列)のどちらで処理するか
- 変数名として、グローバルなのかデータ内の列名なのか
でうまく回らないことが多い。
そもそも、tidyverseの世界で、列名なら裸(クォーテーション無)で指定できているのが便利でありながらも、問題を生む温床である。
気になる人は、「非標準評価(NSE)」や「tidy eval」で検索検索!
また、今回はaesのなかで分けているが、group_byや別のところでも使うことは可能
今回の手法をまとめると
- aes × enquo のグループ
- aes × {{ は aes × enquo と等価
- aes × … は aes × {{ と仕組みは同じだが、関数がどういうふうに使われるべきかによって選択する
- aes_ (aes_q) × quote (ないし ~) のグループ
- aes_string に比べると X$1 などの扱いが楽
- ただし soft-deprecated
- aes_string × 文字列のグループ
- aes_ に比べると X$1 などの扱いがやや面倒
- ただし soft-deprecated
-ただし aes_string の代わりに aes(x = .data[[var]]) などとすれば文字列で変数を指定することが可能
参考文献
公文書1:aes_string と aes_
公文書2:enquo や {{
メモ:dplyr・ggplot2 で {{ }} を使う
読書日記-2017年8月19日 (土)
スペシャルサンクス
本質問は、Rのslackコミュニティ「r-wakalang」にて議論させていただきました。