Upgrade to Pro — share decks privately, control downloads, hide ads and more …

dplyr 1.0.0の新機能 / dplyr 1.0.0

dplyr 1.0.0の新機能 / dplyr 1.0.0

松村優哉

June 27, 2020
Tweet

More Decks by 松村優哉

Other Decks in Programming

Transcript

  1. dplyr1.0.0の新機能
    @y__mattu
    2020/6/27
    Tokyo.R #86 応⽤セッション

    View Slide

  2. 誰︖
    • 名前: 松村優哉
    • 学⽣時代の専⾨: 計量経済学、
    ベイズ統計、因果推論、マーケティング
    (研究室のAWSの管理とかもやってた)
    • ⾔語: R, Python
    • HR系企業でデータサイエンティストしてます
    • Tokyo.R 運営(雑⽤, ⾳響)
    @y__mattu
    ymattu
    2

    View Slide

  3. #宇宙本
    3
    あれからもう2年…
    RStudioのバージョンも上がったし、
    パッケージも新機能がいろいろ登場した。
    例えば、
    tidyr 1.0.0の新機能 pivot_*() / tidyr-pivot
    ※宇宙本に書いてある内容は、
    基本的に今の時代でも使える内容です。

    View Slide

  4. 今回は、dplyr1.0.0について。
    4
    2020/3/10
    訳: dply1.0.0もうすぐ出るよ。
    新機能を⼀部紹介するね
    訳: dplyr 1.0.0 出たぜ︕
    2020/6/2
    2020/5/7
    訳:折返し地点︕

    View Slide

  5. 今⽇のお話
    • dplyr1.0.0での変化
    • 1.0.0で変更があったもの
    • 1.0.0で新しく追加されたもの
    の中から影響が⼤きそう、注⽬すべきポイント
    ※20分しかないので、要点を絞っていきます
    ※ただし、余談として
    • 「新しいバージョンやパッケージを試すときのポイント」
    • 「関数のライフサイクル」
    みたいな話を挟んでいきます
    ※全変更点⼀覧はリリースノートを参照
    5

    View Slide

  6. 早速dplyr 1.0.0を試してみよう︕
    〜新しいパッケージを試すときのポイント︕〜
    6
    Dockerを使うのが吉︕︕
    Dockerを使うと、⾃分の環境を汚さずにお⼿軽に新しいものが試せます!

    View Slide

  7. 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環境

    View Slide

  8. ブラウザで localhost:8787 に接続
    8
    ユーザー名はrstudio、
    初期パスワードはrstudio

    View Slide

  9. dply1.0.0がインストールされてます
    9

    View Slide

  10. 使うデータ1
    10
    > library(dplyr)
    > glimpse(starwars)
    Rows: 87
    Columns: 14
    $ name "Luke Skywalker", "C-3PO", "R2-D2", "Darth Vader", "Leia Organa", "Owen La…
    $ height 172, 167, 96, 202, 150, 178, 165, 97, 183, 182, 188, 180, 228, 180, 173, 1…
    $ mass 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 "blond", NA, NA, "none", "brown", "brown, grey", "brown", NA, "black", "au…
    $ skin_color "fair", "gold", "white, blue", "white", "light", "light", "light", "white,…
    $ eye_color "blue", "yellow", "red", "yellow", "brown", "blue", "blue", "red", "brown"…
    $ birth_year 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 "male", "none", "none", "male", "female", "male", "female", "none", "male"…
    $ gender "masculine", "masculine", "masculine", "masculine", "feminine", "masculine…
    $homeworld "Tatooine", "Tatooine", "Naboo", "Tatooine", "Alderaan", "Tatooine", "Tato…
    $ species "Human", "Droid", "Droid", "Human", "Human", "Human", "Human", "Droid", "H…
    $ films [$ vehicles [, <>, <>, <>, "Imperial Speeder …
    $ starships [, <>, <>, "TIE Advanced x1", <>, <>, <>,

    View Slide

  11. 使うデータ2
    11
    > glimpse(iris)
    Rows: 150
    Columns: 5
    $ Sepal.Length 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 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 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 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 setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, se…

    View Slide

  12. 使うデータ3
    12
    > df > 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

    View Slide

  13. dplyr1.0.0の変更点その0
    ロゴ

    View Slide

  14. ロゴが変わっただと︕︖
    14
    旧ロゴ 新ロゴ

    View Slide

  15. dplyr1.0.0の変更点その1
    summarise()の挙動

    View Slide

  16. .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

    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
    ???

    View Slide

  17. .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

    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)
    が消えた

    View Slide

  18. .groups引数でグルーピングを制御できるようになった
    18
    starwars %>%
    group_by(gender, homeworld) %>%
    summarise(. groups = “drop”,
    height = mean(height))
    # A tibble: 58 x 3
    gender homeworld height

    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
    すべてのグルーピング
    が消えた

    View Slide

  19. .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

    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
    すべてのグルーピング
    が残る

    View Slide

  20. 注意︕.groupsを書かなかったときの挙動
    20
    dplyr::summarise()のhelp
    .groupsを指定しない場合、結果の⼤きさが1のときは”drop_last”が、
    ⼤きさが変動する場合は”keep”になります。
    options(“dplyr.summarise.inform” = FALSE)をやらない限り、
    どれが選ばれたのかメッセージとして出⼒されます。
    しばらくは明⽰的に.groupsを書いたほうがトラブルが少なくて済みそう

    View Slide

  21. dplyr1.0.0の変更点その2
    rowwise()

    View Slide

  22. そもそも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:
    # A tibble: 9 x 3
    x y m

    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

    View Slide

  23. 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(…))
    みたいな書き⽅

    View Slide

  24. dplyr1.0.0では、正式に使ってOKに
    (stableというステータスに)
    24
    df %>%
    rowwise() %>%
    mutate(m = mean(c(x, y)))
    Source: local data frame [9 x 3]
    Groups:
    # A tibble: 9 x 3
    x y m

    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という扱い

    View Slide

  25. dplyr1.0.0の追加関数その1
    across(), where()

    View Slide

  26. ***_at(), ***_if(), ***_allの書き⽅が変わります︕
    26
    starwars %>%
    group_by(species) %>%
    filter(n() > 1) %>%
    summarise_at(vars(gender, homeworld),
    n_distinct))
    species gender homeworld

    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: 2 3
    特定の列だけに、特定の処理をする書き⽅
    starwars %>%
    group_by(species) %>%
    filter(n() > 1) %>%
    summarise(across(c(gender, homeworld),
    n_distinct))
    species gender homeworld

    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: 2 3
    複数列はc()でくくる
    (tidyr::pivot_***()
    と同じ書き⽅)
    ***_atの場合

    View Slide

  27. 27
    starwars %>%
    group_by(species) %>%
    filter(n() > 1) %>%
    summarise_if(is.numeric,
    mean, na.rm = TRUE)
    species height mass birth_year

    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: 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

    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の場合
    数値型の列だけを処理

    View Slide

  28. ***_at() ***(across(列の指定, 処理))
    ***_if ***(across(where(列の型の指定), 処理))
    ***_all ***(across(everything(), 処理))
    ***_at(), ***_if(), ***_allとの対応
    28
    ***には、mutate/summariseが⼊る

    View Slide

  29. dplyr1.0.0の追加関数その2
    relocate()

    View Slide

  30. 列の並び替えを簡単にできる関数
    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

    View Slide

  31. dplyr1.0.0の追加関数その3
    slice_***()

    View Slide

  32. いくつかの関数が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::

    View Slide

  33. 関数のライフサイクルについて
    主に開発者向け

    View Slide

  34. lifecycle パッケージ
    34
    https://lifecycle.r-lib.org/articles/lifecycle.html
    旧: retired

    View Slide

  35. lifecycle パッケージの使い⽅
    35
    > mutate_at
    function (.tbl, .vars, .funs, ..., .cols = NULL)
    {
    lifecycle::signal_superseded("1.0.0", "mutate_at()", "across()")
    .vars funs .include_group_vars = TRUE, ..., .caller = "mutate_at")
    mutate(.tbl, !!!funs)
    }


    例: mutate_at()
    バージョン、旧関数、代⽤の新関数を記述

    View Slide

  36. この資料で出てきた旧関数の1.0.0での扱い
    36
    rowwise() ***_at()
    ***_if()
    ***_all()
    top_n()
    top_frac()
    sample_n()
    sample_frac()

    View Slide

  37. まとめ

    View Slide

  38. まとめ
    • dplyrがついに1.0.0に︕
    • ***_at(), ***_if(), ***_all()の書き⽅が変わる
    →***(across(…))に︕
    →以前のコードが動かなくなることはすぐにはないけど
    今後の書き⽅は変えたほうが良い
    • summariseの.groups引数は注意︕
    • rowwise()を含め、purrrパッケージとの対応は今後もアップデート
    がありそうなので、備えよう
    38

    View Slide

  39. その他の参考リンク
    • 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

    View Slide

  40. Enjoy!

    View Slide