2017-05-26 10 views
5

私はsummarise()任意の変数で任意の変数に単純なラッパーを書こうとしています今、私はcorrect library version loadedを持っていますが、複数の引数を引用符で囲まないように混乱しています値。dplyr-0.6.0プログラミングunquoting

私は現在、以下の機能を持っている...

そこに道のほとんどを取得し、私は1つのグループ化変数を指定した場合に動作
table_summary <- function(df  = ., 
          id  = individual_id, 
          select = c(), 
          group = site, 
          ...){ 
    ## Quote all arguments (see http://dplyr.tidyverse.org/articles/programming.html) 
    quo_id  <- enquo(id) 
    quo_select <- enquo(select) 
    quo_group <- enquo(group) 
    ## Subset the data 
    df <- df %>% 
      dplyr::select(!!quo_id, !!quo_select, !!quo_group) %>% 
      unique() 
    ## gather() data, just in case there is > 1 variable selected to be summarised 
    df <- df %>% 
      gather(key = variable, value = value, !!quo_select) 
    ## Summarise selected variables by specified groups 
    results <- df %>% 
      group_by(!!quo_group, variable) %>% 
      summarise(n = n(), 
        mean = mean(value, na.rm = TRUE)) 
    return(results) 
} 

...

> table_summary(df = mtcars, id = model, select = c(mpg), group = gear) 
# A tibble: 3 x 4 
# Groups: c(gear) [?] 
     gear variable  n  mean 
     <dbl> <chr> <int> <dbl> 
1   3  mpg 15 16.10667 
2   4  mpg 12 24.53333 
3   5  mpg  5 21.38000 

...しかし、失敗しました私は複数のgroup = c(gear, hp)を指定group_by(!!quo_group, variable)で...

> mtcars$model <- rownames(mtcars) 
> table_summary(df = mtcars, id = model, select = c(mpg), group = c(gear, hp)) 
Error in mutate_impl(.data, dots) : 
    Column `c(gear, hp)` must be length 32 (the group size) or one, not 64 

私は戻って、再読み込みprogramming dplyr documentationと私はあなたがcapture multiple variables!!!quo_group``withinへの最初の参照に失敗した... ...そうしようとした、

table_summary <- function(df  = ., 
          id  = individual_id, 
          select = c(), 
          group = c(), 
          digits = 3, 
          ...){ 
    ## Quote all arguments (see http://dplyr.tidyverse.org/articles/programming.html) 
    quo_id  <- enquo(id) 
    quo_select <- enquo(select) 
    quo_group <- quos(group) ## Use quos() rather than enquo() 
    UQS(quo_group) %>% print() ## Check to see what quo_group holds 
    ## Subset the data 
    df <- df %>% 
      dplyr::select(!!quo_id, !!quo_select, !!!quo_group)) %>% 
      unique() 
    ## gather() data, just in case there is > 1 variable selected to be summarised 
    df <- df %>% 
      gather(key = variable, value = value, !!quo_select) 
    ## Summarise selected variables by specified groups 
    results <- df %>% 
       group_by(!!!quo_group, variable) %>% 
       summarise(n = n(), 
         mean = mean(value, na.rm = TRUE)) 
    return(results) 
} 

