Introduction to dplyr

データを扱うときに必要なこと。

dplyr パッケージは、これらのステップを迅速かつ容易にします。

このドキュメントでは、dplyr の基本的なツール群を紹介し、それらをデータフレームに適用する方法を示します。 dplyr は、dbplyr パッケージによってデータベースもサポートしています。

データ: starwars

dplyr の基本的なデータ操作方法を調べるために、データセット starwars を使います。このデータセットは 87 の文字を含んでおり、Star Wars APIから来ており、?starwars で文書化されています。

dim(starwars)
#> [1] 87 14
starwars
#> # A tibble: 87 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 C-3PO    167    75 <NA>       gold       yellow         112   none  mascu~
#> 3 R2-D2     96    32 <NA>       white, bl~ red             33   none  mascu~
#> 4 Dart~    202   136 none       white      yellow          41.9 male  mascu~
#> # ... with 83 more rows, and 5 more variables: homeworld <chr>, species <chr>,
#> #   films <list>, vehicles <list>, starships <list>

starwarsは、データフレームを現代風にアレンジした tibble であることに注意してください。これは最初の数行だけを表示するので、大きなデータセットには特に便利です。tibble については https://tibble.tidyverse.org を参照してください。特に、データフレームを tibble に変換するには as_tibble() を使用します。

単一テーブルの動詞

dplyrは、データ操作の基本的な動詞ごとに関数を提供することを目指しています。これらの動詞は、扱うデータセットの構成要素に基づいて、3つのカテゴリに分類されます。

パイプ

dplyrのすべての関数は、第1引数としてデータフレーム(または tibble)を取ります。中間オブジェクトの保存や関数のネストをユーザに強いるのではなく、dplyr は magrittr の%>%演算子を提供します。x %>% f(y)f(x, y) となり,あるステップの結果が次のステップに「パイプ」されます.パイプを使って、左から右へ、上から下へと読める複数の操作を書き換えることができます(パイプ演算子を「then」と読みます)。

filter() による行のフィルタリング

filter() を使うと、データフレーム内の行のサブセットを選択することができます。他の単一の動詞と同様に、第1引数は tibble (またはデータフレーム)です。2番目以降の引数は、そのデータフレーム内の変数を参照し、その式が TRUE である行を選択します。

例えば、肌の色が明るく、目が茶色のキャラクターをすべて選択するには、次のようにします。

これは、この基本的なRのコードとほぼ同じです。

arrange()で行を並べる

arrange()filter() と似たような動作をしますが、行をフィルタリングしたり選択したりするのではなく、並び替えを行います。データフレームと、順序付けするための列名(またはより複雑な式)のセットを受け取ります。複数の列名を指定した場合,追加の各列は前の列の値の同値を解消するために使用されます。

列を降順で並べるには desc() を使います。

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

slice() では、行の(整数の)位置でインデックスを作ることができます。これにより、行の選択、削除、複製が可能になります。

5行目から10行目までの文字を得ることができます。

これには,一般的な使用例に対応した多くのヘルパーが付属しています.

ブートストラップサンプルを実行するには、replace = TRUE を使用します。必要であれば、weightという引数でサンプルに重み付けをすることができます。

select()によるカラムの選択

多くのカラムを含む大規模なデータセットを扱う際に、実際にはいくつかのカラムにしか興味を持てないことがよくあります。select() を使えば、通常は数値変数の位置にしか作用しない操作を使って、有用なサブセットを素早く拡大することができます。

select() の中には、starts_with()ends_with()matches()contains()といったヘルパー関数が用意されています。これらを使うと、ある基準を満たす大きな変数のブロックに素早くマッチさせることができます。詳細は ?select を参照してください。

select() では、名前付き引数を使って変数の名前を変更することができます。

しかし、select() は明示的に言及されていないすべての変数を削除してしまうので、あまり便利ではありません。代わりに rename() を使ってください。:

mutate()で新しいカラムを追加する

既存のカラムのセットを選択するだけでなく、既存のカラムの関数である新しいカラムを追加することもしばしば役に立ちます。これが mutate() の仕事です。

