dplyr <-> base R

この vignette は、dplyr の関数を base R の同等品と比較しています。これは、base R に精通している人がdplyrの機能をよりよく理解するのに役立ち、dplyr ユーザーが同じアイデアを base R のコードでどのように表現できるかを示します。まず、主な違いの大まかな概要を説明し、次に1テーブルの動詞について詳しく説明し、続いて2テーブルの動詞について説明します。

概要

  1. dplyr verbs は、データフレームを入出力するコードです。これは、Rの基本的な Rの関数は、個々のベクトルを扱うことが多いです。

  2. dplyr は「非標準の評価」に大きく依存しており、「現在の」データフレーム内の列を参照するのに 現在の "データフレーム内の列を参照するために$を使用する必要がないように。この動作は 基本関数の subset()transform() にヒントを得ています。

  3. dplyr のソリューションは様々な単一目的の動詞を使用する傾向があります。 Rのソリューションは、一般的に、タスクに応じて様々な方法で [ を使用する傾向があります。 を使う傾向があります。

  4. 複数の dplyr の動詞は、多くの場合、%>%によってパイプラインにつなぎ合わされます。 ベースRでは、通常、中間結果を変数に保存して、それを破棄したり、繰り返したりします。 捨てたり、繰り返し上書きしたりします。

  5. すべての dplyr verbs は「グループ化された」データフレームを扱うため、グループごとに計算を実行するコードは非常に似ています。 グループごとに計算を実行するコードは、データフレーム全体で動作するコードとよく似ています。 データフレーム全体を扱うコードとよく似ています。基本的なRでは、グループ単位の演算は様々な形で行われます。

One table verbs

次の表は、dplyrの動詞とベースとなるRの等価物との間の凝縮された翻訳を示しています。次のセクションでは、各操作についてより詳しく説明します。dplyrの動詞については、それぞれのドキュメントや vignette("one-table")で詳しく説明されています。

dplyr base
arrange(df, x) df[order(x), , drop = FALSE]
distinct(df, x) df[!duplicated(x), , drop = FALSE], unique()
filter(df, x) df[which(x), , drop = FALSE], subset()
mutate(df, z = x + y) df$z <- df$x + df$y, transform()
pull(df, 1) df[[1]]
pull(df, x) df$x
rename(df, y = x) names(df)[names(df) == "x"] <- "y"
relocate(df, y) df[union("y", names(df))]
select(df, x, y) df[c("x", "y")], subset()
select(df, starts_with("x") df[grepl(names(df), "^x")]
summarise(df, mean(x)) mean(df$x), tapply(), aggregate(), by()
slice(df, c(1, 2, 5)) df[c(1, 2, 5), , drop = FALSE]

まず、dplyr をロードして、mtcarsiris を tibble に変換して、各操作の略式出力だけを簡単に表示できるようにします。

library(dplyr)
mtcars <- as_tibble(mtcars)
iris <- as_tibble(iris)

arrange(): 変数で行を並べる

dplyr::arrange()は、データフレームの行を1つまたは複数の列の値で並べます。

desc()ヘルパーを使うと、選択した変数を降順で並べることができます。

order()[ を使うことで、base Rに複製することができます。

drop = FALSEの使用に注意してください。これを忘れると、入力が1列のデータフレームであった場合、出力はデータフレームではなくベクトルになります。これは微妙なバグの原因になります。

base Rは、個々の変数を降順でソートする便利で一般的な方法を提供していないので、2つの選択肢があります。

distinct(): 固有/ユニークな行の選択

dplyr::distinct() は、ユニークな行を選択します。

base R では、データフレーム全体を取得するか、選択した変数のみを取得するかによって、2つの同等の機能があります。

filter(): 条件にマッチした行を返す

dplyr::filter()は、ある式が TRUE である行を選択する。

最も近い基本的な等価物(そして filter() のインスピレーション)は subset() です。

また、[を使うこともできますが、その場合はNAを削除するためにwhich()を使う必要があります。

starwars[which(starwars$species == "Human"), , drop = FALSE]
#> # A tibble: 35 x 14
#>   name  height  mass hair_color skin_color eye_color birth_year sex   gender
#>   <chr>  <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
#> 1 Luke~    172    77 blond      fair       blue            19   male  mascu~
#> 2 Dart~    202   136 none       white      yellow          41.9 male  mascu~
#> 3 Leia~    150    49 brown      light      brown           19   fema~ femin~
#> 4 Owen~    178   120 brown, gr~ light      blue            52   male  mascu~
#> # ... with 31 more rows, and 5 more variables: homeworld <chr>, species <chr>,
#> #   films <list>, vehicles <list>, starships <list>
starwars[which(starwars$mass > 1000), , drop = FALSE]
#> # A tibble: 1 x 14
#>   name  height  mass hair_color skin_color eye_color birth_year sex   gender
#>   <chr>  <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
#> 1 Jabb~    175  1358 <NA>       green-tan~ orange           600 herm~ mascu~
#> # ... with 5 more variables: homeworld <chr>, species <chr>, films <list>,
#> #   vehicles <list>, starships <list>
starwars[which(starwars$hair_color == "none" & starwars$eye_color == "black"), , drop = FALSE]
#> # A tibble: 9 x 14
#>   name  height  mass hair_color skin_color eye_color birth_year sex   gender
#>   <chr>  <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
#> 1 Nien~    160    68 none       grey       black             NA male  mascu~
#> 2 Gasg~    122    NA none       white, bl~ black             NA male  mascu~
#> 3 Kit ~    196    87 none       green      black             NA male  mascu~
#> 4 Plo ~    188    80 none       orange     black             22 male  mascu~
#> # ... with 5 more rows, and 5 more variables: homeworld <chr>, species <chr>,
#> #   films <list>, vehicles <list>, starships <list>

mutate(): 変数の作成と変換

dplyr::mutate()は、既存の変数から新しい変数を作成します。

これに最も近い基本的なものはtransform()ですが、作成したばかりの変数は使えないことに注意してください。:

代わりに、$<-を使うこともできます。:

グループ化されたデータフレームに適用すると、dplyr::mutate()はグループごとに一度だけ新しい変数を計算します。:

これを base R で再現するには、ave()を使います。

pull(): 単一の変数を取り出す

dplyr::pull() は、名前または位置によって変数を抽出します。:

これは、ポジションの場合は [[、名前の場合は $ に相当します。

relocate(): 列の順序を変更する

dplyr::relocate()は、列のセットを新しい位置(デフォルトでは前)に簡単に移動させることができます。

これを base R でも少しのセット操作で再現できます。

カラムを中間地点に移動させるには、もう少しセットをいじる必要があります。

rename(): 名前による変数名の変更

dplyr::rename()では、変数を名前や位置でリネームすることができます。

base R では、ポジションによる変数名の変更は簡単です。

変数を名前でリネームするには、少し手間がかかります。:

rename_with(): 変数名を関数で変更する

dplyr::rename_with()は、関数を使って列名を変換します。

同様の効果は,base R の setNames() でも得られます。

select(): 名前による変数の選択

dplyr::select() は、位置、名前、名前の関数、または他のプロパティによって列をサブセットします。

base R では、位置による変数のサブセットが簡単にできます。

名前によるサブセットには2つのオプションがあります。

名前の関数でサブセットするには、grep() でちょっとした作業が必要です。

また、Filter() を使ってタイプ別にサブセットすることもできます。

summarise(): 複数の値を1つの値にまとめる

dplyr::summarise() は、各グループの1つまたは複数のサマリーを計算します。:

base R としては、by() が最も近いと思います。残念ながら、by() はデータフレームのリストを返しますが、do.call()rbind() を使って、再びデータフレームを組み合わせることができます。

aggregate() は、エレガントな答えに非常に近いものです。

しかし、残念ながら、disp.meandisp.n の列があるように見えますが、実際には1つの行列の列です。

他にも様々なオプションがhttps://gist.github.com/hadley/c430501804349d382ce90754936ab8ecに掲載されています。

slice(): 位置による行の選択

slice()は、位置で行を選択します。:

これは、[ で簡単に再現できます。:

2テーブルの動詞

2つのデータフレーム(xy)をマージしたい場合、それらを一緒にするための様々な方法があります。Rの基本的な merge() コールは、様々な dplyr の join() 関数で置き換えられます。

dplyr base
inner_join(df1, df2) merge(df1, df2)
left_join(df1, df2) merge(df1, df2, all.x = TRUE)
right_join(df1, df2) merge(df1, df2, all.y = TRUE)
full_join(df1, df2) merge(df1, df2, all = TRUE)
semi_join(df1, df2) df1[df1$x %in% df2$x, , drop = FALSE]
anti_join(df1, df2) df1[!df1$x %in% df2$x, , drop = FALSE]

two-table動詞の詳細については、vignette("two-table")を参照してください。

結合の変更

dplyrのinner_join()left_join()right_join()full_join()は、yからxまでの新しい列を追加し、一連の「キー」に基づいて行をマッチングします。これらは,all, all.x, all.y の各引数を様々に設定した merge() の呼び出しと同じです。主な違いは、行の順序です。

結合のフィルタリング

dplyr の semi_join()anti_join() は行のみに影響し、列には影響しません。

これらは[%in%を使って base R で複製することができます。

複数のキーとなる変数を持つ半統合や反統合は、実装が非常に困難です。