タイトルのまんまです。

関数の定義

ざっくり作ってみました。

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
d_quant <- function(x, var, probs = seq(0, 1, 0.25)) {
  if(length(var)!=1){
    stop("length(var) must 1.", call. = FALSE)
  }
  if(!is.character(var)){
    stop("var must be a charactor.", call. = FALSE)
  }
  dots <- lapply(sprintf("~quantile(%1$s, probs = %2$s)", as.character(var), probs), as.formula)
  summarise_(x, .dots = setNames(dots, probs))
}

注意した点は、「dplyr::summarise()で使える関数は長さ1を返さないとだめ」という点です。なので、そのままquantile関数を適用しようとすると怒られました。

仕方ないので「引数で複数列を返してくるように記述」することになるのですが、何個も同じように記述するのは実に面倒です。かといって単純にsplintf()で持ってきてもうまくいきませんでした。そこでsummarise_()を使うこととし、引数部分はリストで渡してみました。

多分大したものではないのですが、NSEとかeval(parse())とか自分にとってはいい勉強になりました。

使用例

こんな感じです。

d_quant(iris, "Sepal.Length")
##     0 0.25 0.5 0.75   1
## 1 4.3  5.1 5.8  6.4 7.9
iris %>% d_quant("Sepal.Length", probs = c(0.25, 0.5, 0.75))
##   0.25 0.5 0.75
## 1  5.1 5.8  6.4
iris %>% group_by(Species) %>% d_quant("Sepal.Length", probs = c(0.25, 0.5, 0.75))
## Source: local data frame [3 x 4]
## 
##      Species  0.25   0.5  0.75
##       (fctr) (dbl) (dbl) (dbl)
## 1     setosa 4.800   5.0   5.2
## 2 versicolor 5.600   5.9   6.3
## 3  virginica 6.225   6.5   6.9

わりとやっつけなので、変数名をcharactorで指定しないといけなかったりしますが、このようにpipeでつないでもOKです。

応用

多分この関数自体の需要は少ないですが、「dplyr::summarise()で使える関数は長さ1を返さないとだめ」をクリアできるのは嬉しいかなと思います。要するにlapplyを利用して作ったformula型のものを、summarise_().dots =にぶち込めば、いい感じに評価して戻してくれます。もうちょっといい方法もありそうだけど、私ではこの程度でした。

Enjoy!