先ほど計算したメートル単位の高さを見ることはできませんが、select コマンドを使って修正することができます。

dplyr::mutate() は基本的な transform() と似ていますが、作成したばかりのカラムを参照することができます。:

新しい変数だけを保持したい場合は、transmute() を使用してください。:

relocate()による列の順序変更

select() と同様の構文で、複数の列を一度に移動させることができます。

summarise()で値をまとめる

最後の動詞は summarise() です。これは、データフレームを1つの行にまとめるものです。

以下の group_by() という動詞を覚えるまでは、それほど便利ではありません。

共通点

これらの動詞の構文や機能が非常に似ていることにお気づきでしょうか。

これらのプロパティを組み合わせることで、複数のシンプルなステップを連鎖させて、複雑な結果を簡単に得ることができます。

これらの5つの機能は、データ操作のための言語の基礎となります。最も基本的なレベルでは、整理されたデータフレームを5つの便利な方法で変更することができます。行を並べ替える(arrange())、興味のある観測値や変数を選ぶ(filter()およびselect())、既存の変数の関数である新しい変数を追加する(mutate())、多くの値をまとめて表示する(summarise())です。

%>% を使った関数の組み合わせ

dplyr の API は、関数呼び出しが副作用を持たないという意味で機能的です。関数呼び出しの結果は必ず保存しなければなりません。これは、特に多くの処理を一度に行いたい場合、特にエレガントなコードにはなりません。ステップ・バイ・ステップで行う必要があります。

a1 <- group_by(starwars, species, sex)
a2 <- select(a1, height, mass)
a3 <- summarise(a2,
  height = mean(height, na.rm = TRUE),
  mass = mean(mass, na.rm = TRUE)
)

あるいは、中間結果に名前を付けたくない場合は、関数の呼び出しを相互にラップする必要があります。:

summarise(
  select(
    group_by(starwars, species, sex),
    height, mass
  ),
  height = mean(height, na.rm = TRUE),
  mass = mean(mass, na.rm = TRUE)
)
#> Adding missing grouping variables: `species`, `sex`
#> `summarise()` has grouped output by 'species'. You can override using the `.groups` argument.
#> # A tibble: 41 x 4
#> # Groups:   species [38]
#>   species  sex   height  mass
#>   <chr>    <chr>  <dbl> <dbl>
#> 1 Aleena   male      79    15
#> 2 Besalisk male     198   102
#> 3 Cerean   male     198    82
#> 4 Chagrian male     196   NaN
#> # ... with 37 more rows

