データサイエンス100本ノック(構造化データ加工編)- R Part 2 (Q21 to Q40)の解説です。
参照(Reference) : 「データサイエンティスト協会スキル定義委員」の「データサイエンス100本ノック(構造化データ加工編)」
The Data Scientist Society Github :
Data Science 100 Knocks (Structured Data Processing) URL :
はじめに
- 初めに以下のセルを実行してください
- 必要なライブラリのインポートとデータベース(PostgreSQL)からのデータ読み込みを行います
- 利用が想定されるライブラリは以下セルでインポートしています
- その他利用したいライブラリがあればinstall.packages()で適宜インストールしてください
- 名前、住所等はダミーデータであり、実在するものではありません
require("RPostgreSQL")
require("tidyr")
require("dplyr")
require("stringr")
require("caret")
require("lubridate")
require("rsample")
require("recipes")
require("themis")
host <- "db"
port <- Sys.getenv()["PG_PORT"]
dbname <- Sys.getenv()["PG_DATABASE"]
user <- Sys.getenv()["PG_USER"]
password <- Sys.getenv()["PG_PASSWORD"]
con <- dbConnect(PostgreSQL(), host=host, port=port, dbname=dbname, user=user, password=password)
df_customer <- dbGetQuery(con,"SELECT * FROM customer")
df_category <- dbGetQuery(con,"SELECT * FROM category")
df_product <- dbGetQuery(con,"SELECT * FROM product")
df_receipt <- dbGetQuery(con,"SELECT * FROM receipt")
df_store <- dbGetQuery(con,"SELECT * FROM store")
df_geocode <- dbGetQuery(con,"SELECT * FROM geocode")
Loading required package: RPostgreSQL Loading required package: DBI Loading required package: tidyr Loading required package: dplyr Attaching package: ‘dplyr’ The following objects are masked from ‘package:stats’: filter, lag The following objects are masked from ‘package:base’: intersect, setdiff, setequal, union Loading required package: stringr Loading required package: caret Loading required package: ggplot2 Loading required package: lattice Loading required package: lubridate Attaching package: ‘lubridate’ The following objects are masked from ‘package:base’: date, intersect, setdiff, union Loading required package: rsample Loading required package: recipes Attaching package: ‘recipes’ The following object is masked from ‘package:stringr’: fixed The following object is masked from ‘package:stats’: step Loading required package: themis Registered S3 methods overwritten by 'themis': method from bake.step_downsample recipes bake.step_upsample recipes prep.step_downsample recipes prep.step_upsample recipes tidy.step_downsample recipes tidy.step_upsample recipes tunable.step_downsample recipes tunable.step_upsample recipes Attaching package: ‘themis’ The following objects are masked from ‘package:recipes’: step_downsample, step_upsample
演習問題
R-021: レシート明細データ(df_receipt)に対し、件数をカウントせよ。
nrow(df_receipt)
104681
解説:
nrow(df_receipt)」というコードは、Rまたは同様の統計プログラミング言語で記述されています。これは、"df_receipt "というデータフレームの行数を決定するために使用されます。
以下、コードの内訳を説明します。
"nrow() "はRの組み込み関数で、データフレーム内の行数を返す。
"df_receipt "は、行数を求めたいデータフレームの名前です。
例えば、データフレーム "df_receipt "に100行のデータがある場合、このコードを実行すると、値100が返されます。このコードは、さらなる分析やデータの操作を行う前に、データフレームのサイズを素早くチェックし、期待通りの行数を持つことを確認するのに便利です。
R-022: レシート明細データ(df_receipt)の顧客ID(customer_id)に対し、ユニーク件数をカウントせよ。
length(unique(df_receipt$customer_id))
8307
解説:
コード "length(unique(df_receipt$customer_id))" は、R または同様の統計プログラミング言語で記述されています。これは、"df_receipt "というデータフレームに含まれるユニークな顧客の数を決定するために使用されます。
以下、コードの内訳を説明します。
"unique() "は、あるベクトルのユニークな要素だけを含むベクトルを返すR関数です。この場合、"unique() "関数に渡されるベクトルは "df_receipt$customer_id "で、"df_receipt "データフレーム内の顧客IDを含む列である。
"length() "もまた、ベクトルの要素数を返すRの組み込み関数である。この場合、"length() "に渡されるベクトルは、"unique() "関数の出力であり、ユニークな顧客IDを含むベクトルである。
これをまとめると、このコードは、ユニークな顧客IDを含むベクトルの長さを取ることによって、「df_receipt」データフレーム内のユニークな顧客の数を計算する。例えば、データフレームに1000行が含まれ、ユニークな顧客IDが500しかない場合、このコードを実行すると、500という値が返されます。このコードは、データセット内のユニークな顧客の数を把握したり、顧客生涯価値などの顧客レベルの指標を計算するのに便利です。
R-023: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)と売上数量(quantity)を合計せよ。
df_receipt %>% group_by(store_cd) %>% summarise(amount = sum(amount), quantity = sum(quantity), .groups = "drop")
store_cd | amount | quantity |
---|---|---|
<chr> | <int> | <int> |
S12007 | 638761 | 2099 |
S12013 | 787513 | 2425 |
S12014 | 725167 | 2358 |
S12029 | 794741 | 2555 |
S12030 | 684402 | 2403 |
S13001 | 811936 | 2347 |
S13002 | 727821 | 2340 |
S13003 | 764294 | 2197 |
S13004 | 779373 | 2390 |
S13005 | 629876 | 2004 |
S13008 | 809288 | 2491 |
S13009 | 808870 | 2486 |
S13015 | 780873 | 2248 |
S13016 | 793773 | 2432 |
S13017 | 748221 | 2376 |
S13018 | 790535 | 2562 |
S13019 | 827833 | 2541 |
S13020 | 796383 | 2383 |
S13031 | 705968 | 2336 |
S13032 | 790501 | 2491 |
S13035 | 715869 | 2219 |
S13037 | 693087 | 2344 |
S13038 | 708884 | 2337 |
S13039 | 611888 | 1981 |
S13041 | 728266 | 2233 |
S13043 | 587895 | 1881 |
S13044 | 520764 | 1729 |
S13051 | 107452 | 354 |
S13052 | 100314 | 250 |
S14006 | 712839 | 2284 |
S14010 | 790361 | 2290 |
S14011 | 805724 | 2434 |
S14012 | 720600 | 2412 |
S14021 | 699511 | 2231 |
S14022 | 651328 | 2047 |
S14023 | 727630 | 2258 |
S14024 | 736323 | 2417 |
S14025 | 755581 | 2394 |
S14026 | 824537 | 2503 |
S14027 | 714550 | 2303 |
S14028 | 786145 | 2458 |
S14033 | 725318 | 2282 |
S14034 | 653681 | 2024 |
S14036 | 203694 | 635 |
S14040 | 701858 | 2233 |
S14042 | 534689 | 1935 |
S14045 | 458484 | 1398 |
S14046 | 412646 | 1354 |
S14047 | 338329 | 1041 |
S14048 | 234276 | 769 |
S14049 | 230808 | 788 |
S14050 | 167090 | 580 |
解説:
df_receipt %>% group_by(store_cd) %>% summarise(amount = sum(amount), quantity = sum(quantity), .groups = 'drop')" というコードは、Rまたは同様の統計プログラミング言語で書かれています。これは、"df_receipt" データフレームを "store_cd" という変数でグループ化し、各店舗グループ内の "amount" と "quantity" 変数の合計を計算するために使用されています。
以下、コードの内訳を説明します。
パイプ演算子(「%>%」)は、複数の関数を順番に連結するために使用します。パイプ演算子(「%>%」)は、複数の関数を連鎖させて使うもので、前の関数の出力を受け取り、次の関数の入力として使用します。この例では、"group_by() "と "summarise() "関数を連結させるためにパイプ演算子を使用しています。
"group_by() "は、データフレームを1つまたは複数の変数でグループ化するために使用されるR関数です。今回は、"df_receipt "データフレームを "store_cd "変数でグループ化します。
"summarise() "は、データフレームの要約統計量を計算するために使用されるR関数です。今回は、各店舗グループ内の「金額」「数量」変数の合計を算出しています。また、代入演算子「=」を使って、新しい変数の名前を指定しています。
summarise()」関数の「.groups」引数は、出力の書式を指定するために使用されます。これを "drop "に設定すると、出力からグループ化情報が取り除かれます。
このコードの結果は、"df_receipt "データフレーム内の各店舗に1行を持つ新しいデータフレームになります。amount "と "quantity "の列には、各店舗グループ内のこれらの変数の合計が含まれます。このコードは、総売上高や販売個数など、店舗レベルの指標を計算するのに便利です。
R-024: レシート明細データ(df_receipt)に対し、顧客ID(customer_id)ごとに最も新しい売上年月日(sales_ymd)を求め、10件表示せよ。
df_receipt %>% group_by(customer_id) %>% summarise(max_ymd = max(sales_ymd), .groups = "drop") %>% slice(1:10)
customer_id | max_ymd |
---|---|
<chr> | <int> |
CS001113000004 | 20190308 |
CS001114000005 | 20190731 |
CS001115000010 | 20190405 |
CS001205000004 | 20190625 |
CS001205000006 | 20190224 |
CS001211000025 | 20190322 |
CS001212000027 | 20170127 |
CS001212000031 | 20180906 |
CS001212000046 | 20170811 |
CS001212000070 | 20191018 |
解説:
df_receipt %>% group_by(customer_id) %>% summarise(max_ymd = max(sales_ymd), .groups = 'drop') %>% slice(1:10)" というコードはRまたは同様の統計プログラミング言語で書かれています。これは、"df_receipt" データフレームを "customer_id" という変数でグループ化し、各顧客の最新の購入日を見つけるために使用されます。最後に、出来上がったデータフレームの最初の10行をスライスしています。
以下、コードの内訳を説明します。
パイプ演算子(「%>%」)は、複数の関数を順番に連結するために使用します。パイプ演算子("%>%")は、複数の関数を順番に連結するために使用されます。前の関数の出力を受け取り、次の関数の入力として使用します。この例では、"group_by()"、"summarise()"、"slice() "関数を連結するためにパイプ演算子が使用されています。
"group_by() "は、データフレームを1つまたは複数の変数でグループ化するために使用されるR関数です。この場合、"df_receipt "データフレームを "customer_id "変数でグループ化しています。
"summarise() "は、データフレームの要約統計量を計算するために使用されるR関数です。今回は、"sales_ymd "変数の "max() "関数を用いて、各顧客の最新の購入日を算出しています。
summarise()」関数の「.groups」引数は、出力がどのようにフォーマットされるかを指定するために使用されます。これを "drop "に設定すると、出力からグループ化情報が取り除かれます。
"slice() "は、データフレームから行のサブセットを抽出するために使用されるR関数です。この場合、結果のデータフレームから最初の10行を選択しています。
このコードの結果は、"df_receipt "データフレームの各顧客について1行を持つ新しいデータフレームになります。max_ymd "列には、各顧客の最新の購入日が含まれます。最後に、このコードは結果のデータ・フレームの最初の10行を選択します。このコードは、各顧客の最新の購入日を把握するのに役立ち、様々な顧客レベルの分析やセグメンテーションの目的に使用することができます。
R-025: レシート明細データ(df_receipt)に対し、顧客ID(customer_id)ごとに最も古い売上年月日(sales_ymd)を求め、10件表示せよ。
df_receipt %>% group_by(customer_id) %>% summarise(min_ymd = min(sales_ymd), .groups = "drop") %>% slice(1:10)
customer_id | min_ymd |
---|---|
<chr> | <int> |
CS001113000004 | 20190308 |
CS001114000005 | 20180503 |
CS001115000010 | 20171228 |
CS001205000004 | 20170914 |
CS001205000006 | 20180207 |
CS001211000025 | 20190322 |
CS001212000027 | 20170127 |
CS001212000031 | 20180906 |
CS001212000046 | 20170811 |
CS001212000070 | 20191018 |
解説:
このコードでは、%>%(パイプ)演算子を使って、df_receiptというデータ・フレームに対して一連の操作を連鎖的に行っています。
以下は、各操作が何をするのかのステップバイステップの説明です。
group_by(customer_id)。group_by(customer_id):customer_id列でデータをグループ化し、その後の処理を顧客ごとに分けて実行します。
summarise(min_ymd = min(sales_ymd), .groups = "drop"):sales_ymdカラムの最小値を計算し、min_ymdという新しいカラムに格納することで、各グループ内のデータの要約を作成する。.groups = "drop "引数は、結果のデータフレームからグループ化情報を削除するようdplyrに指示します(さらなる分析に必要ないため)。
slice(1:10):これは、結果のデータフレームから最初の10行を選択します。データはcustomer_idでグループ化され、summary関数が使用されたので、データセットの最初の10人の顧客の最も早いsales_ymd値が得られることになります。
全体として、このコードはdf_receiptデータフレーム内の各顧客の最も早いsales_ymd値を選択し、データセットの最初の10人の顧客の最も早い日付を返しています。
R-026: レシート明細データ(df_receipt)に対し、顧客ID(customer_id)ごとに最も新しい売上年月日(sales_ymd)と古い売上年月日を求め、両者が異なるデータを10件表示せよ。
df_receipt %>% group_by(customer_id) %>% summarise(max_ymd = max(sales_ymd) ,min_ymd = min(sales_ymd), .groups = "drop") %>% filter(max_ymd != min_ymd) %>% slice(1:10)
customer_id | max_ymd | min_ymd |
---|---|---|
<chr> | <int> | <int> |
CS001114000005 | 20190731 | 20180503 |
CS001115000010 | 20190405 | 20171228 |
CS001205000004 | 20190625 | 20170914 |
CS001205000006 | 20190224 | 20180207 |
CS001214000009 | 20190902 | 20170306 |
CS001214000017 | 20191006 | 20180828 |
CS001214000048 | 20190929 | 20171109 |
CS001214000052 | 20190617 | 20180208 |
CS001215000005 | 20181021 | 20170206 |
CS001215000040 | 20171022 | 20170214 |
解説:
このコードでは、%>%(パイプ)演算子を使って、df_receiptというデータ・フレームに対して一連の操作を連鎖的に行っています。
以下は、各操作が何をするのかのステップバイステップの説明です。
group_by(customer_id) : group_by(customer_id):customer_id列でデータをグループ化し、その後の処理を顧客ごとに分けて実行する。
summarise(max_ymd = max(sales_ymd), min_ymd = min(sales_ymd), .groups = "drop"): sales_ymdカラムの最大値と最小値を計算し、それぞれmax_ymdとmin_ymdという新しいカラムに格納することで、各グループ内のデータの要約を作成する。.groups = "drop "引数は、結果のデータフレームからグループ化情報を削除するようdplyrに指示します(さらなる分析には必要ないため)。
filter(max_ymd != min_ymd): これは、max_ymdの値がmin_ymdの値と等しくない行だけを含むようにデータフレームをフィルタリングします。これにより、データセットの対象期間中に1回しか購入しなかった顧客は除外されます。
slice(1:10):これは、結果のデータ・フレームの最初の10行を選択します。データはcustomer_idでグループ化され、max関数とmin関数で要約され、それらの要約統計に基づいてフィルタリングされたので、これはデータセットの対象期間中に1回以上購入した最初の10人の顧客を得ることができます。
全体として、このコードはdf_receiptデータフレームでカバーされる期間中に1回以上購入した顧客を選択し、最も早い購入日と最も遅い購入日を返しています。このコードでは、これらの条件を満たす最初の10人の顧客について、最も早い購入日と最も遅い購入日を返します。
R-027: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、降順でTOP5を表示せよ。
df_receipt %>% group_by(store_cd) %>% summarise(mean_amount = mean(amount), .groups = "drop") %>% arrange(desc(mean_amount)) %>% slice(1:5)
store_cd | mean_amount |
---|---|
<chr> | <dbl> |
S13052 | 402.8675 |
S13015 | 351.1120 |
S13003 | 350.9155 |
S14010 | 348.7913 |
S13001 | 348.4704 |
解説:
このコードでは、%>%(パイプ)演算子を使って、df_receiptというデータ・フレームに対して一連の操作を連鎖的に行っています。
以下、各操作が何をするのか、順を追って説明します。
group_by(store_cd)。group_by(store_cd):store_cd列でデータをグループ化し、その後の処理を各店舗ごとに行う。
summarise(mean_amount = mean(amount), .groups = "drop") : 各グループ内のデータの要約を作成し、amount列の平均値を計算して、mean_amountという新しい列に格納します。.groups = "drop "引数は、結果のデータフレームからグループ化情報を削除するようdplyrに指示します(さらなる分析に必要ないため)。
arrange(desc(mean_amount)) : これは、mean_amount列の降順(高いものから低いものへ)で結果のデータフレームをソートします。
slice(1:5) : 結果のデータフレームから最初の5行を選択します。データはstore_cdでグループ化され、mean関数を使って要約されたので、これにより、すべてのトランザクションで最も高い平均金額値を持つ店舗が得られます。
全体として、このコードはdf_receiptデータフレーム内のすべてのトランザクションで最も高い平均金額値を持つ店舗を選択し、その値に基づいて上位5店舗を返しています。
R-028: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の中央値を計算し、降順でTOP5を表示せよ。
df_receipt %>% group_by(store_cd) %>% summarise(median_amount = median(amount), .groups = "drop") %>% arrange(desc(median_amount)) %>% slice(1:5)
store_cd | median_amount |
---|---|
<chr> | <dbl> |
S13052 | 190 |
S14010 | 188 |
S14050 | 185 |
S13003 | 180 |
S13018 | 180 |
解説:
このコードでは、%>%(パイプ)演算子を使って、df_receiptというデータ・フレームに対して一連の操作を連鎖的に行っています。
以下、各操作が何をするのか、順を追って説明します。
group_by(store_cd)。group_by(store_cd):store_cd列でデータをグループ化し、その後の処理を店舗ごとに分けて実行するようにします。
summarise(median_amount = median(amount), .groups = "drop") : 各グループ内のデータの要約を作成し、amount列の中央値を計算して、median_amountという新しい列に格納します。.groups = "drop "引数は、結果のデータフレームからグループ化情報を削除するようdplyrに指示します(さらなる分析には必要ないため)。
arrange(desc(median_amount)) : これは、結果のデータフレームをmedian_amount列で降順(高い方から低い方へ)にソートします。
slice(1:5) : 結果のデータフレームから最初の5行を選択します。データはstore_cdでグループ化され、median関数を使って要約されたので、これにより、すべてのトランザクションで中央値の値が最も高い店舗が得られることになります。
全体として、このコードはdf_receiptデータフレームの全トランザクションの中で最も中央値の高い店舗を選択し、その値に基づいて上位5店舗を返しています。このコードと前回説明したコードの違いは、このコードでは、各店舗の金額値の中心傾向を計算するために、平均関数ではなく、中央値関数を使用していることです。
R-029: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに商品コード(product_cd)の最頻値を求め、10件表示させよ。
# コード例1 df_receipt %>% group_by(store_cd, product_cd) %>% summarise(cnt = n(), .groups = "drop_last") %>% filter(cnt == cnt %>% max()) %>% ungroup() %>% slice(1:10)
store_cd | product_cd | cnt |
---|---|---|
<chr> | <chr> | <int> |
S12007 | P060303001 | 72 |
S12013 | P060303001 | 107 |
S12014 | P060303001 | 65 |
S12029 | P060303001 | 92 |
S12030 | P060303001 | 115 |
S13001 | P060303001 | 67 |
S13002 | P060303001 | 78 |
S13003 | P071401001 | 65 |
S13004 | P060303001 | 88 |
S13005 | P040503001 | 36 |
解説:
このコードはdplyrパッケージを使って、df_receiptというデータフレームに対してデータ操作を行うものです。以下は、このコードが行っていることを段階的に説明したものである。
ある関数の出力が次の関数の入力になるように、関数を連鎖させるために使用されるパイプ演算子です。
group_by関数は、データフレームをstore_cdとproduct_cdでグループ化する関数です。
summarise関数は、各グループの要約統計量を計算します。この場合、各グループの行数をカウントし、cntという新しい列を作成します。
.groups = "drop_last "引数は、summarise関数で作成された最後のグループ化レベル、つまりproduct_cdグループ化を削除するために使用されます。これは、後で最大数でフィルタリングするのを簡単にするために行われます。
filter関数は、ある条件を満たした行を選択する。この場合、cnt列がデータフレーム内のcnt列の最大値と等しい行を選択することになります。
ungroup関数は、データフレームからすべてのグループ化レベルを削除します。
slice関数は、その位置に基づいて行のサブセットを選択する。この場合、データフレームの最初の10行を選択しています。
つまり、このコードは全体として、データを店舗と商品でグループ化し、各グループのカウントを計算し、カウントが最も多いグループをフィルタリングして、上位10件を選択しています。
# コード例2: which.max()を使用(最頻値複数発生時、どれか一つに絞られる) # 件数の表示は省略
# Display of the number of cases is omitted
table_product <-table(df_receipt$store_cd,df_receipt$product_cd)
store <- names(table_product[,1])
mode_product <- c()
for (i in 1:length(store)){
mode_product[i] <- names(which.max(table_product[i,]))
}
data.frame(store_cd = store, product_cd = mode_product) %>%
slice(1:10)
store_cd | product_cd |
---|---|
<chr> | <chr> |
S12007 | P060303001 |
S12013 | P060303001 |
S12014 | P060303001 |
S12029 | P060303001 |
S12030 | P060303001 |
S13001 | P060303001 |
S13002 | P060303001 |
S13003 | P071401001 |
S13004 | P060303001 |
S13005 | P040503001 |
解説:
このコードは、df_receiptデータフレーム内の各店舗の各商品コードのモード(最頻値)を求めるために、table関数とforループを使っています。
以下、このコードが行っていることをステップバイステップで説明します。
table関数は、df_receiptのstore_cdとproduct_cdの各組み合わせのカウントの分割表を作成します。その結果、table_productというオブジェクトは、行が各店舗、列が各商品コードに対応する行列となります。
names関数は、table_product行列の1列目から店舗コードを抽出し、storeという文字ベクトルとして保存する。
各店舗の各商品コードのモードを保存するために、mode_productという空のベクトルが作成されます。
forループはstoreの各店舗を繰り返し、その店舗の各商品コードのモードを求めます。which.max関数でtable_product行列の各行の最大カウントのインデックスを求め、names関数でそのインデックスを持つ商品コードを抽出する。得られたプロダクトコードはmode_productベクトルに格納される。
store_cdとproduct_cdの2つのカラムを持つデータフレームが作成される。store_cdカラムにはstoreベクトルの値が、product_cdカラムにはmode_productベクトルの値が格納される。
また、%>%演算子を使ってデータフレームをslice関数にパイプし、データフレームの最初の10行を選択しています。
つまり、このコードは全体として、df_receiptの各店舗の各商品コードのモードを求め、これらの値でデータフレームを作成し、上位10件を選択しています。
R-030: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の分散を計算し、降順で5件表示せよ。
var_sample <- function(x){ var(x) * (length(x) - 1) / length(x) }
df_receipt %>%
group_by(store_cd) %>%
summarise(var_amount = var_sample(amount), .groups = "drop") %>% arrange(desc(var_amount)) %>%
slice(1:5)
store_cd | var_amount |
---|---|
<chr> | <dbl> |
S13052 | 440088.7 |
S14011 | 306314.6 |
S14034 | 296920.1 |
S13001 | 295432.0 |
S13015 | 295294.4 |
解説:
このコードは、dplyrパッケージを使用して、df_receiptデータフレームの各店舗の金額変数のサンプル分散を計算し、次に分散が最も大きい上位5店舗を選択しています。
以下は、このコードが行っていることをステップバイステップで説明したものです。
var_sample 関数が定義されており、var(x) * (length(x) - 1) / length(x) という式を使って値xのベクトルのサンプル分散を計算します。この式は、母集団の分散を偏りなく推定するために、length(x)の代わりにlength(x) - 1で割ることで分散を調整する。
演算子 %>% は、df_receipt データフレームをチェーンの次の関数にパイプするために使用されます。
group_by関数は、データをstore_cdでグループ化するために使用されます。
summarise関数は、各グループの要約統計量を計算します。この場合、var_sample関数を使用して、各グループの金額変数のサンプル分散を計算し、var_amountという新しい列を作成しています。
.groups = "drop "引数は、出力からグループ化情報を削除し、グループ化されたtibbleではなく、フラットなデータフレームにするために使用されます。
arrange関数は、var_amountでデータフレームを降順にソートするために使用され、分散が最も高い店舗が最初に表示されるようにします。
演算子%>%は、ソートされたデータフレームをslice関数にパイプし、データフレームの最初の5行を選択するために使用されています。
つまり、このコードは全体として、店舗ごとにデータをグループ化し、グループごとに金額変数のサンプル分散を計算し、分散によって結果のデータフレームを降順にソートし、そして上位5つの結果を選択しています。
R-031: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の標準偏差を計算し、降順で5件表示せよ。
var_sample <- function(x){ var(x)*(length(x)-1)/length(x) }
std_sample <- function(x){ sqrt(var_sample(x)) }
head(
df_receipt %>%
group_by(store_cd) %>%
summarise(std_amount = std_sample(amount), .groups = "drop") %>%
arrange(desc(std_amount)) ,
n = 5
)
store_cd | std_amount |
---|---|
<chr> | <dbl> |
S13052 | 663.3918 |
S14011 | 553.4569 |
S14034 | 544.9037 |
S13001 | 543.5366 |
S13015 | 543.4099 |
解説:
このコードは、dplyrパッケージを使って、df_receiptデータフレームの各店舗の金額変数のサンプル標準偏差を計算し、標準偏差が最も高い上位5店舗を選択しています。
以下、このコードが何をやっているのか、順を追って説明します。
var_sample 関数が定義されており、var(x) * (length(x) - 1) / length(x) という式を使って値 x のベクトルのサンプル分散を計算しています。この式は、母集団の分散を偏りなく推定するために、length(x)の代わりにlength(x) - 1で割ることで分散を調整する。
std_sample関数が定義されており、sqrt(var_sample(x))という式を用いて、値のベクトルxの標本標準偏差を計算するものである。
head関数は、結果のデータフレームの最初の5行を選択するために使用されます。
演算子 %>% は、df_receipt データフレームをチェーンの次の関数にパイプするために使用されます。
group_by関数は、データをstore_cdでグループ化するために使用されます。
summarise関数は、各グループの要約統計量を計算します。この場合、std_sample関数を使用して、各グループの金額変数のサンプル標準偏差を計算し、std_amountという新しい列を作成しています。
.groups = "drop "引数は、出力からグループ化情報を削除し、グループ化されたtibbleではなく、フラットなデータフレームにするために使用されます。
arrange関数は、データフレームをstd_amountで降順にソートし、標準偏差が最も高い店舗が最初に表示されるようにするために使用される。
n = 5の引数は、出力を上位5行に限定するために使用されます。
つまり、このコードは全体として、データを店舗ごとにグループ化し、グループごとに金額変数のサンプル標準偏差を計算し、標準偏差の降順で結果のデータフレームをソートし、そして上位5つの結果を選択しています。
R-032: レシート明細データ(df_receipt)の売上金額(amount)について、25%刻みでパーセンタイル値を求めよ。
df_receipt %>%
summarise
(amount_25per = quantile(amount, 0.25),
amount_50per = quantile(amount, 0.5),
amount_75per = quantile(amount, 0.75),
amount_100per = quantile(amount, 1.0))
amount_25per | amount_50per | amount_75per | amount_100per |
---|---|---|---|
<dbl> | <dbl> | <dbl> | <dbl> |
102 | 170 | 288 | 10925 |
解説:
このコードはdplyrパッケージを使って、df_receiptデータフレーム内の金額変数の四分位を計算しています。
以下は、このコードが行っていることをステップバイステップで説明します。
演算子%>%は、df_receiptデータフレームをチェーン内の次の関数にパイプするために使用されます。
summarise関数は、データフレームの要約統計量を計算するために使用されます。この場合、量変数の25、50(中央値)、75、100パーセンタイルを計算するために、分位関数を使用しています。
結果のデータフレームは1行4列で、列名はamount_25per, amount_50per, amount_75per, amount_100perで、対応する四分位点の値もあります。
つまり、全体として、このコードはdf_receiptデータフレーム内のamount変数の四分位を計算し、四分位値を含むサマリーデータフレームを返しているのです。
R-033: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、330以上のものを抽出せよ。
df_receipt %>%
group_by(store_cd) %>%
summarise(mean_amount = mean(amount), .groups = "drop") %>%
filter(mean_amount >= 330)
store_cd | mean_amount |
---|---|
<chr> | <dbl> |
S12013 | 330.1941 |
S13001 | 348.4704 |
S13003 | 350.9155 |
S13004 | 330.9439 |
S13015 | 351.1120 |
S13019 | 330.2086 |
S13020 | 337.8799 |
S13052 | 402.8675 |
S14010 | 348.7913 |
S14011 | 335.7183 |
S14026 | 332.3406 |
S14045 | 330.0821 |
S14047 | 330.0771 |
解説:
このコードはdplyrパッケージを使って、df_receiptデータフレームをstore_cdでグループ化し、各グループの平均金額を計算し、平均金額が330以上であるグループのみを含むように結果のデータフレームをフィルターしています。
以下は、このコードが行っていることを段階的に説明したものです。
演算子%>%は、df_receiptデータフレームをチェーンの次の関数にパイプするために使用されます。
group_by関数は、データをstore_cdでグループ化するために使用されます。
summarise関数は、各グループの要約統計量を計算するために使用されます。この場合、mean関数を使って各グループの平均金額を計算し、mean_amountという新しい列を作成しています。
.groups = "drop "引数は、出力からグループ化情報を削除し、グループ化されたtibbleではなく、フラットなデータフレームにするために使用されます。
filter関数は、mean_amountが330以上の行のみを含むようにデータフレームをサブセットするために使用されます。
つまり、このコードは全体として、データをstore_cdでグループ化し、各グループの平均金額を計算し、平均金額が330以上のグループのみを選択しています。結果として得られるデータフレームには、対象となる店舗ごとに1行が含まれ、店舗コードと平均金額が表示されます。
R-034: レシート明細データ(df_receipt)に対し、顧客ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求めよ。ただし、顧客IDが”Z”から始まるものは非会員を表すため、除外して計算すること。
df_mean <- df_receipt %>%
filter(!grepl("^Z", customer_id)) %>%
group_by(customer_id) %>%
summarise(sum_amount = sum(amount), .groups = "drop") %>%
summarise(mean_amount = mean(sum_amount))
df_mean$mean_amount
2547.74223452926
解説:
このコードは、dplyrパッケージを使用して、customer_idが文字 "Z "で始まる顧客を除外した後、各顧客の平均消費額を計算しています。
以下は、このコードが行っていることを段階的に説明したものである。
演算子 %>% は、df_receipt データフレームをチェーンの次の関数にパイプするために使用されます。
filter関数は、customer_idが文字 "Z "で始まる行を除外するために使用されます。
group_by関数は、customer_idでデータをグループ化するために使用されます。
summarise関数は、各グループの要約統計量を計算するために使用されます。この場合、sum関数を使って各顧客が使った金額の合計を計算し、sum_amountという新しい列を作成しています。
.groups = "drop "引数は、出力からグループ化情報を削除し、グループ化されたibbleではなく、フラットなデータフレームにするために使用されます。
もう一つのsummarise関数は、全顧客のsum_amountの平均値を計算するために使用されます。
結果の mean_amount 値は、$mean_amount を使って抽出されます。
全体として、このコードは customer_id が "Z" で始まる行を除外するためにデータをフィルタリングし、customer_id でデータをグループ化し、各顧客が使った合計金額を計算し、すべての顧客にわたる平均 sum_amount を計算し、結果の平均値を返している。結果の出力は、各顧客が使用した平均額を表す単一の数値です。
R-035: レシート明細データ(df_receipt)に対し、顧客ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求め、平均以上に買い物をしている顧客を抽出し、10件表示せよ。ただし、顧客IDが”Z”から始まるものは非会員を表すため、除外して計算すること。
df_sum <- df_receipt %>%
filter(!grepl("^Z", customer_id)) %>%
group_by(customer_id) %>%
summarise(sum_amount = sum(amount), .groups = "drop")
df_mean <- df_sum %>%
summarise(mean_amount = mean(sum_amount))
df_sum %>%
filter(sum_amount >= df_mean$mean_amount) %>%
slice(1:10)
customer_id | sum_amount |
---|---|
<chr> | <int> |
CS001115000010 | 3044 |
CS001205000006 | 3337 |
CS001214000009 | 4685 |
CS001214000017 | 4132 |
CS001214000052 | 5639 |
CS001215000040 | 3496 |
CS001304000006 | 3726 |
CS001305000005 | 3485 |
CS001305000011 | 4370 |
CS001315000180 | 3300 |
解説:
このコードは、dplyrパッケージを使用して、customer_idが文字「Z」で始まる顧客を除外した後、全顧客の平均使用額以上の金額を使用した顧客をフィルタリングしています。その後、総使用額に基づいて上位10名の顧客を選択します。
以下は、このコードが行っていることを順を追って説明したものです。
演算子 %>% は、df_receipt データフレームをチェーン内の次の関数にパイプするために使用されます。
filter関数は、customer_idが文字 "Z "で始まる行を除外するために使用されます。
group_by関数は、customer_idでデータをグループ化するために使用されます。
summarise関数は、各グループの要約統計量を計算するために使用されます。この場合、sum関数を使って各顧客が使った金額の合計を計算し、sum_amountという新しい列を作成しています。
.groups = "drop "引数は、出力からグループ化情報を削除し、グループ化されたibbleではなく、フラットなデータフレームにするために使用されます。
df_sumデータフレームは、上記の操作の出力を格納することで作成されます。
summarise関数は、df_sumの全顧客のsum_amountの平均値を計算するために再び使用されます。
結果の mean_amount 値は $mean_amount を使って抽出される。
演算子%>%は、df_sumをチェーンの次の関数にパイプするために使用されます。
フィルター関数は、sum_amountがステップ7で計算されたmean_amount以上の行だけを選択するために使用される。
スライス関数は、元のデータフレームでの順序に基づいて、結果のデータフレームの上位10行のみを選択するために使用されます。
つまり、このコードは全体として、customer_idが "Z "で始まる行を除外するためのデータのフィルタリング、customer_idによるデータのグループ化、各顧客が使った合計金額の計算、全顧客の平均sum_amountの計算、使った合計金額が全顧客の平均金額以上の顧客のデータフレームの作成、使った合計金額に基づいて上位10顧客を選択することです。
R-036: レシート明細データ(df_receipt)と店舗データ(df_store)を内部結合し、レシート明細データの全項目と店舗データの店舗名(store_name)を10件表示せよ。
inner_join(df_receipt, df_store[c("store_cd", "store_name")], by = "store_cd") %>% slice(1:10)
sales_ymd | sales_epoch | store_cd | receipt_no | receipt_sub_no | customer_id | product_cd | quantity | amount | store_name |
---|---|---|---|---|---|---|---|---|---|
<int> | <int> | <chr> | <int> | <int> | <chr> | <chr> | <int> | <int> | <chr> |
20181103 | 1541203200 | S14006 | 112 | 1 | CS006214000001 | P070305012 | 1 | 158 | 葛が谷店 |
20181118 | 1542499200 | S13008 | 1132 | 2 | CS008415000097 | P070701017 | 1 | 81 | 成城店 |
20170712 | 1499817600 | S14028 | 1102 | 1 | CS028414000014 | P060101005 | 1 | 170 | 二ツ橋店 |
20190205 | 1549324800 | S14042 | 1132 | 1 | ZZ000000000000 | P050301001 | 1 | 25 | 新山下店 |
20180821 | 1534809600 | S14025 | 1102 | 2 | CS025415000050 | P060102007 | 1 | 90 | 大和店 |
20190605 | 1559692800 | S13003 | 1112 | 1 | CS003515000195 | P050102002 | 1 | 138 | 狛江店 |
20181205 | 1543968000 | S14024 | 1102 | 2 | CS024514000042 | P080101005 | 1 | 30 | 三田店 |
20190922 | 1569110400 | S14040 | 1102 | 1 | CS040415000178 | P070501004 | 1 | 128 | 長津田店 |
20170504 | 1493856000 | S13020 | 1112 | 2 | ZZ000000000000 | P071302010 | 1 | 770 | 十条仲原店 |
20191010 | 1570665600 | S14027 | 1102 | 1 | CS027514000015 | P071101003 | 1 | 680 | 南藤沢店 |
解説:
このコードは、df_receiptとdf_storeの2つのデータフレーム間で、共通の列「store_cd」に基づいて内部結合操作を実行します。この操作の結果はslice()関数に送られ、結果のデータフレームの最初の10行が選択されます。
それでは、コードをステップごとに分解してみましょう。
inner_join(df_receipt, df_store[c("store_cd", "store_name")], by = "store_cd"): これは、df_receiptデータフレームと、列 "store_cd "と "store_name "のみを含むdf_storeのサブセットとの間の内部結合を実行する。結合は、両方のデータフレームに存在する "store_cd "カラムに対して行われます。結果は、両方のデータフレームの "store_cd "カラムが一致するすべての行を含む新しいデータフレームとなります。
%>%: これはパイプ演算子で、前のコマンドの出力を受け取り、次のコマンドの入力としてパイプします。
slice(1:10):この関数は、前のコマンドで得られたデータフレームの最初の10行を選択します。
つまり、このコードの全体的な目的は、df_receiptとdf_storeのサブセット間の内部結合操作の結果の最初の10行を選択することです。結果のデータフレームは、両方のデータフレームの "store_cd "カラムが一致する行のみを含み、df_storeの "store_cd "と "store_name "カラムとdf_receiptのすべてのカラムを持つことになる。
R-037: 商品データ(df_product)とカテゴリデータ(df_category)を内部結合し、商品データの全項目とカテゴリデータのカテゴリ小区分名(category_small_name)を10件表示せよ。
inner_join(df_product, df_category[c("category_small_cd", "category_small_name")], by = "category_small_cd") %>% slice(1:10)
product_cd | category_major_cd | category_medium_cd | category_small_cd | unit_price | unit_cost | category_small_name |
---|---|---|---|---|---|---|
<chr> | <chr> | <chr> | <chr> | <int> | <int> | <chr> |
P040101001 | 04 | 0401 | 040101 | 198 | 149 | 弁当類 |
P040101002 | 04 | 0401 | 040101 | 218 | 164 | 弁当類 |
P040101003 | 04 | 0401 | 040101 | 230 | 173 | 弁当類 |
P040101004 | 04 | 0401 | 040101 | 248 | 186 | 弁当類 |
P040101005 | 04 | 0401 | 040101 | 268 | 201 | 弁当類 |
P040101006 | 04 | 0401 | 040101 | 298 | 224 | 弁当類 |
P040101007 | 04 | 0401 | 040101 | 338 | 254 | 弁当類 |
P040101008 | 04 | 0401 | 040101 | 420 | 315 | 弁当類 |
P040101009 | 04 | 0401 | 040101 | 498 | 374 | 弁当類 |
P040101010 | 04 | 0401 | 040101 | 580 | 435 | 弁当類 |
解説:
このコードは、df_productとdf_categoryの2つのデータフレーム間で、共通の列「category_small_cd」に基づいて内部結合操作を実行します。この操作の結果は、結果のデータ・フレームの最初の10行を選択するためにslice()関数にパイプされます。
それでは、コードをステップごとに分解してみましょう。
inner_join(df_product, df_category[c("category_small_cd", "category_small_name")], by = "category_small_cd"): これは、df_productデータフレームと、"category_small_cd "と "category_small_name "のカラムのみを含むdf_categoryのサブセット間の内部結合を実行する。結合は、両方のデータフレームに存在する "category_small_cd "カラムに対して行われます。結果は、両方のデータフレームの "category_small_cd "カラムが一致するすべての行を含む新しいデータフレームになります。
%>%: これはパイプ演算子で、前のコマンドの出力を受け取り、次のコマンドの入力としてパイプします。
slice(1:10) : この関数は、前のコマンドで得られたデータフレームの最初の10行を選択します。
つまり、このコードの全体的な目的は、df_productとdf_categoryのサブセット間の内部結合操作の結果の最初の10行を選択することです。結果のデータフレームは、両方のデータフレームの "category_small_cd "カラムが一致する行だけを含み、df_categoryの "category_small_cd "と "category_small_name "のカラムとdf_productのすべてのカラムを持つことになる。
R-038: 顧客データ(df_customer)とレシート明細データ(df_receipt)から、顧客ごとの売上金額合計を求め、10件表示せよ。ただし、売上実績がない顧客については売上金額を0として表示させること。また、顧客は性別コード(gender_cd)が女性(1)であるものを対象とし、非会員(顧客IDが”Z”から始まるもの)は除外すること。
df_sum <- df_receipt %>%
group_by(customer_id) %>%
summarise(sum_amount = sum(amount), .groups = "drop")
df_target <- df_customer %>%
filter(gender_cd == "1" & !grepl("^Z", customer_id))
left_join(df_target["customer_id"], df_sum, by = "customer_id") %>%
replace_na(list(sum_amount = 0)) %>% slice(1:10)
customer_id | sum_amount |
---|---|
<chr> | <dbl> |
CS021313000114 | 0 |
CS031415000172 | 5088 |
CS028811000001 | 0 |
CS001215000145 | 875 |
CS015414000103 | 3122 |
CS033513000180 | 868 |
CS035614000014 | 0 |
CS011215000048 | 3444 |
CS009413000079 | 0 |
CS040412000191 | 210 |
解説:
このコードでは、顧客データの要約表を得るためにいくつかの処理を実行します。最後に、この結果をslice()関数に渡して、結果のデータフレームの最初の10行を選択します。
それでは、コードをステップごとに分解してみましょう。
df_sum <- df_receipt %>% group_by(customer_id) %>% summise(sum_amount = sum(amount), .groups = "drop"): このコードは、まずdf_receiptデータフレームを "customer_id "列でグループ化し、次にsum()関数を用いて "amount "列を要約しています。結果として得られるデータフレームdf_sumには、各顧客が使った金額の合計が含まれています。.groupsパラメータは、出力からグループ化情報を削除するために "drop "に設定されています。
df_target <- df_customer %>% filter(gender_cd == "1" & !grepl("^Z", customer_id)): このコードは、df_customerデータフレームをフィルタリングして、"gender_cd" カラムが "1" に等しく、"customer_id" カラムが文字 "Z" で始まらない行のみを含むようにします。その結果、データフレームdf_targetには、IDが "Z "で始まらない男性顧客のみが含まれます。
left_join(df_target["customer_id"], df_sum, by = "customer_id"): これは、df_target["customer_id"]とdf_sumの間で、"customer_id "列に基づいて左結合操作を実行する。結果は、df_targetのすべての行と、df_sumの各顧客が使用した対応する合計金額を含む新しいデータフレームになります。
replace_na(list(sum_amount = 0)): sum_amount "カラムの欠損値をデフォルトの0に置き換えます。
%>% slice(1:10): この関数は、前のコマンドで得られたデータフレームの最初の10行を選択します。
つまり、このコードの全体的な目的は、IDが "Z "で始まらない男性客が使った金額の合計の要約表を得ることです。出来上がったデータフレームは、"customer_id "と "sum_amount "という2つの列を持ち、"sum_amount "は各顧客が使った合計金額となります。sum_amount "列の欠損値はすべて0に置き換えられ、結果のデータフレームは最初の10行に限定される。
R-039: レシート明細データ(df_receipt)から、売上日数の多い顧客の上位20件を抽出したデータと、売上金額合計の多い顧客の上位20件を抽出したデータをそれぞれ作成し、さらにその2つを完全外部結合せよ。ただし、非会員(顧客IDが”Z”から始まるもの)は除外すること。
# コード例1
df_data <- df_receipt %>%
filter(!grepl("^Z", customer_id)) %>%
group_by(customer_id)
df_cnt <- df_data %>%
summarise(come_days = n_distinct(sales_ymd), .groups = "drop") %>%
arrange(desc(come_days), customer_id) %>%
slice(1:20)
df_sum <- df_data %>% summarise(sum_amount = sum(amount), .groups = "drop") %>%
arrange(desc(sum_amount)) %>%
slice(1:20)
full_join(df_cnt, df_sum, by = "customer_id")
customer_id | come_days | sum_amount |
---|---|---|
<chr> | <int> | <int> |
CS040214000008 | 23 | NA |
CS010214000010 | 22 | 18585 |
CS015415000185 | 22 | 20153 |
CS010214000002 | 21 | NA |
CS028415000007 | 21 | 19127 |
CS016415000141 | 20 | 18372 |
CS017415000097 | 20 | 23086 |
CS014214000023 | 19 | NA |
CS021514000045 | 19 | NA |
CS021515000172 | 19 | NA |
CS022515000226 | 19 | NA |
CS031414000051 | 19 | 19202 |
CS039414000052 | 19 | NA |
CS007515000107 | 18 | NA |
CS014415000077 | 18 | NA |
CS021515000056 | 18 | NA |
CS021515000211 | 18 | NA |
CS022515000028 | 18 | NA |
CS030214000008 | 18 | NA |
CS031414000073 | 18 | NA |
CS001605000009 | NA | 18925 |
CS006515000023 | NA | 18372 |
CS011414000106 | NA | 18338 |
CS038415000104 | NA | 17847 |
CS035414000024 | NA | 17615 |
CS021515000089 | NA | 17580 |
CS032414000072 | NA | 16563 |
CS016415000101 | NA | 16348 |
CS011415000006 | NA | 16094 |
CS034415000047 | NA | 16083 |
CS007514000094 | NA | 15735 |
CS009414000059 | NA | 15492 |
CS030415000034 | NA | 15468 |
CS015515000034 | NA | 15300 |
解説:
このコードは、顧客データの2つのサマリー・テーブルを取得するためにいくつかの操作を行い、"customer_id "カラムに基づいてこれら2つのテーブル間で完全結合操作を実行します。結果として得られるデータ・フレームには、販売日が最も明確な上位20人の顧客と、購入金額の合計が最も高い上位20人の顧客が含まれています。
それでは、コードをステップごとに分解してみましょう。
df_data <- df_receipt %>% filter(!grepl("^Z", customer_id)) %>% group_by(customer_id): このコードは、まずdf_receiptデータフレームをフィルタリングして、"customer_id "列が文字 "Z "で始まる行を除外します。その結果、データフレームは "customer_id "カラムによってグループ化されます。結果のdf_dataデータフレームは、df_receiptから "Z "の顧客IDを取り除いたすべての行を含み、"customer_id "でグループ化されています。
df_cnt <- df_data %>% summarise(come_days = n_distinct(sales_ymd), .groups = "drop") %>% arrange(desc(come_days), customer_id) %>% slice(1:20): このコードでは、まず、n_distinct()関数を使用して、各顧客の "sales_ymd" 値の数をカウントして、df_data データフレームを要約しています。結果として得られるデータフレームdf_cntは、各顧客のユニークな販売日の合計数を含んでいます。このデータフレームは、"come_days "の降順、"customer_id "の降順で並べられます。次に、slice()関数を使用して、結果のデータ・フレームの最初の20行を選択します。
df_sum <- df_data %>% summarise(sum_amount = sum(amount), .groups = "drop") %>% arrange(desc(sum_amount)) %>% slice(1:20): このコードは、sum()関数を使用して各顧客の「金額」列の合計を計算することにより、df_dataデータフレームを要約しています。結果として得られるデータフレームdf_sumには、各顧客が使った金額の合計が含まれています。次に、このデータフレームを "sum_amount" の降順に並べ、slice() 関数を使用して、結果のデータフレームの最初の 20 行を選択します。
full_join(df_cnt, df_sum, by = "customer_id"): このコードは、df_cntとdf_sumの間で、"customer_id "列に基づいて完全な結合操作を実行する。結果は、両方のデータフレームから "customer_id "でマッチしたすべての行を含む新しいデータフレームになります。結果として得られるデータフレームには、最も明確な販売日を持つ上位20人の顧客と、最も高い総消費額を持つ上位20人の顧客が含まれています。
つまり、このコードの全体的な目的は、顧客データの2つのサマリーテーブルを取得し、これら2つのテーブル間で完全結合操作を実行することです。結果として得られるデータフレームには、最も異なる販売日を持つ上位20人の顧客と、最も高い総支払額を持つ上位20人の顧客が含まれます。
# コード例2
# Code example using slice_max.
# Rewrite with_ties = FALSE to with_ties = TRUE to change the form to include the same rank
df_data <- df_receipt %>%
filter(!grepl("^Z", customer_id)) %>%
group_by(customer_id)
df_cnt <- df_data %>%
summarise(come_days = n_distinct(sales_ymd)) %>%
slice_max(come_days, n = 20, with_ties = FALSE)
df_sum <- df_data %>%
summarise(sum_amount = sum(amount)) %>%
slice_max(sum_amount, n = 20, with_ties = FALSE)
full_join(df_cnt, df_sum, by = "customer_id")
customer_id | come_days | sum_amount |
---|---|---|
<chr> | <int> | <int> |
CS040214000008 | 23 | NA |
CS010214000010 | 22 | 18585 |
CS015415000185 | 22 | 20153 |
CS010214000002 | 21 | NA |
CS028415000007 | 21 | 19127 |
CS016415000141 | 20 | 18372 |
CS017415000097 | 20 | 23086 |
CS014214000023 | 19 | NA |
CS021514000045 | 19 | NA |
CS021515000172 | 19 | NA |
CS022515000226 | 19 | NA |
CS031414000051 | 19 | 19202 |
CS039414000052 | 19 | NA |
CS007515000107 | 18 | NA |
CS014415000077 | 18 | NA |
CS021515000056 | 18 | NA |
CS021515000211 | 18 | NA |
CS022515000028 | 18 | NA |
CS030214000008 | 18 | NA |
CS031414000073 | 18 | NA |
CS001605000009 | NA | 18925 |
CS006515000023 | NA | 18372 |
CS011414000106 | NA | 18338 |
CS038415000104 | NA | 17847 |
CS035414000024 | NA | 17615 |
CS021515000089 | NA | 17580 |
CS032414000072 | NA | 16563 |
CS016415000101 | NA | 16348 |
CS011415000006 | NA | 16094 |
CS034415000047 | NA | 16083 |
CS007514000094 | NA | 15735 |
CS009414000059 | NA | 15492 |
CS030415000034 | NA | 15468 |
CS015515000034 | NA | 15300 |
解説:
このコードは前回説明したコードと似ていますが、arrange()関数の代わりにslice_max()関数を使い、販売日数と購入金額の合計から上位20名の顧客を取得します。
以下、コードの内訳を紹介します。
df_data <- df_receipt %>% filter(!grepl("^Z", customer_id)) %>% group_by(customer_id): このコードは前のコードと同様で、df_receiptデータフレームをフィルタリングして、"customer_id "列が文字 "Z "で始まる行を除外しています。その結果、データフレームは "customer_id "カラムによってグループ化されます。
df_cnt <- df_data %>% summarise(come_days = n_distinct(sales_ymd)) %>% slice_max(come_days, n = 20, with_ties = FALSE): このコードは、n_distinct()関数を使用して、各顧客の "sales_ymd "値の数をカウントすることにより、df_dataデータフレームを要約しています。結果のデータフレームdf_cntは、各顧客のユニークな販売日の合計数を含んでいます。slice_max()関数は、"come_days "列に基づいて上位20行を選択するために使用されます。
df_sum <- df_data %>% summarise(sum_amount = sum(amount)) %>% slice_max(sum_amount, n = 20, with_ties = FALSE): このコードは、sum()関数を使用して各顧客の "amount "列の合計を計算することにより、df_dataデータフレームを要約しています。結果として得られるデータフレームdf_sumには、各顧客が使った金額の合計が含まれています。slice_max()関数を使用して、"sum_amount "列に基づいて上位20行を選択します。with_ties = FALSEは、上位20個の異なる値のみを選択することを指定します。
full_join(df_cnt, df_sum, by = "customer_id"): このコードは、df_cntとdf_sumの間で、"customer_id "カラムに基づく完全な結合操作を実行する。結果は、両方のデータフレームから "customer_id "でマッチしたすべての行を含む新しいデータフレームになります。結果として得られるデータフレームには、最も明確な販売日を持つ上位20人の顧客と、最も高い総消費額を持つ上位20人の顧客が含まれています。
つまり、このコードの全体的な目的は、顧客データの2つのサマリーテーブルを取得し、これら2つのテーブル間で完全結合操作を実行することです。結果として得られるデータフレームには、最も異なる販売日を持つ上位20人の顧客と、最も高い総支払額を持つ上位20人の顧客が含まれ、arrange() 関数の代わりに slice_max() 関数を使用して取得します。
R-040: 全ての店舗と全ての商品を組み合わせたデータを作成したい。店舗データ(df_store)と商品データ(df_product)を直積し、件数を計算せよ。
df_store_tmp <- df_store
df_product_tmp <- df_product
df_store_tmp["key"] <- 0
df_product_tmp["key"] <- 0
nrow(full_join(df_store_tmp, df_product_tmp, by = "key"))
531590
解説:
このコードは、df_storeとdf_productの両データフレームに追加された共通の「キー」列に基づいて、両データフレーム間の完全な結合処理を実行します。その後、結果のデータフレームを使用して、nrow()関数を使用して行数を計算します。
以下、コードの内訳を示します。
df_store_tmp <- df_store: このコードでは、df_store_tmpという新しいデータフレームを作成し、df_storeデータフレームのコピーとします。これは、元のデータ・フレームを変更しないようにするためです。
df_product_tmp <- df_product: このコードは、df_productデータ・フレームのコピーであるdf_product_tmpという新しいデータ・フレームを作成します。これは、元のデータフレームを変更しないようにするために行われます。
df_store_tmp["key"] <- 0: このコードはdf_store_tmpデータフレームに "key "という新しい列を追加し、すべての値をゼロに初期化します。このカラムは、結合操作のための共通カラムを提供するために追加されます。
df_product_tmp["key"] <- 0: このコードはdf_product_tmpデータフレームに "key "という新しい列を追加し、すべての値をゼロに初期化します。このカラムは、結合操作のための共通カラムを提供するために追加されます。
full_join(df_store_tmp, df_product_tmp, by = "key")。このコードは、共通の "key "列に基づいてdf_store_tmpとdf_product_tmpデータフレーム間の完全な結合操作を実行する。両データフレームはすべての行でこのカラムに同じ値を持つので、完全結合は2つのデータフレームのデカルト積となり、df_store_tmpのすべての行はdf_product_tmpのすべての行と対になることを意味します。
nrow(full_join(df_store_tmp, df_product_tmp, by = "key")): このコードは、nrow()関数を使用して、完全結合操作から得られるデータフレーム内の行数を計算します。結果は、df_storeとdf_product間の行の組み合わせの総数です。
要約すると、このコードはdf_storeとdf_productデータフレームのコピーを作成し、両方のデータフレームに共通の「キー」列を追加してすべての値をゼロに設定し、共通の「キー」列に基づいて2つのデータフレーム間で完全結合操作を実行し、結果の行数を計算する。このコードの目的は、df_storeとdf_productのデータフレーム間の行の組み合わせの総数を決定することである。
Comment