前回までの進捗
こんにちは、小幡です。Rを学んでおります。
前回は「dplyr」というパッケージを使ってデータ集計の7つの処理のうち、select
、arrange
、filter
の3つを勉強しました。列を絞る、特定の順番で並び替える、行の一部を取り出す、といった操作ができるようになりました。一つ一つは今までExcelでやっていたような単純な操作ですが、組み合わせてコードを書くことで少し高度なこともできるようになった気がします。
そして今回は、前回と同じ「dplyr」のパッケージの残りの基本的な関数について勉強します。
※編集部注:記事分割の関係上、シリーズを全7回から全8回に変更しました。
もう全体の中では折返し地点を超えています。だんだんとゴールが見えてきました…! では早速、輿石さんよろしくお願いします!
データの要約、列の追加、グループ化の3操作
輿石さん:さて、今回はデータフレームに対する7つの操作のうち、残りの4つをお伝えしていきます。集計処理を行うsummarise
や、処理をグループ化するgroup_by
などの基本操作を覚えたら、Rはさらに強力なツールとなっているはずですよ。
株式会社ヴァリューズ ソリューション局 マネジャー
輿石拓真(こしいし・たくま)さん
輿石さん:前回と同じように健康系のサプリメントECを想定したサンプルのデータを使っていきます。次のコードを打ち込んで、データフレームを用意しましょう。
# packageの読み込み
library(tidyverse)
# データの読み込み
kenko_ec_data <- read_tsv("https://adcreative.valuesccg.net/manamina/article/manaminar/kenko_ec_sample.tsv")
kenko_ec_data
●コンソールの出力内容
#> # A tibble: 10,361 x 7
#> userid purchase_date item_category series price purchase_amount
#> <chr> <date> <chr> <chr> <dbl> <int>
#> 1 K00002 2020-01-07 マルチ酵素 お徳用 3186 1
#> 2 K00003 2020-03-24 カルシウム プレミアム~ 934 1
#> 3 K00005 2020-01-30 クレアチン スタンダー~ 2560 1
#> 4 K00008 2020-01-30 乳酸菌 プレミアム~ 2574 1
#> 5 K00009 2020-01-15 クエン酸 スタンダー~ 1080 1
#> 6 K00010 2020-03-22 ビタミンB お徳用 1617 1
#> 7 K00019 2020-03-21 グルコサミン お徳用 5329 3
#> 8 K00023 2020-01-05 ビタミンB プレミアム~ 778 1
#> 9 K00027 2020-03-13 スピルリナ お徳用 5713 5
#> 10 K00031 2020-02-12 BCAA スタンダー~ 3694 1
#> # ... with 10,351 more rows, and 1 more variable: item_name <chr>
■4.データを要約する
輿石さん:では早速、データを要約・集計する関数「summarise」について学びましょう。使い方はsummarise(データフレーム, 新列名1 = 式1, 新列名 = 式2, …)
の形です。summarise
はデータフレームを集計し、集計値に要約する働きをします。次の図は、1つのデータフレームからUU(人数)とPV数合計を集計するイメージ図です。summarise
に記載した列名と集計値だけの1行のデータフレームが出力されます。
輿石さん:例えばkenko_ec_data
から「ユーザーIDの種類の数=UU数」と「売れた個数の総計」を知りたいという場合は次のようにします。kenko_ec_data
をuserid、purchase_amountで集計してみましょう。
summarise(kenko_ec_data, uu = n_distinct(userid), purchase_amount_sum = sum(purchase_amount))
●コンソールの出力内容
# A tibble: 1 x 2
uu purchase_amount_sum
<int> <dbl>
1 3000 17398
輿石さん:データフレームkenko_ec_data
に対して、合計する関数sum()
でpurchase_amount
を足し上げています。また、関数n_distinct()
は重複のない値の個数を数える関数で、この場合にはuserid
の数なのでユニークユーザー数になりますね。それぞれを新しい列purchase_amount_sum
とuu
として出力しています。このデータフレームには3000人分のデータが含まれていて、合計で17398点の商品が購入されているのがわかりましたね。
輿石さん:ここではsum()
とn_distinct()
という関数を使っていますが、このような、集計に使う関数のバリエーションを増やすとできることが広がります。例えば関数max()
で列の中で一番多い数値を出したり、関数mean()
で平均値を出したり。
小幡:なるほど、まだまだいろいろ関数があるんですね…!
輿石さん:そうですね。集計によく使う関数をまとめておきます。これらはデータフレームの列をインプットに1つの集計値を出力するという特徴があり、僕は集計関数と呼んでます。
関数 | 関数の概要 |
sum() | 合計値 |
mean() | 平均値 |
max()/min() | 最大値/最小値 |
n_distinct() | ユニークな要素の数(要素の種類の数) |
n() | 行数 ※引数は何も取らないので注意 |
■5.新しい列を追加する
輿石さん:今度は「mutate」です。もともとの列に処理をして、新しい列を追加する関数ですね。使い方はmutate(データフレーム, 新列名1 = 式1, 新列名2 = 式2, …)
という形。先ほどのsummariseと引数は似ていますが、要約するのではなく、列を追加する働きをします。
横に新しく列が追加される
輿石さん:ユニークユーザー数をuu
、支払い金額(価格に購入数をかけたもの)をpayment
という列として追加してみましょう。
kenko_ec_data_m <- mutate(kenko_ec_data, uu = n_distinct(userid), payment = price * purchase_amount) # 追加した列が確認しようにselectで列を絞って表示 select(kenko_ec_data_m, userid, price, purchase_amount, uu, payment)
# A tibble: 10,361 x 5
userid price purchase_amount uu payment
<chr> <dbl> <dbl> <int> <dbl>
1 K00002 3186 1 3000 3186
2 K00003 934 1 3000 934
3 K00005 2560 1 3000 2560
4 K00008 2574 1 3000 2574
5 K00009 1080 1 3000 1080
6 K00010 1617 1 3000 1617
7 K00019 5329 3 3000 15987
8 K00023 778 1 3000 778
9 K00027 5713 5 3000 28565
10 K00031 3694 1 3000 3694
# ... with 10,351 more rows
小幡:uu
にはすべて同じ値が入っていますね?
輿石さん:mutate
の中でuu
のように1つの値を返す計算が行われると、すべての行に同じ1つの値が格納されます。summarise
で勉強した集計関数を使うケースですね。集計以外の計算を行うとそれぞれの行ごとに計算が行われます。単純に2倍するとか、列同士を足し算する、割り算するなどが当てはまります。
小幡:なるほど、分かりました!
■6.グループ化された集計を行う
輿石さん:本日最後の操作はgroup_by
です。これはsummariseをはじめとする今まで勉強してきたデータフレームに変更を加える関数と一緒に使うことで真価を発揮します。group_by(データフレーム, 列1, 列2, ...)というように列名を指定します。試しにgroup_by
を実行してみましょう。
group_by(kenko_ec_data, item_category, series)●コンソールの出力内容
# A tibble: 10,361 x 7
# Groups: item_category, series [154]
userid purchase_date item_category series price purchase_amount item_name
<chr> <date> <chr> <chr> <dbl> <dbl> <chr>
1 K00002 2020-01-07 マルチ酵素 お徳用 3186 1 マルチ酵素 サプリメント お徳用 90日分
2 K00003 2020-03-24 カルシウム プレミアム 934 1 カルシウム サプリメント プレミアム 30日分
3 K00005 2020-01-30 クレアチン スタンダード 2560 1 クレアチン サプリメント スタンダード 30日分
4 K00008 2020-01-30 乳酸菌 プレミアム 2574 1 乳酸菌 サプリメント プレミアム 30日分
5 K00009 2020-01-15 クエン酸 スタンダード 1080 1 クエン酸 サプリメント スタンダード 30日分
6 K00010 2020-03-22 ビタミンB お徳用 1617 1 ビタミンB サプリメント お徳用 90日分
7 K00019 2020-03-21 グルコサミン お徳用 5329 3 グルコサミン サプリメント お徳用 90日分
8 K00023 2020-01-05 ビタミンB プレミアム 778 1 ビタミンB サプリメント プレミアム 30日分
9 K00027 2020-03-13 スピルリナ お徳用 5713 5 スピルリナ サプリメント お徳用 90日分
10 K00031 2020-02-12 BCAA スタンダード 3694 1 BCAA サプリメント スタンダード 30日分
# ... with 10,351 more rows
小幡:あれ、一見もとのkenko_ec_data
から何も変わっていないように見えますが…。
輿石さん:そうですね。ただ、出力結果の2行目に「# Groups: item_category, series [154]」と記載されているのが分かりますか? これはデータフレームがitem_category
とseries
の組み合わせで154個にグループ化されていることを表しています。見た目は変わりませんが、実はデータフレームが154個に分割されているんです。
小幡:実は分割されている...?
輿石さん:グループ化したデータフレームをsummarise
で集計してみましょう。
kenko_ec_data_g <- group_by(kenko_ec_data, item_category) summarise(kenko_ec_data_g, uu = n_distinct(userid))
# A tibble: 54 x 2
item_category uu
<chr> <int>
1 BCAA 322
2 DHA 236
3 EPA 40
4 L-グルタミン 138
5 L-シトルリン 215
6 L-リジン 57
7 アミノ酸 236
8 ウコン 160
9 オルニチン 141
10 カゼインプロテイン 64
# ... with 44 more rows
小幡:group_by
に指定したカテゴリごとにuu数が集計されてますね!
輿石さん:group_by
をした後は、group_by
に指定した列に含まれる種類ごとに処理が行われるんです。下図を見てください。group_by
をすると、データフレームが指定した列の種類別に分割されて、それぞれにsummarise
が適用されて、最後は1つにくっついて出力される、というイメージを持ってください。
小幡:group_by
と書くだけで、実は裏で分割が行われていて、何回も集計を繰り返してくれているんですね。
輿石さん:summarise
だけではなくmutate
やfilter
も、同じようにグループ化したデータフレームに使うとグループごとに適応されます。最後に1点注意ですが、summarise
を行うとグループの情報が1列なくなります。実際にコードを実行して確かめてみましょう。
kenko_ec_data_g2 <- group_by(kenko_ec_data, item_category, series) summarise(kenko_ec_data_g2, uu = n_distinct(userid))●コンソールの出力内容
# A tibble: 154 x 3
# Groups: item_category [54]
item_category series uu
<chr> <chr> <int>
1 BCAA お徳用 87
2 BCAA スタンダード 173
3 BCAA プレミアム 103
4 DHA お徳用 54
5 DHA スタンダード 112
6 DHA プレミアム 84
7 EPA お徳用 5
8 EPA スタンダード 20
9 EPA プレミアム 16
10 L-グルタミン お徳用 54
# ... with 144 more rows
輿石さん: item_category
と series
の組み合わせでグループ化しましたが、summarise
の出力結果はitem_category
だけになっています。「# Groups: item_category [54]」という記載から分かりますね。慣れるまでは「今どの列でグループ化されているんだろう?」と確認しながら進めると良いと思います。グループ化を解除したいときはungroup(グループ化されたデータフレーム)
と実行します。覚えておきましょう。
輿石さん: 最後に練習問題を1題解いてみましょう。
小幡:はいっ!
輿石さん:kenko_ec_data
から、単価(price
)が1000以上の商品(item_category
とseries
の組み合わせを商品とします)の中で、売上が大きいランキングを作成してください。ついでに商品の購入者数もわかるようなランキングにしましょう。
小幡:少し難しそうですがチャレンジしてみます!
輿石さん:今まで勉強した関数を使って少しずつデータフレームを加工していけばたどり着けます。単純な処理を組み合わせることを意識してやってみましょう!
考える小幡さん
小幡:はい、出来ました!
# 練習問題 # まず、1000円以上の商品に絞ったデータフレームにする kenko_ec_data_tmp1 <- filter(kenko_ec_data, price >= 1000) # 売上を計算したいので、単価×購入数で売上を表す列を追加する。 kenko_ec_data_tmp2 <- mutate(kenko_ec_data_tmp1, payment = price * purchase_amount) # 「商品ごと」なので、item_category,とseriesの2列でグループ化する。 kenko_ec_data_tmp3 <- group_by(kenko_ec_data_tmp2, item_category, series) # summariseで集計。 kenko_ec_data_tmp4 <- summarise(kenko_ec_data_tmp3, payment_sum = sum(payment), uu = n_distinct(userid)) # ランキングなのでarrangeで降順に並び替える。 output <- arrange(kenko_ec_data_tmp4, desc(payment_sum)) output●コンソールの出力内容
# A tibble: 140 x 4
# Groups: item_category [53]
item_category series payment_sum uu
<chr> <chr> <dbl> <int>
1 ホエイプロテイン お徳用 6846400 395
2 ホエイプロテイン プレミアム 3530228 391
3 ホエイプロテイン スタンダード 2571828 358
4 BCAA お徳用 1904843 87
5 マルチビタミン&ミネラル お徳用 1894352 219
6 乳酸菌 お徳用 1400652 136
7 BCAA スタンダード 1381556 173
8 BCAA プレミアム 801934 103
9 コラーゲン お徳用 788400 88
10 ビフィズス菌 お徳用 742720 104
# ... with 130 more rows
小幡:単価1000円以上の商品の中で一番売り上げが大きいのはホエイプロテインのお徳用で、395人が購入していますね。
輿石さん:正解です!dplyrにも慣れてきましたね!今回はここまでです。次回はデータフレームを結合する「JOIN」と、連続した処理の記述に便利な「パイプ演算子」を勉強しましょう。
まとめ
今回でdplyrパッケージの7つの基本操作のうち、6つを学び終えました。dplyrの学習にも終わりが見えてきて、少し難しい集計もできるようになってきた気がします!
# packageの読み込み library(tidyverse) # データの読み込み kenko_ec_data <- read_tsv("https://adcreative.valuesccg.net/manamina/article/manaminar/kenko_ec_sample.tsv") kenko_ec_data # summariseでデータを集計する summarise(kenko_ec_data, uu = n_distinct(userid), purchase_amount_sum = sum(purchase_amount)) # mutateで列を追加する kenko_ec_data_m <- mutate(kenko_ec_data, uu = n_distinct(userid), payment = price * purchase_amount) ## 列追加が見やすいようにselectで列を絞る select(kenko_ec_data_m, userid, price, purchase_amount, uu, payment) # group_byでグループ化した処理を行う group_by(kenko_ec_data, item_category, series) ## group_byの後にsummariseで集計する kenko_ec_data_g <- group_by(kenko_ec_data, item_category) summarise(kenko_ec_data_g, uu = n_distinct(userid)) ## summariseを行うとグループ化した列が1つなくなる kenko_ec_data_g <- group_by(kenko_ec_data, item_category, series) summarise(kenko_ec_data_g, uu = n_distinct(userid)) # 練習問題 ## まず、1000円以上の商品に絞ったデータフレームにする kenko_ec_data_tmp1 <- filter(kenko_ec_data, price >= 1000) ## 売上を計算したいので、単価×購入数で売上を表す列を追加する。 kenko_ec_data_tmp2 <- mutate(kenko_ec_data_tmp1, payment = price * purchase_amount) ## 「商品ごと」なので、item_category,とseriesの2列でグループ化する。 kenko_ec_data_tmp3 <- group_by(kenko_ec_data_tmp2, item_category, series) ## summariseで集計。 kenko_ec_data_tmp4 <- summarise(kenko_ec_data_tmp3, payment_sum = sum(payment), uu = n_distinct(userid)) ## ランキングなのでarrangeで降順に並び替える。 output <- arrange(kenko_ec_data_tmp4, desc(payment_sum)) output
Rで複数のデータフレームを結合するJOIN関数の使い方とは。マーケターが1からRを勉強します【第6回】
https://manamina.valuesccg.com/articles/898マーケター1年目の小幡さんがRを学んでいきます。講師は株式会社ヴァリューズのデータアナリスト、輿石さん。第6回はRを使ったデータ同士を結合させるjoin関数を習得します。Rでデータを扱えるようになりたいと考えている方、ぜひ小幡さんと一緒に勉強していきましょう。
メールマガジン登録
最新調査やマーケティングに役立つ
トレンド情報をお届けします
大学でマーケティングを勉強しながら、ヴァリューズでインターンとして働いていました。2020年の春からは新卒としてヴァリューズに入社しました。