purrr 0.1.0を使ってみる(5) invoke

追記:invoke()はバージョン0.2になってだいぶ挙動が変わりました。(参考:purrr 0.2.0を使ってみる - Technically, technophobic.)「一組の引数に複数の関数を適用」は、invoke()ではなくてinvoke_map()です。そのうち書き直しますが今はとりあえずこのままで...


map()はひとつの関数を複数組の引数に適用するものでしたが、invoke()は逆に、一組の引数に複数の関数を適用します。

ドキュメントに載ってる例はこんな感じです。

# 関数のリストをつくる
middle <- list(m1 = mean, m2 = median)

# 関数のリストを適用
middle %>% invoke(rcauchy(100))
#> $m1
#> [1] -3.370418
#> 
#> $m2
#> [1] 0.165954

map()のようにinvoke_dbl()invoke_chr()のように型を指定するバージョンもあります。

middle %>% invoke_dbl(rcauchy(100))
#>         m1         m2 
#> -0.6844287 -0.1419248 

で、どういう場合に便利かなと考えてたんですが、たとえば、同じデータに対して色んなパターンのグラフを描くときとか?

# ggplotオブジェクト
g <- ggplot(mpg, aes(class))

# geomを足し合わせる関数をつくる。「. %>%」で関数ができる
draw_bar  <- . %>% { . + geom_bar() }
draw_dens <- . %>% { . + geom_density() }
draw_dot  <- . %>% { . + geom_dotplot() }

# 関数のリストをgに適用
plotlist <- list(draw_bar, draw_dens, draw_bar) %>%
  invoke(g)

lift(gridExtra::grid.arrange)(plotlist)

f:id:yutannihilation:20151110004215p:plain:w400

ちなみに、@hoxo_m親分に教えてもらいましたけどpartial().first引数にFALSEを指定すると後ろに回してくれるので、関数のリストはこんな風にも書けるみたいです。

list(geom_bar(), geom_density(), geom_dotplot()) %>%
    map(~ partial(`+`, ., .first = FALSE))