Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
dplyr 1.0.0の新機能 / dplyr 1.0.0
松村優哉
June 27, 2020
Programming
2
6.7k
dplyr 1.0.0の新機能 / dplyr 1.0.0
松村優哉
June 27, 2020
Tweet
Share
More Decks by 松村優哉
See All by 松村優哉
はじめての機械学習 / entrance-to-machine-learning2022
y__mattu
2
890
validateパッケージでデータを検証する / Data Validation with validate package
y__mattu
0
210
rstanの環境構築 / Set Up rstan
y__mattu
1
680
R言語とGo言語 / R and Go
y__mattu
1
380
はじめての機械学習 / Entrance to Machine Learning
y__mattu
0
510
平均値と中央値の違いについて
y__mattu
1
620
Other Decks in Programming
See All in Programming
フロントエンドエンジニアが変える現場のモデリング意識/modeling-awareness-changed-by-front-end-engineers
uggds
32
13k
SAM × Dockerでサーバーレス開発が超捗った話
yu_yukk_y
1
200
設計の考え方とやり方
masuda220
PRO
49
27k
クラウド KMS の活用 / TOKYO BLOCKCHAIN TECH MEETUP 2022
odanado
PRO
0
180
AWS Config Custom Rule、ノーコードでできるかな?
watany
0
250
読みやすいコード クラスメソッド 2022 年度新卒研修
januswel
0
2.9k
How to start contributing to Kubernetes Projects
ydfu
0
130
Getting Started With Data Structures
adoranwodo
1
260
테라폼으로 ECR 관리하기 (How to Manage ECR with Terraform)
posquit0
0
520
Automating Gradle benchmarks at N26
ubiratansoares
PRO
1
140
Pythonで鉄道指向プログラミング
usabarashi
0
130
Edge Side Frontend という新領域
mizchi
22
10k
Featured
See All Featured
Navigating Team Friction
lara
175
11k
Unsuck your backbone
ammeep
659
55k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
107
16k
Six Lessons from altMBA
skipperchong
14
1.4k
No one is an island. Learnings from fostering a developers community.
thoeni
9
1.3k
5 minutes of I Can Smell Your CMS
philhawksworth
196
18k
Fantastic passwords and where to find them - at NoRuKo
philnash
27
1.6k
What the flash - Photography Introduction
edds
62
10k
Building Adaptive Systems
keathley
25
1.1k
Clear Off the Table
cherdarchuk
79
290k
Building Flexible Design Systems
yeseniaperezcruz
310
34k
10 Git Anti Patterns You Should be Aware of
lemiorhan
638
52k
Transcript
dplyr1.0.0の新機能 @y__mattu 2020/6/27 Tokyo.R #86 応⽤セッション
誰︖ • 名前: 松村優哉 • 学⽣時代の専⾨: 計量経済学、 ベイズ統計、因果推論、マーケティング (研究室のAWSの管理とかもやってた) •
⾔語: R, Python • HR系企業でデータサイエンティストしてます • Tokyo.R 運営(雑⽤, ⾳響) @y__mattu ymattu 2
#宇宙本 3 あれからもう2年… RStudioのバージョンも上がったし、 パッケージも新機能がいろいろ登場した。 例えば、 tidyr 1.0.0の新機能 pivot_*() /
tidyr-pivot ※宇宙本に書いてある内容は、 基本的に今の時代でも使える内容です。
今回は、dplyr1.0.0について。 4 2020/3/10 訳: dply1.0.0もうすぐ出るよ。 新機能を⼀部紹介するね 訳: dplyr 1.0.0 出たぜ︕
2020/6/2 2020/5/7 訳:折返し地点︕
今⽇のお話 • dplyr1.0.0での変化 • 1.0.0で変更があったもの • 1.0.0で新しく追加されたもの の中から影響が⼤きそう、注⽬すべきポイント ※20分しかないので、要点を絞っていきます ※ただし、余談として
• 「新しいバージョンやパッケージを試すときのポイント」 • 「関数のライフサイクル」 みたいな話を挟んでいきます ※全変更点⼀覧はリリースノートを参照 5
早速dplyr 1.0.0を試してみよう︕ 〜新しいパッケージを試すときのポイント︕〜 6 Dockerを使うのが吉︕︕ Dockerを使うと、⾃分の環境を汚さずにお⼿軽に新しいものが試せます!
Dockerでdplyr1.0.0を試す 7 docker pull rocker/tidyverse:4.0.0 docker run \ -p 8787:8787
\ -v ~/Desktop/dplyr1:/home/rstudio \ -d --name try-dplyr_1 \ rocker/tidyverse:4.0.0 緑⾊のところは、それぞれ、ローカルのディレクトリ、コンテナ名をそれぞれ任意に設定 R 4.0.0 上でtidyverseが インストールされたRstudio環境
ブラウザで localhost:8787 に接続 8 ユーザー名はrstudio、 初期パスワードはrstudio
dply1.0.0がインストールされてます 9
使うデータ1 10 > library(dplyr) > glimpse(starwars) Rows: 87 Columns: 14
$ name <chr> "Luke Skywalker", "C-3PO", "R2-D2", "Darth Vader", "Leia Organa", "Owen La… $ height <int> 172, 167, 96, 202, 150, 178, 165, 97, 183, 182, 188, 180, 228, 180, 173, 1… $ mass <dbl> 77.0, 75.0, 32.0, 136.0, 49.0, 120.0, 75.0, 32.0, 84.0, 77.0, 84.0, NA, 11… $ hair_color <chr> "blond", NA, NA, "none", "brown", "brown, grey", "brown", NA, "black", "au… $ skin_color <chr> "fair", "gold", "white, blue", "white", "light", "light", "light", "white,… $ eye_color <chr> "blue", "yellow", "red", "yellow", "brown", "blue", "blue", "red", "brown"… $ birth_year <dbl> 19.0, 112.0, 33.0, 41.9, 19.0, 52.0, 47.0, NA, 24.0, 57.0, 41.9, 64.0, 200… $ sex <chr> "male", "none", "none", "male", "female", "male", "female", "none", "male"… $ gender <chr> "masculine", "masculine", "masculine", "masculine", "feminine", "masculine… $homeworld <chr> "Tatooine", "Tatooine", "Naboo", "Tatooine", "Alderaan", "Tatooine", "Tato… $ species <chr> "Human", "Droid", "Droid", "Human", "Human", "Human", "Human", "Droid", "H… $ films <list> [<"The Empire Strikes Back", "Revenge of the Sith", "Return of the Jedi",… $ vehicles <list> [<"Snowspeeder", "Imperial Speeder Bike">, <>, <>, <>, "Imperial Speeder … $ starships <list> [<"X-wing", "Imperial shuttle">, <>, <>, "TIE Advanced x1", <>, <>, <>, <…
使うデータ2 11 > glimpse(iris) Rows: 150 Columns: 5 $ Sepal.Length
<dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3, 5.8, 5.7, 5.4, 5.1, … $ Sepal.Width <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3.0, 3.0, 4.0, 4.4, 3.9, 3.5, … $ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, 1.4, … $ Petal.Width <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.4, 0.4, 0.3, … $ Species <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, se…
使うデータ3 12 > df <- expand.grid(x = 1:3, y =
3:1) > df x y 1 1 3 2 2 3 3 3 3 4 1 2 5 2 2 6 3 2 7 1 1 8 2 1 9 3 1
dplyr1.0.0の変更点その0 ロゴ
ロゴが変わっただと︕︖ 14 旧ロゴ 新ロゴ
dplyr1.0.0の変更点その1 summarise()の挙動
.groups引数で、グループの挙動を制御 16 starwars %>% group_by(gender, homeworld) %>% summarise(height = mean(height))
`summarise()` regrouping output by 'gender' (override with `.groups` argument)# A tibble: 58 x 3 # A tibble: 58 x 3 # Groups: gender [3] gender homeworld height <chr> <chr> <dbl> 1 feminine Alderaan 150 2 feminine Chandrila 150 3 feminine Coruscant 176. 4 feminine Kamino 213 5 feminine Mirial 168 6 feminine Naboo 162. 7 feminine Ryloth 178 8 feminine Shili 178 9 feminine Tatooine 164 10 feminine Zolan 168 # … with 48 more rows ???
.groups引数でグルーピングを制御できるようになった 17 starwars %>% group_by(gender, homeworld) %>% summarise(. groups =
“drop_last”, height = mean(height)) # A tibble: 58 x 3 # Groups: gender [3] gender homeworld height <chr> <chr> <dbl> 1 feminine Alderaan 150 2 feminine Chandrila 150 3 feminine Coruscant 176. 4 feminine Kamino 213 5 feminine Mirial. 168 6 feminine Naboo 162. 7 feminine Ryloth 178 8 feminine Shili 178 9 feminine Tatooine 164 10 feminine Zolan 168 # … with 48 more rows 他に、”drop”と”keep”と”rowwiseが 選択可能 最後のグルーピング(ここではhomeworld) が消えた
.groups引数でグルーピングを制御できるようになった 18 starwars %>% group_by(gender, homeworld) %>% summarise(. groups =
“drop”, height = mean(height)) # A tibble: 58 x 3 gender homeworld height <chr> <chr> <dbl> 1 feminine Alderaan 150 2 feminine Chandrila 150 3 feminine Coruscant 176. 4 feminine Kamino 213 5 feminine Mirial. 168 6 feminine Naboo 162. 7 feminine Ryloth 178 8 feminine Shili 178 9 feminine Tatooine 164 10 feminine Zolan 168 # … with 48 more rows すべてのグルーピング が消えた
.groups引数でグルーピングを制御できるようになった 19 starwars %>% group_by(gender, homeworld) %>% summarise(. groups =
keep”, height = mean(height)) # A tibble: 58 x 3 # Groups: gender, homeworld [58] gender homeworld height <chr> <chr> <dbl> 1 feminine Alderaan 150 2 feminine Chandrila 150 3 feminine Coruscant 176. 4 feminine Kamino 213 5 feminine Mirial. 168 6 feminine Naboo 162. 7 feminine Ryloth 178 8 feminine Shili 178 9 feminine Tatooine 164 10 feminine Zolan 168 # … with 48 more rows すべてのグルーピング が残る
注意︕.groupsを書かなかったときの挙動 20 dplyr::summarise()のhelp .groupsを指定しない場合、結果の⼤きさが1のときは”drop_last”が、 ⼤きさが変動する場合は”keep”になります。 options(“dplyr.summarise.inform” = FALSE)をやらない限り、 どれが選ばれたのかメッセージとして出⼒されます。 しばらくは明⽰的に.groupsを書いたほうがトラブルが少なくて済みそう
dplyr1.0.0の変更点その2 rowwise()
そもそもrowwise()ってどんな関数︖ 22 df %>% mutate(m = mean(c(x, y))) x y
m 1 1 3 2 2 2 3 2 3 3 3 2 4 1 2 2 5 2 2 2 6 3 2 2 7 1 1 2 8 2 1 2 9 3 1 2 もともと、レコード⽅向の操作は苦⼿ なので、それを解消するもの df %>% rowwise() %>% mutate(m = mean(c(x, y))) Source: local data frame [9 x 3] Groups: <by row> # A tibble: 9 x 3 x y m <int> <int> <dbl> 1 1 3 2 2 2 3 2.5 3 3 3 3 4 1 2 1.5 5 2 2 2 6 3 2 2.5 7 1 1 1 8 2 1 1.5 9 3 1 2
rowwiseの歴史 23 • 2014年頃(dplyr0.2くらい) →rowwise()はすでにあった • 2017年頃(dplyr0.7くらい) →purrrパッケージやtidyr::nest()の充実で 推奨されなくなる (将来的になくなるとの⾒解も)
• 2019年頃(dplyr0.8くらい) →questioning(使ってもいいけど、ちょっ とどうなんだろう︖でも代替⼿段はない)と いうステータスになっていた 参考: do()とかrowwise()は今から覚える必要はない(たぶん) https://notchained.hatenablog.com/entry/2017/11/15/212117 df %>% mutate(m = pmap(…)) みたいな書き⽅
dplyr1.0.0では、正式に使ってOKに (stableというステータスに) 24 df %>% rowwise() %>% mutate(m = mean(c(x,
y))) Source: local data frame [9 x 3] Groups: <by row> # A tibble: 9 x 3 x y m <int> <int> <dbl> 1 1 3 2 2 2 3 2.5 3 3 3 3 4 1 2 1.5 5 2 2 2 6 3 2 2.5 7 1 1 1 8 2 1 1.5 9 3 1 2 使い⽅はこれまでと⼀緒 ちなみに、 「purrrの機能を減らして dplyrでもっと⾊々やれるようにしよう」 という動きもあるみたいです 昔purrrlyrというパッケージもあったし、 purrrとdplyrの関係はこれからも変わっていきそう… ※いまはretiredという扱い ※
dplyr1.0.0の追加関数その1 across(), where()
***_at(), ***_if(), ***_allの書き⽅が変わります︕ 26 starwars %>% group_by(species) %>% filter(n() >
1) %>% summarise_at(vars(gender, homeworld), n_distinct)) species gender homeworld <char> <int> <int> 1: Droid 2 3 2: Gungan 1 1 3: Human 2 16 4: Kaminoan 2 1 5: Mirialan 1 1 6: Twi'lek 2 1 7: Wookiee 1 1 8: Zabrak 1 2 9: <NA> 2 3 特定の列だけに、特定の処理をする書き⽅ starwars %>% group_by(species) %>% filter(n() > 1) %>% summarise(across(c(gender, homeworld), n_distinct)) species gender homeworld <char> <int> <int> 1: Droid 2 3 2: Gungan 1 1 3: Human 2 16 4: Kaminoan 2 1 5: Mirialan 1 1 6: Twi'lek 2 1 7: Wookiee 1 1 8: Zabrak 1 2 9: <NA> 2 3 複数列はc()でくくる (tidyr::pivot_***() と同じ書き⽅) ***_atの場合
27 starwars %>% group_by(species) %>% filter(n() > 1) %>% summarise_if(is.numeric,
mean, na.rm = TRUE) species height mass birth_year <char> <num> <num> <num> 1: Droid 140.0000 69.75000 53.33333 2: Gungan 208.6667 74.00000 52.00000 3: Human 176.6452 82.78182 53.41200 4: Kaminoan 221.0000 88.00000 NaN 5: Mirialan 168.0000 53.10000 49.00000 6: Twi'lek 179.0000 55.00000 48.00000 7: Wookiee 231.0000 124.00000 200.00000 8: Zabrak 173.0000 80.00000 54.00000 9: <NA> 160.0000 48.00000 62.00000 starwars %>% group_by(species) %>% filter(n() > 1) %>% summarise(across(where(is.numeric), mean, na.rm = TRUE)) `summarise()` ungrouping output (override with `.groups` argument) # A tibble: 9 x 4 species. height mass birth_year <chr> <dbl> <dbl> <dbl> 1 Droid 131. 69.8 53.3 2 Gungan 209. 74. 52 3 Human 177. 82.8. 53.4 4 Kaminoan 221 88. NaN 5 Mirialan 168. 53.1. 49 6 Twi'lek 179 55. 48 7 Wookiee 231 124 200 8 Zabrak. 173 80 54 9 NA 181. 48 62 ***_ifの場合 数値型の列だけを処理
***_at() ***(across(列の指定, 処理)) ***_if ***(across(where(列の型の指定), 処理)) ***_all ***(across(everything(), 処理)) ***_at(),
***_if(), ***_allとの対応 28 ***には、mutate/summariseが⼊る
dplyr1.0.0の追加関数その2 relocate()
列の並び替えを簡単にできる関数 30 iris %>% relocate(Species, .before =Sepal.Length) %>% head() Species
Sepal.Length Sepal.Width Petal.Length Petal.Width 1 setosa 5.1 3.5 1.4 0.2 2 setosa 4.9 3.0 1.4 0.2 3 setosa 4.7 3.2 1.3 0.2 4 setosa 4.6 3.1 1.5 0.2 5 setosa 5.0 3.6 1.4 0.2 6 setosa 5.4 3.9 1.7 0.4 ※ あとに持っていきたいときは .after
dplyr1.0.0の追加関数その3 slice_***()
いくつかの関数がslice_***()にまとまります 32 sample_n() sample_frac() ランダムにN件(fracの場合は割合)抽出 top_n() top_frac() 上位N件(fracの場合は割合)抽出 slice_sample() slice_max()
slice_min() head() tail() 最初(最後)のN件を抽出 slice_head() slice_tail() ※グループ化されていると グループごとにN件 utils::
関数のライフサイクルについて 主に開発者向け
lifecycle パッケージ 34 https://lifecycle.r-lib.org/articles/lifecycle.html 旧: retired
lifecycle パッケージの使い⽅ 35 > mutate_at function (.tbl, .vars, .funs, ...,
.cols = NULL) { lifecycle::signal_superseded("1.0.0", "mutate_at()", "across()") .vars <- check_dot_cols(.vars, .cols) funs <- manip_at(.tbl, .vars, .funs, enquo(.funs), caller_env(), .include_group_vars = TRUE, ..., .caller = "mutate_at") mutate(.tbl, !!!funs) } <bytecode: 0x55fb29fd93f8> <environment: namespace:dplyr> 例: mutate_at() バージョン、旧関数、代⽤の新関数を記述
この資料で出てきた旧関数の1.0.0での扱い 36 rowwise() ***_at() ***_if() ***_all() top_n() top_frac() sample_n() sample_frac()
まとめ
まとめ • dplyrがついに1.0.0に︕ • ***_at(), ***_if(), ***_all()の書き⽅が変わる →***(across(…))に︕ →以前のコードが動かなくなることはすぐにはないけど 今後の書き⽅は変えたほうが良い
• summariseの.groups引数は注意︕ • rowwise()を含め、purrrパッケージとの対応は今後もアップデート がありそうなので、備えよう 38
その他の参考リンク • dplyr 1.0.0 available now! – Tidyverse.org https://www.tidyverse.org/blog/2020/06/dplyr-1-0-0/ •
dplyr 1.0.0 https://speakerdeck.com/romainfrancois/dplyr-1-dot-0-0 • dplyr ver.1.0.0に追加された関数 + α - 名前はまだない https://saltcooky.hatenablog.com/entry/2020/06/13/161919 • dplyr 1.00のacross関数が便利だった - 世界銀⾏で働くデータサ イエンティストのブログ https://datascience-blog.com/2020/06/02/202427 39
Enjoy!