50

関数を別の関数内で使用したいのですがdplyr::group_by、この関数に引数を渡す方法がわかりません。

誰かが実用的な例を提供できますか?

library(dplyr)
data(iris)
iris %.% group_by(Species) %.% summarise(n = n()) # 
## Source: local data frame [3 x 2]
##      Species  n
## 1  virginica 50
## 2 versicolor 50
## 3     setosa 50

mytable0 <- function(x, ...) x %.% group_by(...) %.% summarise(n = n())
mytable0(iris, "Species") # OK
## Source: local data frame [3 x 2]
##      Species  n
## 1  virginica 50
## 2 versicolor 50
## 3     setosa 50

mytable1 <- function(x, key) x %.% group_by(as.name(key)) %.% summarise(n = n())
mytable1(iris, "Species") # Wrong!
# Error: unsupported type for column 'as.name(key)' (SYMSXP)

mytable2 <- function(x, key) x %.% group_by(key) %.% summarise(n = n())
mytable2(iris, "Species") # Wrong!
# Error: index out of bounds
4

4 に答える 4

73

プログラミングの場合、group_by_は次のものに対応しgroup_byます。

library(dplyr)

mytable <- function(x, ...) x %>% group_by_(...) %>% summarise(n = n())
mytable(iris, "Species")
# or iris %>% mytable("Species")

与える:

     Species  n
1     setosa 50
2 versicolor 50
3  virginica 50

更新これが書かれた時点%.%では、もともと上で使用されていたdplyrが使用されていましたが、現在%>%は好まれているため、これを関連性を保つために上記に変更しました。

Update 2の再グループ化は非推奨になりました。代わりに group_by_ を使用してください。

ロベルトのコメントによると、更新 3 は dplyr の新しいバージョンにgroup_by_(list(...))なります。group_by_(...)

更新 4コメントで提案されたマイナー バリエーションを追加しました。

更新 5: rlang/tidyeval を使用すると、これを実行できるようになりました。

library(rlang)
mytable <- function(x, ...) {
  group_ <- syms(...)
  x %>% 
    group_by(!!!group_) %>% 
    summarise(n = n())
}
mytable(iris, "Species")

または未評価のまま渡しSpeciesます。つまり、引用符で囲みません。

library(rlang)
mytable <- function(x, ...) {
  group_ <- enquos(...)
  x %>% 
    group_by(!!!group_) %>% 
    summarise(n = n())
}
mytable(iris, Species)

更新 6: グループ化変数が 1 つだけの場合に機能する {{...}} 表記法が追加されました。

mytable <- function(x, group) {
  x %>% 
    group_by({{group}}) %>% 
    summarise(n = n())
}
mytable(iris, Species)
于 2014-02-16T21:45:01.657 に答える
2

彼らが来るように醜いですが、彼女は働いています:

mytable3 <- function(x, key) {
  my.call <- bquote(summarise(group_by(.(substitute(x)), NULL), n = n()))
  my.call[[2]][[3]] <- as.name(key)
  eval(my.call, parent.frame())
} 
mytable3(iris, "Species")
# Source: local data frame [3 x 2]
#
#      Species  n
# 1  virginica 50
# 2 versicolor 50
# 3     setosa 50

これが壊れる原因となるケースはほぼ確実にありますが、アイデアはわかります。私はあなたが電話をいじるのを回避できるとは思わない。機能したが、さらに醜いもう1つのことは次のとおりです。

mytable4 <- function(x, key) summarise(group_by(x, x[[key]]), n = n())
于 2014-02-16T20:27:57.690 に答える