はじめに
dplyr ver.1.0.0が公開されました。
dplyr 1.0.0 out now: https://t.co/NDMJmxwllZ. This is the culmination of months of work and we're very excited that it's now available to the world! #rstats
— Hadley Wickham (@hadleywickham) 2020年6月1日
主な変更点については、こちらにまとめられています。
新しい関数などはなかなか取り入れないので、こちらにまとめておいて、しっかり使っていきたいと思います。
slice
今まで、sample_n()
で行っていたような、レコードのランダムサンプリングは、slice_*
系にまとまることになりました。
> iris %>% slice_sample(n = 4) Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 7.2 3.6 6.1 2.5 virginica 2 6.0 3.4 4.5 1.6 versicolor 3 5.8 2.7 5.1 1.9 virginica 4 6.8 2.8 4.8 1.4 versicolor
n=
を付けないと意図した動きをしてくれません。
特定のカラムの上位N件を取得する関数としてslice_max()
があります。
> iris %>% slice_max(Sepal.Length, n=5) Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 7.9 3.8 6.4 2.0 virginica 2 7.7 3.8 6.7 2.2 virginica 3 7.7 2.6 6.9 2.3 virginica 4 7.7 2.8 6.7 2.0 virginica 5 7.7 3.0 6.1 2.3 virginica
下位N件を取得する関数としてslice_min()
もあります。
> iris %>% slice_min(Sepal.Length, n=5) Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 4.3 3.0 1.1 0.1 setosa 2 4.4 2.9 1.4 0.2 setosa 3 4.4 3.0 1.3 0.2 setosa 4 4.4 3.2 1.3 0.2 setosa 5 4.5 2.3 1.3 0.3 setosa
N番目に小さな値が2つある場合、N+1件抽出されます。
> iris %>% slice_min(Sepal.Length, n=3) Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 4.3 3.0 1.1 0.1 setosa 2 4.4 2.9 1.4 0.2 setosa 3 4.4 3.0 1.3 0.2 setosa 4 4.4 3.2 1.3 0.2 setosa
slice_head()
, slice_tail()
もある。
summarise
summarise
後にグルーピングを変更したい場合は、またgroup_by()
やungroup()
などを行わないといけなかった。
ver1.0.0からは.group()
引数でグルーピングを制御できるようになっている。
> starwars %>% + group_by(sex, gender, species) %>% + summarise(height = mean(height), .groups = "drop") # A tibble: 42 x 4 sex gender species height <chr> <chr> <chr> <dbl> 1 female feminine Clawdite 168 2 female feminine Human NA 3 female feminine Kaminoan 213 4 female feminine Mirialan 168 5 female feminine Tholothian 184 6 female feminine Togruta 178 7 female feminine Twi'lek 178 8 hermaphroditic masculine Hutt 175 9 male masculine Aleena 79 10 male masculine Besalisk 198 # … with 32 more rows
where
今まで、条件にあったカラムに対する処理として、*_if()
、*_at()
、*_all()
などがありました。
ver1.0.0からは、それが非推奨となり新しくwhere()
の使用が推奨されるようになります。
以下の二つは同じ出力となります。
starwars %>% select(where(is.character))
starwars %>% select_if(is.character)
<出力>
name hair_color skin_color eye_color sex gender homeworld species <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> 1 Luke Skywalker blond fair blue male masculine Tatooine Human 2 C-3PO NA gold yellow none masculine Tatooine Droid 3 R2-D2 NA white, blue red none masculine Naboo Droid 4 Darth Vader none white yellow male masculine Tatooine Human 5 Leia Organa brown light brown female feminine Alderaan Human 6 Owen Lars brown, grey light blue male masculine Tatooine Human 7 Beru Whitesun lars brown light blue female feminine Tatooine Human
関数を意味する~
と併用することも可能です。
以下は、num型かつ平均値が3.5以上のカラムを選択ような方法です。
iris %>% select(where(~ is.numeric(.x) && mean(.x) > 3.5))
relocate
今まで、カラムの整列を柔軟を行う方法はなかったと思います。
今バージョンからrelocate()
がその役割を果たしてくれるようになりました。
height
をmass
の前の列に持ってくるには次にようにします。
> starwars %>% relocate(height, .before = mass) # A tibble: 87 x 14 name height mass hair_color skin_color eye_color birth_year sex gender homeworld species <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr> <chr> <chr> 1 Luke… 172 77 blond fair blue 19 male mascu… Tatooine Human 2 C-3PO 167 75 NA gold yellow 112 none mascu… Tatooine Droid 3 R2-D2 96 32 NA white, bl… red 33 none mascu… Naboo Droid 4 Dart… 202 136 none white yellow 41.9 male mascu… Tatooine Human
height
をmass
の後の列に持ってくるには次にようにします。
> starwars %>% relocate(height, .after = mass) # A tibble: 87 x 14 name mass height hair_color skin_color eye_color birth_year sex gender homeworld species <chr> <dbl> <int> <chr> <chr> <chr> <dbl> <chr> <chr> <chr> <chr> 1 Luke… 77 172 blond fair blue 19 male mascu… Tatooine Human 2 C-3PO 75 167 NA gold yellow 112 none mascu… Tatooine Droid 3 R2-D2 32 96 NA white, bl… red 33 none mascu… Naboo Droid 4 Dart… 136 202 none white yellow 41.9 male mascu… Tatooine Human
where()
を用いるとより柔軟なカラムの並び替えが可能です。
> starwars %>% relocate(where(is.character), where(is.numeric)) # A tibble: 87 x 14 name hair_color skin_color eye_color sex gender homeworld species height mass birth_year <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <int> <dbl> <dbl> 1 Luke… blond fair blue male mascu… Tatooine Human 172 77 19 2 C-3PO NA gold yellow none mascu… Tatooine Droid 167 75 112 3 R2-D2 NA white, bl… red none mascu… Naboo Droid 96 32 33 4 Dart… none white yellow male mascu… Tatooine Human 202 136 41.9
ここでも.after引数も併用可能です。
across
summarise_if()
のようなsummarise_*
系は非推奨となりました。
その代わりに、同じような処理を行うためにacross()
との併用が推奨することになりました。
where()
を用いてカラムを選択します。
> iris %>% + group_by(Species) %>% + summarise(across(.cols = where(is.numeric), + .fns = mean), + across(where(is.factor), nlevels), + n = n()) `summarise()` ungrouping output (override with `.groups` argument) # A tibble: 3 x 6 Species Sepal.Length Sepal.Width Petal.Length Petal.Width n <fct> <dbl> <dbl> <dbl> <dbl> <int> 1 setosa 5.01 3.43 1.46 0.246 50 2 versicolor 5.94 2.77 4.26 1.33 50 3 virginica 6.59 2.97 5.55 2.03 50
なお、以下の場合は生成されるカラム名が被ってしまうため、エラーになります。
iris %>% group_by(Species) %>% summarise(across(.cols = where(is.numeric), .fns = mean), across(.cols = where(is.numeric), .fns = sd))
複数の関数を適用する場合は、list()
で指定します。
iris %>% group_by(Species) %>% summarise(across(contains("Length"), list(mean = mean, sd = sd)))
生成されるカラム名の命名規則を.name
引数で指定することができます。
iris %>% group_by(Species) %>% summarise(across(starts_with("Sepal"), list(mean, sd), .names = "{col}.fn{fn}"))
rowwise
通常、レコード方向の操作が苦手です。
df <- tibble(id = 1:4, w = runif(4), x = runif(4), y = runif(4), z = runif(4))
> df %>% mutate(m = mean(c(x, y, z))) # A tibble: 4 x 6 id w x y z m <int> <dbl> <dbl> <dbl> <dbl> <dbl> 1 1 0.924 0.0631 0.369 0.863 0.511 2 2 0.158 0.222 0.422 0.201 0.511 3 3 0.578 0.185 0.601 0.954 0.511 4 4 0.226 0.491 0.786 0.971 0.511
rowwise()
を挟むことで、レコードごとの処理を行うことができます。
> df %>% rowwise() %>% mutate(m = mean(c(x, y, z))) # A tibble: 4 x 6 # Rowwise: id w x y z m <int> <dbl> <dbl> <dbl> <dbl> <dbl> 1 1 0.924 0.0631 0.369 0.863 0.432 2 2 0.158 0.222 0.422 0.201 0.282 3 3 0.578 0.185 0.601 0.954 0.580 4 4 0.226 0.491 0.786 0.971 0.749
c_across()
と併用することで、柔軟にカラムの選択が行えます。
以下のようにするとw列からz列までのカラムに対して、各レコード毎に関数を適用することできる。
df %>% rowwise() %>% mutate( sum = sum(c_across(w:z)), sd = sd(c_across(w:z)) )
# A tibble: 4 x 7 # Rowwise: id w x y z sum sd <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 1 0.924 0.0631 0.369 0.863 2.22 0.411 2 2 0.158 0.222 0.422 0.201 1.00 0.117 3 3 0.578 0.185 0.601 0.954 2.32 0.314 4 4 0.226 0.491 0.786 0.971 2.47 0.328
pivot_*
v1.0.0から追加されたものではないですが、個人的に使い方が覚えられないので、一緒にまとめておきます。
<あとで>