quos()代わりにenquo()を使用して、unquote-splice them with !!!できることを読みますdplyr ::()奇妙なよう何regardless of how many variables are specified underグループ= `...

> table_summary(df = mtcars, id = model, select = c(mpg), group = c(gear)) 
[[1]] 
<quosure: frame> 
~group 

attr(,"class") 
[1] "quosures" 
Error in overscope_eval_next(overscope, expr) : object 'gear' not found 
> traceback() 
17: .Call(rlang_eval, f_rhs(quo), overscope) 
16: overscope_eval_next(overscope, expr) 
15: FUN(X[[i]], ...) 
14: lapply(.x, .f, ...) 
13: map(.x[matches], .f, ...) 
12: map_if(ind_list, !is_helper, eval_tidy, data = names_list) 
11: select_vars(names(.data), !(!(!quos(...)))) 
10: select.data.frame(., !(!quo_id), !(!quo_select), !(!(!quo_group))) 
9: dplyr::select(., !(!quo_id), !(!quo_select), !(!(!quo_group))) 
8: function_list[[i]](value) 
7: freduce(value, `_function_list`) 
6: `_fseq`(`_lhs`) 
5: eval(quote(`_fseq`(`_lhs`)), env, env) 
4: eval(quote(`_fseq`(`_lhs`)), env, env) 
3: withVisible(eval(quote(`_fseq`(`_lhs`)), env, env)) 
2: df %>% dplyr::select(!(!quo_id), !(!quo_select), !(!(!quo_group))) %>% 
     unique() 
1: table_summary(df = mtcars, id = model, select = c(mpg), group = c(gear)) 

を選択して、私は問題の原因は、!!!quo_group(すなわちということであると思いますUQS(quo_group)は)~gearではなく、示しが起こる働い例にprint()の追加などquosuresのリストを出力します...

> my_summarise <- function(df, ...) { 
    group_by <- quos(...) 
    UQS(group_by) %>% print() 
    df %>% 
    group_by(!!!group_by) %>% 
    summarise(a = mean(a)) 
    } 
> df <- tibble(
    g1 = c(1, 1, 2, 2, 2), 
    g2 = c(1, 2, 1, 2, 1), 
    a = sample(5), 
    b = sample(5) 
) 
> my_summarise(df, g1, g2) 
[[1]] 
<quosure: global> 
~g1 

[[2]] 
<quosure: global> 
~g2 

attr(,"class") 
[1] "quosures" 
# A tibble: 4 x 3 
# Groups: g1 [?] 
    g1 g2  a 
    <dbl> <dbl> <dbl> 
1  1  1 1.0 
2  1  2 5.0 
3  2  1 2.5 
4  2  2 4.0 
私は明示的にパラメータとしてで私はグループに希望の変数を提供したいと思います

私私は...としてそれらを指定する場合は引数が、それは動作しませんが、私は...

table_summary <- function(df  = ., 
          id  = individual_id, 
          select = c(), 
          group = c(), 
          digits = 3, 
          ...){ 
    ## Quote all arguments (see http://dplyr.tidyverse.org/articles/programming.html) 
    quo_id  <- enquo(id) 
    quo_select <- enquo(select) 
    ## quo_group <- quos(group) 
    quo_group <- quos(...) 
    UQS(quo_group) %>% print() 
    ## Subset the data 
    df <- df %>% 
      dplyr::select(!!quo_id, !!quo_select, !!!quo_group) %>% 
      unique() 
    ## gather() data, just in case there is > 1 variable selected to be summarised 
    df <- df %>% 
      gather(key = variable, value = value, !!quo_select) 
    ## Summarise selected variables by specified groups 
    results <- df %>% 
       group_by(!!!quo_group, variable) %>% 
       summarise(n = n(), 
         mean = mean(value, na.rm = TRUE)) 
    return(results) 
} 

としてグループ化変数を供給する場合、私の機能が動作するかどうかをテストすることにしました...が、それはNULLにない、quos()再びにunquote-スプライスを行いますだからvar iablesは、どちらも私は何回かは今enquo()を使用してそれぞれの方法をチェックしquos()このサイクルを行ってきたが、私は間違っているとプログラミングを読んだにも関わらず、午前場所を確認することはできません

> table_summary(df = mtcars, id = model, select = c(mpg), gear, hp) 
NULL 
# A tibble: 1 x 3 
    variable  n  mean 
    <chr> <int> <dbl> 
1  mpg 32 20.09062 
> table_summary(df = mtcars, id = model, select = c(mpg), gear) 
NULL 
# A tibble: 1 x 3 
    variable  n  mean 
    <chr> <int> <dbl> 
1  mpg 32 20.09062 

...によって選択されなかったりグループ化されていますdplyrドキュメンテーションを何回か繰り返します。

答えて

4

IIUCあなたの投稿は、あなたがgroup_by()c(col1, col2)を供給します。これは、その動詞でサポートされていない:group_by()のmutate意味を持っているためだ

group_by(mtcars, c(cyl, am)) 
#> Error in mutate_impl(.data, dots) : 
#> Column `c(cyl, am)` must be length 32 (the number of rows) or one, not 64 

、ないセマンティクスを選択します。つまり、group_by()に提供する式は変形式です。これは驚くが、非常に便利な機能です。たとえば、グループ化できますdispカットすることにより、このような3つの区間へ:

group_by(mtcars, cut3 = cut(disp, 3)) 

これもあなたがc(cyl, am)を供給する場合、それは期待していたが、それは、2つの列を連結し、長さ64のベクトルを返すことを意味します長さは32(行数)です。

問題は、選択のセマンティクスを持つgroup_by()のラッパーが必要なことです。

library("dplyr") 

group_wrapper <- function(df, groups = rlang::chr()) { 
    groups <- select_vars(tbl_vars(df), !! enquo(groups)) 
    group_by(df, !!! rlang::syms(groups)) 
} 

また、あなたが選択する意味を持っている新しいgroup_by_at()動詞ラップすることができます::これはすぐに新しいtidyselectパッケージに抽出される、dplyr::select_vars()を使用して行うことは容易であるのは、試してみましょう

group_wrapper <- function(df, groups = rlang::chr()) { 
    group_by_at(df, vars(!! enquo(groups))) 
} 

をそれアウト:

group_wrapper(mtcars, c(disp, am)) 
#> # A tibble: 32 x 11 
#> # Groups: disp, am [27] 
#>  mpg cyl disp hp drat wt qsec vs am gear carb 
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
#> 1 21.0  6 160 110 3.90 2.62 16.5  0  1  4  4 
#> # ... with 22 more rows 

このインタフェースは、グループに列を選択するために、すべてのselect()操作をサポートするという利点があります。機能を選択することでサポートされていないc()戻っNULLは(私たちは将来的にそれを変更したい場合があります)ので、私はデフォルトの引数としてrlang::chr()を使用してい

注意。引数なしで呼び出されたchr()は、長さ0の文字ベクトルを返します。