2017-07-31 5 views
1

2つの変数でグループ化された観測数を与えるテーブルを公開する必要があります。このコードは正常に動作します。しかし、私はこれを機能に変えようとすると問題に遭遇しました。テーブルの機能の外dplyrとgroup_byを使用して独自の関数を書く - 変更された列名を使用する方法

コード::これは
library(tidyverse) 

tab1 <- mtcars %>% count(cyl) %>% rename(Total = n) 

tab2 <- mtcars %>% 
    group_by(cyl, gear) %>% count %>% 
    spread(gear, n) 

tab <- full_join(tab1, tab2, by = "cyl") 
tab 


# This is the output (which is what I want) 

A tibble: 3 x 5 
cyl Total `3` `4` `5` 
<dbl> <int> <int> <int> <int> 
1  4 11  1  8  2 
2  6  7  2  4  1 
3  8 14 12 NA  2 

が機能

機能にこれを入れしようとする働き

私はdplyr_0.7.2

例使用mtcarsを使用していますtab1の場合:これは動作します

count_by_two_groups_A <- function(df, var1){ 
    var1 <- enquo(var1) 
    tab1 <- df %>% count(!!var1) %>% rename(Total = n) 
    tab1 
} 

count_by_two_groups_A(mtcars, cyl) 

A tibble: 3 x 2 
cyl Total 
<dbl> <int> 
1  4 11 
2  6  7 
3  8 14 

TAB2の最初の部分のための機能:それはこの時点までに動作しますが、...

count_by_two_groups_B <- function(df, var1, var2){ 

    var1 <- enquo(var1) 
    var2 <- enquo(var2) 

    tab2 <- df %>% group_by((!!var1), (!!var2)) %>% count 
    tab2 
} 

count_by_two_groups_B(mtcars, cyl, gear) 

A tibble: 8 x 3 
Groups: (cyl), (gear) [8] 
`(cyl)` `(gear)`  n 
<dbl> <dbl> <int> 
1  4  3  1 
2  4  4  8 
3  4  5  2 
4  6  3  2 
5  6  4  4 
6  6  5  1 
7  8  3 12 
8  8  5  2 

列名は(CYL)及び(ギア)に変更されました。私は列名が変更されたので、spread()とfull_join()(または新しい列名を使用する他のもの)を引き継ぐ方法を理解できないようです。私。私はtidyeval方法で新しい列名を指定する方法を理解することはできません。私は成功せずに様々なことを試みました。

答えて

2

tidyevに名前を設定する通常の方法:ちょうどそのspreadであなたの目標をされている場合があります。このテーブルオブジェクトとして(思考を取得他のコンテキストでは、定義演算子:=を使用します。あなたはvar1からnm1を抽出する必要がある。このため

df %>% 
    group_by(
    !! nm1 := !! var1, 
    !! nm2 := !! var2 
) %>% 
    count() 

:それは次のようになります。残念ながら、私は囲み括弧を取り除く簡単な方法はまだありません。私は、今後の関数ensym()でそれを行うのが理にかなっていると思う(それは、quosuresの代わりにシンボルを取り込み、呼び出しを提供するとエラーを出す)。私はここにチケットを提出しました:https://github.com/tidyverse/rlang/issues/223

幸いにもここでは2つの簡単な解決策があります。最初に、カッコを囲む必要はないことに注意してください。キャプチャされた表現に他の演算子が関与している場合にのみ必要です。例えば。このような状況では:あなたは括弧を省略した場合この場合

(!! var)/avg 
(!! var) < value 

!!は全体の表現だけではなく1つのシンボルをUNQUOTEしようとするだろう。最後に

count_by_two_groups_B <- function(df, var1, var2) { 
    var1 <- enquo(var1) 
    var2 <- enquo(var2) 

    df %>% 
    group_by(!! var1, !! var2) %>% 
    count() 
} 

は、あなたが引数の可変数を可能にすることにより、あなたの関数は、より一般的にすることができます:あなたの関数で一方囲むことなく、あなたが安全にunquoteことができるように何の演算子はありません。ドットをに転送してを転送するので、これを実装するのはさらに簡単です。キャプチャしたり引用したりする必要はありません。 group_by()

count_by <- function(df, ...) { 
    df %>% 
    group_by(...) %>% 
    count() 
} 
2

NSE(非標準評価)で動作させることができます。私はそれがインストールされていないとtidyverseでそれを行うことはできませんでしたとインストールを気にしなかった。

library(dplyr) 
library(tidyr) 

count_by_two_groups_B <- function(df, var1, var2){ 

# var1 <- enquo(var1) 
# var2 <- enquo(var2) 

    tab2 <- df %>% group_by_(var1, var2) %>% summarise(n = n()) %>%spread(gear, n) 

    tab2 
} 

count_by_two_groups_B(mtcars, 'cyl', 'gear') 

結果:

# A tibble: 3 x 4 
# Groups: cyl [3] 
    cyl `3` `4` `5` 
* <dbl> <int> <int> <int> 
1  4  1  8  2 
2  6  2  4  1 
3  8 12 NA  2 
0

これはdplyrに手を伸ばしたり、過度tidyverse思えるこれらの状況の一つである。ここ

は動作するコードです。

as.data.frame(with(mtcars, table(cyl,gear)) , responseName="Total") 
#-------- 
    cyl gear Total 
1 4 3  1 
2 6 3  2 
3 8 3 12 
4 4 4  8 
5 6 4  4 
6 8 4  0 
7 4 5  2 
8 6 5  1 
9 8 5  2 

この1つのdplyrアプローチのようになります。:あり、この... tableを行うにし、長い形式で結果を作るために基本機能はas.dataframe、ある

mtcars %>% group_by(cyl,gear) %>% summarise(Total=n()) 
#---- 
# A tibble: 8 x 3 
# Groups: cyl [?] 
    cyl gear Total 
    <dbl> <dbl> <int> 
1  4  3  1 
2  4  4  8 
3  4  5  2 
4  6  3  2 
5  6  4  4 
6  6  5  1 
7  8  3 12 
8  8  5  2 

と疑問だった場合どのように

with(mtcars, table(cyl,gear)) 
+0

私はスクリプト内で統一スタイルを維持する価値があると思います。 tidyevalを働かせようとしているなら、小さな機能から始めるのが最善です。これらの理由から、元の質問に答えることが理にかなっています。 – lionel

+0

私の問題の一部は、元の質問には明確さが欠けていました。 –

関連する問題