2017-04-12 20 views
3

dplyr内でselect()とmutate()関数を手動で組み合わせることがよくあります。これは通常、データフレームを整理し、古い列に基づいて新しい列を作成し、新しい列のみを保持したいからです。私は高さと幅に関するデータを持っていたが、唯一、私が使用する面積を計算し、維持するためにそれらを使用したい場合selectとmutateの組み合わせ

たとえば、:

library(dplyr) 
df <- data.frame(height = 1:3, width = 10:12) 

df %>% 
    mutate(area = height * width) %>% 
    select(area) 

で作成された変数が多い場合にはそれらをすべて選択ステップに入れておくことは難しいでしょう。 mutateステップで定義された変数のみを保持するよりエレガントな方法はありますか?私が使用してきた

つの回避策は以下の通りです:

df %>% 
    mutate(id = row_number()) %>% 
    group_by(id) %>% 
    summarise(area = height * width) %>% 
    ungroup() %>% 
    select(-id) 

これは動作しますが、かなり冗長で、そして集計()を使用すると、パフォーマンスヒットがあります意味:

library(microbenchmark) 

microbenchmark(

    df %>% 
    mutate(area = height * width) %>% 
    select(area), 

    df %>% 
    mutate(id = row_number()) %>% 
    group_by(id) %>% 
    summarise(area = height * width) %>% 
    ungroup() %>% 
    select(-id) 
) 

出力は、 :

 min  lq  mean median  uq  max neval cld 
    868.822 954.053 1258.328 1147.050 1363.251 4369.544 100 a 
1897.396 1958.754 2319.545 2247.022 2549.124 4025.050 100 b 

元のデータフローを比較できる別の回避策があると思います私は新しいデータフレーム名で名前を付け、右の補足を取るが、おそらくもっと良い方法があるだろうか?

私はdplyrのドキュメントで本当に明白な何かを見逃しているような気がするので、これは簡単です!

+6

あなたは 'dplyr :: transmute'について知っていますか? – Nate

+0

'with(df、data.frame(area = height * width))'ははるかに高速です。パイプが必須であれば 'df%$%data.frame(area = height * width)'となります。しかし、そのような小さなデータセットでのベンチマークは実際には意味がありません。 – Frank

+0

@NateDayはい、 'dplyr :: transmute'は完璧です。私はそれが変質して参照された変数を削除しただけであると私は思いましたが、間違いました。ありがとう! – mdpead

答えて

1

わずか2つのステップを組み合わせた独自の関数を作成します。

mutate_only = function (.data, ...) { 
    names = names(match.call(expand.dots = FALSE)$...) 
    .data %>% mutate(...) %>% select(one_of(names)) 
} 

これは、標準的な評価を適切に機能するためにいくつかの作業を必要とします。残念ながら、dplyr APIは現在その時点で進化していますので、この勧告が数週間でどのようになるのか分かりません。したがって、私はちょうどrelevant documentationを参照します。

+1

リンクが破損する可能性があります.devバージョンのvignettesには含まれていないため、https://github.com/tidyverse/dplyr/tree/master/vignettes – Frank

関連する問題