これが読みにくいのは、演算の順番が内側から外側へとなっているからです。したがって、引数は関数からずいぶん離れたところにあります。この問題を回避するために,dplyr は magrittr の %>% 演算子を提供しています.x %>% f(y)f(x, y)` になるので,これを使って,複数の演算を左から右,上から下に読めるように書き換えることができます(パイプ演算子を「then」と読む).

starwars %>%
  group_by(species, sex) %>%
  select(height, mass) %>%
  summarise(
    height = mean(height, na.rm = TRUE),
    mass = mean(mass, na.rm = TRUE)
  )

操作のパターン

dplyr の動詞は、その動作の種類によって分類することができます(その意味を セマンティクス、つまり意味、と呼ぶことがあります)。 select 操作と mutate 操作の違いをよく理解しておくと便利です。

選択操作

dplyr の魅力の1つは、tibble の中の列をあたかも 列を通常の変数のように参照できることです。しかし しかし、列名をそのまま参照するという構文上の統一性のために、動詞間の意味上の違いが隠されています。 意味的な違いが隠されています。select() に与えられた列のシンボルは select() に与えられた列のシンボルは,同じシンボルが mutate() に与えられたものとは同じ意味を持ちません. mutate() に与えられる同じシンボルとは同じ意味を持ちません。

選択操作では、列名と位置が求められます。そのため 裸の変数名で select() を呼び出した場合、それらは実際には tibble の中の自分の位置を表しています。 の位置を表しています。以下の呼び出しは、dplyr の観点からは完全に dplyr の観点からは完全に等価です。

同じ意味で、これは、周囲のコンテキストの変数が列の1つと同じ名前である場合には、その変数を参照できないことを意味します。次の例では、height は5ではなく、やはり2を表しています。:

便利な点としては、これが裸の名前と、c(height, mass)height:mass のような選択的な呼び出しにのみ適用されることです。その他のケースでは、データフレームの列はスコープに入りません。これにより、選択ヘルパーで文脈変数を参照することができます。:

これらのセマンティクスは、通常、直感的に理解できるものです。しかし、微妙な違いに注意してください。:

第1引数の name は自分の位置1を表します。2番目の引数では、name は周囲の文脈で評価され、5番目の列を表します。

長い間、select()は列の位置しか理解できませんでした。dplyr 0.6 からは、列名も理解できるようになりました。これにより、select() を使ったプログラミングが少し楽になりました。

ミューテート操作

ミューテートのセマンティクスは、選択のセマンティクスとは全く異なります。select() では列の名前や位置を指定するのに対し、mutate() では 列のベクトル を指定します。 ここでは、例として小さめの tibble を設定してみます。

select() を使う場合,むき出しの列名はtibbleの中のそれぞれの位置を表している。一方,mutate()では,列のシンボルは tibble に格納されている実際の列ベクトルを表す。 mutate() に文字列や数値を与えるとどうなるか考えてみよう。

mutate() は長さ1のベクトルを取得し,それをデータフレームの新しい列として解釈します.これらのベクトルは,行数と一致するように再利用されます. 行数と一致するように再利用されます。 これは文字列に10を加えることに等しいのです。 正しい表現は:

同じように、有効な列を表す値であれば、コンテキストから値を unquote することができます。これらの値は、長さが1であるか(リサイクルされます)、行数と同じ長さである必要があります。次の例では、新しいベクトルを作成し、データフレームに追加しています。

その例として、group_by()が挙げられます。これは select セマンティクスだと思われるかもしれませんが、実際には mutate セマンティクスです。これは、変更された列でグループ化することができるので、非常に便利です。

group_by(starwars, sex)
#> # A tibble: 87 x 14
#> # Groups:   sex [5]
#>   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 C-3PO    167    75 <NA>       gold       yellow         112   none  mascu~
#> 3 R2-D2     96    32 <NA>       white, bl~ red             33   none  mascu~
#> 4 Dart~    202   136 none       white      yellow          41.9 male  mascu~
#> # ... with 83 more rows, and 5 more variables: homeworld <chr>, species <chr>,
#> #   films <list>, vehicles <list>, starships <list>
group_by(starwars, sex = as.factor(sex))
#> # A tibble: 87 x 14
#> # Groups:   sex [5]
#>   name  height  mass hair_color skin_color eye_color birth_year sex   gender
#>   <chr>  <int> <dbl> <chr>      <chr>      <chr>          <dbl> <fct> <chr> 
#> 1 Luke~    172    77 blond      fair       blue            19   male  mascu~
#> 2 C-3PO    167    75 <NA>       gold       yellow         112   none  mascu~
#> 3 R2-D2     96    32 <NA>       white, bl~ red             33   none  mascu~
#> 4 Dart~    202   136 none       white      yellow          41.9 male  mascu~
#> # ... with 83 more rows, and 5 more variables: homeworld <chr>, species <chr>,
#> #   films <list>, vehicles <list>, starships <list>
group_by(starwars, height_binned = cut(height, 3))
#> # A tibble: 87 x 15
#> # Groups:   height_binned [4]
#>   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 C-3PO    167    75 <NA>       gold       yellow         112   none  mascu~
#> 3 R2-D2     96    32 <NA>       white, bl~ red             33   none  mascu~
#> 4 Dart~    202   136 none       white      yellow          41.9 male  mascu~
#> # ... with 83 more rows, and 6 more variables: homeworld <chr>, species <chr>,
#> #   films <list>, vehicles <list>, starships <list>, height_binned <fct>

これが、group_by()に列名を与えることができない理由です。これは、行数にリサイクルされた文字列を含む新しい列を作成することになります。: