tidylog::でdplyr::関数のフィードバック
初めましての記事です。最近は、SHIROBAKO見てます。
Rの入り口はRstudioやtidyverseの誕生によって敷居がかなり低くなったと言いますが、普通に難しいです。プログラミング初心者で統計よくわからなければちゅらいです。(主はR歴1年弱)
なれないプログラミングですら難しいのに、データをどういう風に使いこなすかのイメージしながらがら操作するのが個人的には非常に難しい。
オブジェクトに入れたり、こまめにprint()
しなければ、基本的にはローデータと成果物(分析結果、プロット)しかよく見ないなんてことも...
処理関数実行による前後が分からなければRで楽しくなれない!!
tidyverse::
は分かりやすいとかいうけど分からないやい!!
###**そんなあなたに`tidylog::`**
dplyr::
使ったことがあれば難しいことは何もありません。
何それっていう人は宇宙本を読むのが一番いいです。
(僕は初めてRに触れたとき、教授から当然のように%>%
を使われて、は?ってなりました)
tidylog::
については英語読めなくても開発者のGithub見れば分かります。
要するに**dplyr::
の関数を実行する際にコンソール上でフィードバックをくれる**のです。
百聞は一見に如かず。同じコードで比較してみましょう。
環境
R version 3.5.1 (2018-07-02) -- "Feather Spray"
Copyright (C) 2018 The R Foundation for Statistical Computing
Platform: x86_64-w64-mingw32/x64 (64-bit)
tidyverse::
を使ったとき
> library(tidyverse)
-- Attaching packages --------------------------------------- tidyverse 1.2.1 --
√ ggplot2 3.0.0 √ purrr 0.2.5
√ tibble 1.4.2 √ dplyr 0.7.6
√ tidyr 0.8.1 √ stringr 1.4.0
√ readr 1.1.1 √ forcats 0.3.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
Warning message:
パッケージ ‘stringr’ はバージョン 3.5.2 の R の下で造られました
> data <- mtcars %>%
+ select(mpg,cyl,hp,am) %>%
+ filter(mpg > 15) %>%
+ mutate(mpg_round = round(mpg)) %>%
+ group_by(cyl, mpg_round, am) %>%
+ tally() %>%
+ filter(n >= 1)
head(data)
# A tibble: 6 x 4
# Groups: cyl, mpg_round [5]
cyl mpg_round am n
<dbl> <dbl> <dbl> <int>
1 4 21 1 1
2 4 22 0 1
3 4 23 0 1
4 4 23 1 1
5 4 24 0 1
6 4 26 1 1
素晴らしいですね。このスマートさがtidyverse()
の真骨頂。
tidylog::
を使ったとき
インストールはCRANから普通にできます
> library(tidylog)
次のパッケージを付け加えます: ‘tidylog’
以下のオブジェクトは ‘package:dplyr’ からマスクされています:
add_count, add_tally, anti_join, count, distinct, filter,
filter_all, filter_at, filter_if, full_join, group_by,
group_by_all, group_by_at, group_by_if, inner_join, left_join,
mutate, mutate_all, mutate_at, mutate_if, right_join, select,
select_all, select_at, select_if, semi_join, summarise,
summarise_all, summarise_at, summarise_if, summarize,
summarize_all, summarize_at, summarize_if, tally, top_n,
transmute, transmute_all, transmute_at, transmute_if
以下のオブジェクトは ‘package:stats’ からマスクされています:
filter
> data <- mtcars %>%
+ select(mpg,cyl,hp,am) %>%
+ filter(mpg > 15) %>%
+ mutate(mpg_round = round(mpg)) %>%
+ group_by(cyl, mpg_round, am) %>%
+ tally() %>%
+ filter(n >= 1)
select: dropped 7 variables (disp, drat, wt, qsec, vs, …)
filter: removed 6 out of 32 rows (19%)
mutate: new variable 'mpg_round' with 15 unique values and 0% NA
group_by: 3 grouping variables (cyl, mpg_round, am)
tally: now 20 rows and 4 columns, 2 group variables remaining (cyl, mpg_round)
filter (grouped): no rows removed
head(data)
# A tibble: 6 x 4
# Groups: cyl, mpg_round [5]
cyl mpg_round am n
<dbl> <dbl> <dbl> <int>
1 4 21 1 1
2 4 22 0 1
3 4 23 0 1
4 4 23 1 1
5 4 24 0 1
6 4 26 1 1
え、好き...
+ filter(n >= 1)
以下を見てください。それぞれの実行した関数のフィードバックが記載されています。
-
select()
でどの行が落とされたか -
filter()
でデータの全行のうち何行(データの何%)取り除かれたか -
mutate()
で何種類の値が挿入されたか(そのうちNA:欠損値は何%あるか) -
group_by()
はgroup_by()
-
tally()
で集計したよ - 最後の
filter()
は該当する条件なし
といったように、各関数ごとにフィードバックをくれるのでデータがどんな足跡をたどったか分かりやすい。データハンドリングを行っている途中でもデータがどんな形をしているかイメージしやすい気がします。どっちがいいのかはユーザー次第ですが、こういう選択肢があるのも知ってほしいです。
開発者のGithubに他の例もあるので見てみてください。
追記{tidylog}
1.0.0
{tidylog}
のアプデが入って、最新の{dplyr},{tidyr}
の関数に対応したそうです。
中でも、_join()
のフィードバックが感動的。
> iris2 <-
+ iris %>%
+ as_tibble() %>%
+ rowid_to_column() %>%
+ select(rowid,Petal.Length,Petal.Width)
select: dropped 3 variables (Sepal.Length, Sepal.Width, Species)
>
> iris %>%
+ as_tibble() %>%
+ rowid_to_column() %>%
+ select(rowid,Sepal.Length, Sepal.Width, Species) %>%
+ left_join(iris2,by = "rowid")
select: dropped 2 variables (Petal.Length, Petal.Width)
left_join: added 2 columns (Petal.Length, Petal.Width)
> rows only in x 0
> rows only in y ( 0)
> matched rows 150
> =====
> rows total 150
joinによって「追加された変数」と「マッチした要素数」を返してくれる。
※githubには、pivot_
に対応してるけど、なんかうまくいかないのでここでは割愛。詳しくは{tidylog}
のページを確認してください。
補足
-
tidylog::
が真価を発揮するのはmutate(name = purrr::map(data, fundtion()))
をつかったり、filter()
の中でstringr::
関数を使う時、複雑な処理による結果を一目で理解できます。 -
また、ビッグデータを扱う時、つまり
%>%
で繋いだ一つ一つの関数の処理に時間がかかるとき、フィードバックが関数の実行完了ごとに吐かれるので、データのトレースをたどりやするくなります。エラーが出てもどこまで走ってたか分かります。
最後まで、読んでいただきありがとうございました。