データサイエンス100本ノック(構造化データ加工編) - Julia/DataFramesMeta
別稿では Base の場合と Query を使う場合の解答例を示した。
https://qiita.com/WolfMoon/items/dea015e37f83da32b0fa
本稿では DataFramesMeta を使う場合の解答例を示す。
ファイル等の準備
https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess
に書かれているように進めればよいが,デスクトップマシンに Python の実行環境がある場合には,そのページの中程の Requirement > Cloud Service > Colaboratory > Open in Colab をクリックし,最初のセルの
import os
import pandas as pd
:
df_geocode = pd.read_csv("data/geocode.csv", dtype=dtype)
を実行すれば,作業ディレクトリの下に 100knocks-preprocess/docker/work/data/
というディレクトリができ,これをベースディレクトリとして以下のように 6 個のデータファイルを読み込めば,始めることができる。
なお,それぞれのファイルの列を数値として読み込むか文字列として読み込むかはユーザが指定しなければならないことがある。入力結果を確認し,想定と違う場合には読み込み方を指示しなければならない。Julia では CSV.read() の types 引数で指定する。
#using DataFrames
using DataFramesMeta
using CSV
#using Query
basedirectory = "../Python/100knocks-preprocess/docker/work/data/"
df_customer = CSV.read(basedirectory * "customer.csv", DataFrame, types=Dict(3 => String, 10 => String));
df_category = CSV.read(basedirectory * "category.csv", DataFrame, types=String);
df_product = CSV.read(basedirectory * "product.csv", DataFrame, types=Dict(2 => String, 3 => String, 4 => String));
df_receipt = CSV.read(basedirectory * "receipt.csv", DataFrame);
df_store = CSV.read(basedirectory * "store.csv", DataFrame, types=Dict(3 => String));
df_geocode = CSV.read(basedirectory * "geocode.csv", DataFrame);
head(df, n=10) = begin println("size = $(size(df))"); println(first(df, n)) end;
はじめに
初めに以下のセルを実行してください必要なライブラリのインポートとデータベース(PostgreSQL)からのデータ読み込みを行いますpandas等、利用が想定されるライブラリは以下セルでインポートしていますその他利用したいライブラリがあれば適宜インストールしてください("!pip install ライブラリ名"でインストールも可能)- 処理は複数回に分けても構いません
- 名前、住所等はダミーデータであり、実在するものではありません
入力したデータフレームの確認
入力後のデータフレームの確認は,ここでは先頭 10 件を表示させ,目視で確認するということであるが,それぞれの列がどのように読み取られているかを確認すべきである。
実際には,各項目の度数分布を求めたり,ヒストグラムを描いたりして不適切なデータがあるかないかを確認すべきである。また,欠損値の有無と欠損値に特別の値が与えられているかどうかなどを確認しておく必要がある。
1. 単純な目視確認
J-001: レシート明細データ(df_receipt)から全項目の先頭10件を表示し、どのようなデータを保有しているか目視で確認せよ。
head(df_receipt)
size = (104681, 9)
[1m10×9 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m sales_epoch [0m[1m store_cd [0m[1m receipt_no [0m[1m receipt_sub_no [0m[1m customer_id [0m[1m product_cd [0m[1m quantity [0m[1m amount [0m
│[90m Int64 [0m[90m Int64 [0m[90m String7 [0m[90m Int64 [0m[90m Int64 [0m[90m String15 [0m[90m String15 [0m[90m Int64 [0m[90m Int64 [0m
─────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ 20181103 1541203200 S14006 112 1 CS006214000001 P070305012 1 158
2 │ 20181118 1542499200 S13008 1132 2 CS008415000097 P070701017 1 81
3 │ 20170712 1499817600 S14028 1102 1 CS028414000014 P060101005 1 170
4 │ 20190205 1549324800 S14042 1132 1 ZZ000000000000 P050301001 1 25
5 │ 20180821 1534809600 S14025 1102 2 CS025415000050 P060102007 1 90
6 │ 20190605 1559692800 S13003 1112 1 CS003515000195 P050102002 1 138
7 │ 20181205 1543968000 S14024 1102 2 CS024514000042 P080101005 1 30
8 │ 20190922 1569110400 S14040 1102 1 CS040415000178 P070501004 1 128
9 │ 20170504 1493856000 S13020 1112 2 ZZ000000000000 P071302010 1 770
10 │ 20191010 1570665600 S14027 1102 1 CS027514000015 P071101003 1 680
2. 必要な項目(列)のみを表示する
J-002: レシート明細データ(df_receipt)から売上年月日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、10件表示せよ。
@select(df_receipt, :sales_ymd, :customer_id, :product_cd, :amount) |> head
size = (104681, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m customer_id [0m[1m product_cd [0m[1m amount [0m
│[90m Int64 [0m[90m String15 [0m[90m String15 [0m[90m Int64 [0m
─────┼───────────────────────────────────────────────
1 │ 20181103 CS006214000001 P070305012 158
2 │ 20181118 CS008415000097 P070701017 81
3 │ 20170712 CS028414000014 P060101005 170
4 │ 20190205 ZZ000000000000 P050301001 25
5 │ 20180821 CS025415000050 P060102007 90
6 │ 20190605 CS003515000195 P050102002 138
7 │ 20181205 CS024514000042 P080101005 30
8 │ 20190922 CS040415000178 P070501004 128
9 │ 20170504 ZZ000000000000 P071302010 770
10 │ 20191010 CS027514000015 P071101003 680
J-003: レシート明細データ(df_receipt)から売上年月日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、10件表示せよ。ただし、sales_ymdをsales_dateに項目名を変更しながら抽出すること。
@select(df_receipt, :sales_date=:sales_ymd, :customer_id, :product_cd, :amount) |> head
size = (104681, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m sales_date [0m[1m customer_id [0m[1m product_cd [0m[1m amount [0m
│[90m Int64 [0m[90m String15 [0m[90m String15 [0m[90m Int64 [0m
─────┼────────────────────────────────────────────────
1 │ 20181103 CS006214000001 P070305012 158
2 │ 20181118 CS008415000097 P070701017 81
3 │ 20170712 CS028414000014 P060101005 170
4 │ 20190205 ZZ000000000000 P050301001 25
5 │ 20180821 CS025415000050 P060102007 90
6 │ 20190605 CS003515000195 P050102002 138
7 │ 20181205 CS024514000042 P080101005 30
8 │ 20190922 CS040415000178 P070501004 128
9 │ 20170504 ZZ000000000000 P071302010 770
10 │ 20191010 CS027514000015 P071101003 680
行と列の選択
3. 論理演算式による行の選択
Quiery の @filter() に比べて rsubset() の書き方はシンプルでわかりやすい。
J-004: レシート明細データ(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の条件を満たすデータを抽出せよ。
- 顧客ID(customer_id)が"CS018205000001"
df = @chain df_receipt begin
@select(:sales_ymd, :customer_id, :product_cd, :amount)
@rsubset(:customer_id == "CS018205000001")
end
println(df)
[1m12×4 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m customer_id [0m[1m product_cd [0m[1m amount [0m
│[90m Int64 [0m[90m String15 [0m[90m String15 [0m[90m Int64 [0m
─────┼───────────────────────────────────────────────
1 │ 20180911 CS018205000001 P071401012 2200
2 │ 20180414 CS018205000001 P060104007 600
3 │ 20170614 CS018205000001 P050206001 990
4 │ 20170614 CS018205000001 P060702015 108
5 │ 20190216 CS018205000001 P071005024 102
6 │ 20180414 CS018205000001 P071101002 278
7 │ 20190226 CS018205000001 P070902035 168
8 │ 20190924 CS018205000001 P060805001 495
9 │ 20190226 CS018205000001 P071401020 2200
10 │ 20180911 CS018205000001 P071401005 1100
11 │ 20190216 CS018205000001 P040101002 218
12 │ 20190924 CS018205000001 P091503001 280
J-005: レシート明細データ(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
- 顧客ID(customer_id)が"CS018205000001"
- 売上金額(amount)が1,000以上
df = @chain df_receipt begin
@select(:sales_ymd, :customer_id, :product_cd, :amount)
@rsubset(:customer_id == "CS018205000001")
@rsubset(:amount >= 1000)
end
println(df)
[1m3×4 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m customer_id [0m[1m product_cd [0m[1m amount [0m
│[90m Int64 [0m[90m String15 [0m[90m String15 [0m[90m Int64 [0m
─────┼───────────────────────────────────────────────
1 │ 20180911 CS018205000001 P071401012 2200
2 │ 20190226 CS018205000001 P071401020 2200
3 │ 20180911 CS018205000001 P071401005 1100
複数個の論理演算式は一つにまとめることができる。
df = @chain df_receipt begin
@select(:sales_ymd, :customer_id, :product_cd, :amount)
@rsubset(:customer_id == "CS018205000001" && :amount >= 1000)
end
println(df)
[1m3×4 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m customer_id [0m[1m product_cd [0m[1m amount [0m
│[90m Int64 [0m[90m String15 [0m[90m String15 [0m[90m Int64 [0m
─────┼───────────────────────────────────────────────
1 │ 20180911 CS018205000001 P071401012 2200
2 │ 20190226 CS018205000001 P071401020 2200
3 │ 20180911 CS018205000001 P071401005 1100
J-006: レシート明細データ(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上数量(quantity)、売上金額(amount)の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
- 顧客ID(customer_id)が"CS018205000001"
- 売上金額(amount)が1,000以上または売上数量(quantity)が5以上
df = @chain df_receipt begin
@select(:sales_ymd, :customer_id, :product_cd, :quantity, :amount)
@rsubset(:customer_id == "CS018205000001" && (:amount >= 1000 || :quantity >= 5))
end
println(df)
[1m5×5 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m customer_id [0m[1m product_cd [0m[1m quantity [0m[1m amount [0m
│[90m Int64 [0m[90m String15 [0m[90m String15 [0m[90m Int64 [0m[90m Int64 [0m
─────┼─────────────────────────────────────────────────────────
1 │ 20180911 CS018205000001 P071401012 1 2200
2 │ 20180414 CS018205000001 P060104007 6 600
3 │ 20170614 CS018205000001 P050206001 5 990
4 │ 20190226 CS018205000001 P071401020 1 2200
5 │ 20180911 CS018205000001 P071401005 1 1100
J-007: レシート明細データ(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
- 顧客ID(customer_id)が"CS018205000001"
- 売上金額(amount)が1,000以上2,000以下
df = @chain df_receipt begin
@select(:sales_ymd, :customer_id, :product_cd, :amount)
@rsubset(:customer_id == "CS018205000001" && 1000 <= :amount <= 2000)
end
println(df)
[1m1×4 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m customer_id [0m[1m product_cd [0m[1m amount [0m
│[90m Int64 [0m[90m String15 [0m[90m String15 [0m[90m Int64 [0m
─────┼───────────────────────────────────────────────
1 │ 20180911 CS018205000001 P071401005 1100
J-008: レシート明細データ(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の全ての条件を満たすデータを抽出せよ。
- 顧客ID(customer_id)が"CS018205000001"
- 商品コード(product_cd)が"P071401019"以外
df = @chain df_receipt begin
@select(:sales_ymd, :customer_id, :product_cd, :amount)
@rsubset(:customer_id == "CS018205000001" && :product_cd != "P071401019")
end
println(df)
[1m12×4 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m customer_id [0m[1m product_cd [0m[1m amount [0m
│[90m Int64 [0m[90m String15 [0m[90m String15 [0m[90m Int64 [0m
─────┼───────────────────────────────────────────────
1 │ 20180911 CS018205000001 P071401012 2200
2 │ 20180414 CS018205000001 P060104007 600
3 │ 20170614 CS018205000001 P050206001 990
4 │ 20170614 CS018205000001 P060702015 108
5 │ 20190216 CS018205000001 P071005024 102
6 │ 20180414 CS018205000001 P071101002 278
7 │ 20190226 CS018205000001 P070902035 168
8 │ 20190924 CS018205000001 P060805001 495
9 │ 20190226 CS018205000001 P071401020 2200
10 │ 20180911 CS018205000001 P071401005 1100
11 │ 20190216 CS018205000001 P040101002 218
12 │ 20190924 CS018205000001 P091503001 280
J-009: 以下の処理において、出力結果を変えずにORをANDに書き換えよ。
df_store.query('not(prefecture_cd == "13" | floor_area > 900)')
df = @rsubset(df_store, !(:prefecture_cd == "13" || :floor_area > 900))
println(df)
[1m3×10 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m store_name [0m[1m prefecture_cd [0m[1m prefecture [0m[1m address [0m[1m address_kana [0m[1m tel_no [0m[1m longitude [0m[1m latitude [0m[1m floor_area [0m
│[90m String7 [0m[90m String31 [0m[90m String [0m[90m String15 [0m[90m String [0m[90m String [0m[90m String15 [0m[90m Float64 [0m[90m Float64 [0m[90m Float64 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ S14046 北山田店 14 神奈川県 神奈川県横浜市都筑区北山田一丁目 カナガワケンヨコハマシツヅキクキ… 045-123-4049 139.592 35.5619 831.0
2 │ S14011 日吉本町店 14 神奈川県 神奈川県横浜市港北区日吉本町四丁… カナガワケンヨコハマシコウホクク… 045-123-4033 139.632 35.5466 890.0
3 │ S12013 習志野店 12 千葉県 千葉県習志野市芝園一丁目 チバケンナラシノシシバゾノイッチ… 047-123-4002 140.022 35.6612 808.0
df = @rsubset(df_store, :prefecture_cd != "13" && :floor_area <= 900)
println(df)
[1m3×10 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m store_name [0m[1m prefecture_cd [0m[1m prefecture [0m[1m address [0m[1m address_kana [0m[1m tel_no [0m[1m longitude [0m[1m latitude [0m[1m floor_area [0m
│[90m String7 [0m[90m String31 [0m[90m String [0m[90m String15 [0m[90m String [0m[90m String [0m[90m String15 [0m[90m Float64 [0m[90m Float64 [0m[90m Float64 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ S14046 北山田店 14 神奈川県 神奈川県横浜市都筑区北山田一丁目 カナガワケンヨコハマシツヅキクキ… 045-123-4049 139.592 35.5619 831.0
2 │ S14011 日吉本町店 14 神奈川県 神奈川県横浜市港北区日吉本町四丁… カナガワケンヨコハマシコウホクク… 045-123-4033 139.632 35.5466 890.0
3 │ S12013 習志野店 12 千葉県 千葉県習志野市芝園一丁目 チバケンナラシノシシバゾノイッチ… 047-123-4002 140.022 35.6612 808.0
4. 部分文字列の有無による選択(正規表現)
J-010: 店舗データ(df_store)から、店舗コード(store_cd)が"S14"で始まるものだけ全項目抽出し、10件表示せよ。
df = @rsubset(df_store, occursin(r"^S14", :store_cd))
head(df)
size = (23, 10)
[1m10×10 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m store_name [0m[1m prefecture_cd [0m[1m prefecture [0m[1m address [0m[1m address_kana [0m[1m tel_no [0m[1m longitude [0m[1m latitude [0m[1m floor_area [0m
│[90m String7 [0m[90m String31 [0m[90m String [0m[90m String15 [0m[90m String [0m[90m String [0m[90m String15 [0m[90m Float64 [0m[90m Float64 [0m[90m Float64 [0m
─────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ S14010 菊名店 14 神奈川県 神奈川県横浜市港北区菊名一丁目 カナガワケンヨコハマシコウホクク… 045-123-4032 139.633 35.5005 1732.0
2 │ S14033 阿久和店 14 神奈川県 神奈川県横浜市瀬谷区阿久和西一丁… カナガワケンヨコハマシセヤクアク… 045-123-4043 139.496 35.4592 1495.0
3 │ S14036 相模原中央店 14 神奈川県 神奈川県相模原市中央二丁目 カナガワケンサガミハラシチュウオ… 042-123-4045 139.372 35.5733 1679.0
4 │ S14040 長津田店 14 神奈川県 神奈川県横浜市緑区長津田みなみ台… カナガワケンヨコハマシミドリクナ… 045-123-4046 139.499 35.524 1548.0
5 │ S14050 阿久和西店 14 神奈川県 神奈川県横浜市瀬谷区阿久和西一丁… カナガワケンヨコハマシセヤクアク… 045-123-4053 139.496 35.4592 1830.0
6 │ S14028 二ツ橋店 14 神奈川県 神奈川県横浜市瀬谷区二ツ橋町 カナガワケンヨコハマシセヤクフタ… 045-123-4042 139.496 35.463 1574.0
7 │ S14012 本牧和田店 14 神奈川県 神奈川県横浜市中区本牧和田 カナガワケンヨコハマシナカクホン… 045-123-4034 139.658 35.4216 1341.0
8 │ S14046 北山田店 14 神奈川県 神奈川県横浜市都筑区北山田一丁目 カナガワケンヨコハマシツヅキクキ… 045-123-4049 139.592 35.5619 831.0
9 │ S14022 逗子店 14 神奈川県 神奈川県逗子市逗子一丁目 カナガワケンズシシズシイッチョウ… 046-123-4036 139.579 35.2964 1838.0
10 │ S14011 日吉本町店 14 神奈川県 神奈川県横浜市港北区日吉本町四丁… カナガワケンヨコハマシコウホクク… 045-123-4033 139.632 35.5466 890.0
J-011: 顧客データ(df_customer)から顧客ID(customer_id)の末尾が1のものだけ全項目抽出し、10件表示せよ。
df = @rsubset(df_customer, occursin(r"1$", :customer_id))
head(df)
size = (2369, 11)
[1m10×11 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS037613000071 六角 雅彦 9 不明 1952-04-01 66 136-0076 東京都江東区南砂********** S13037 20150414 0-00000000-0
2 │ CS028811000001 堀井 かおり 1 女性 1933-03-27 86 245-0016 神奈川県横浜市泉区和泉町********… S14028 20160115 0-00000000-0
3 │ CS040412000191 川井 郁恵 1 女性 1977-01-05 42 226-0021 神奈川県横浜市緑区北八朔町******… S14040 20151101 1-20091025-4
4 │ CS028314000011 小菅 あおい 1 女性 1983-11-26 35 246-0038 神奈川県横浜市瀬谷区宮沢********… S14028 20151123 1-20080426-5
5 │ CS039212000051 藤島 恵梨香 1 女性 1997-02-03 22 166-0001 東京都杉並区阿佐谷北********** S13039 20171121 1-20100215-4
6 │ CS015412000111 松居 奈月 1 女性 1972-10-04 46 136-0071 東京都江東区亀戸********** S13015 20150629 0-00000000-0
7 │ CS004702000041 野島 洋 0 男性 1943-08-24 75 176-0022 東京都練馬区向山********** S13004 20170218 0-00000000-0
8 │ CS041515000001 栗田 千夏 1 女性 1967-01-02 52 206-0001 東京都多摩市和田********** S13041 20160422 E-20100803-F
9 │ CS029313000221 北条 ひかり 1 女性 1987-06-19 31 279-0011 千葉県浦安市美浜********** S12029 20180810 0-00000000-0
10 │ CS034312000071 望月 奈央 1 女性 1980-09-20 38 213-0026 神奈川県川崎市高津区久末********… S14034 20160106 0-00000000-0
J-012: 店舗データ(df_store)から、住所 (address) に"横浜市"が含まれるものだけ全項目表示せよ。
df = @rsubset(df_store, occursin(r"横浜市", :address))
println(df)
[1m11×10 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m store_name [0m[1m prefecture_cd [0m[1m prefecture [0m[1m address [0m[1m address_kana [0m[1m tel_no [0m[1m longitude [0m[1m latitude [0m[1m floor_area [0m
│[90m String7 [0m[90m String31 [0m[90m String [0m[90m String15 [0m[90m String [0m[90m String [0m[90m String15 [0m[90m Float64 [0m[90m Float64 [0m[90m Float64 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ S14010 菊名店 14 神奈川県 神奈川県横浜市港北区菊名一丁目 カナガワケンヨコハマシコウホクク… 045-123-4032 139.633 35.5005 1732.0
2 │ S14033 阿久和店 14 神奈川県 神奈川県横浜市瀬谷区阿久和西一丁… カナガワケンヨコハマシセヤクアク… 045-123-4043 139.496 35.4592 1495.0
3 │ S14040 長津田店 14 神奈川県 神奈川県横浜市緑区長津田みなみ台… カナガワケンヨコハマシミドリクナ… 045-123-4046 139.499 35.524 1548.0
4 │ S14050 阿久和西店 14 神奈川県 神奈川県横浜市瀬谷区阿久和西一丁… カナガワケンヨコハマシセヤクアク… 045-123-4053 139.496 35.4592 1830.0
5 │ S14028 二ツ橋店 14 神奈川県 神奈川県横浜市瀬谷区二ツ橋町 カナガワケンヨコハマシセヤクフタ… 045-123-4042 139.496 35.463 1574.0
6 │ S14012 本牧和田店 14 神奈川県 神奈川県横浜市中区本牧和田 カナガワケンヨコハマシナカクホン… 045-123-4034 139.658 35.4216 1341.0
7 │ S14046 北山田店 14 神奈川県 神奈川県横浜市都筑区北山田一丁目 カナガワケンヨコハマシツヅキクキ… 045-123-4049 139.592 35.5619 831.0
8 │ S14011 日吉本町店 14 神奈川県 神奈川県横浜市港北区日吉本町四丁… カナガワケンヨコハマシコウホクク… 045-123-4033 139.632 35.5466 890.0
9 │ S14048 中川中央店 14 神奈川県 神奈川県横浜市都筑区中川中央二丁… カナガワケンヨコハマシツヅキクナ… 045-123-4051 139.576 35.5491 1657.0
10 │ S14042 新山下店 14 神奈川県 神奈川県横浜市中区新山下二丁目 カナガワケンヨコハマシナカクシン… 045-123-4047 139.659 35.4389 1044.0
11 │ S14006 葛が谷店 14 神奈川県 神奈川県横浜市都筑区葛が谷 カナガワケンヨコハマシツヅキクク… 045-123-4031 139.563 35.5357 1886.0
J-013: 顧客データ(df_customer)から、ステータスコード(status_cd)の先頭がアルファベットのA〜Fで始まるデータを全項目抽出し、10件表示せよ。
df = @rsubset(df_customer, occursin(r"^[A-F]", :status_cd))
head(df)
size = (3401, 11)
[1m10×11 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS031415000172 宇多田 貴美子 1 女性 1976-10-04 42 151-0053 東京都渋谷区代々木********** S13031 20150529 D-20100325-C
2 │ CS015414000103 奥野 陽子 1 女性 1977-08-09 41 136-0073 東京都江東区北砂********** S13015 20150722 B-20100609-B
3 │ CS011215000048 芦田 沙耶 1 女性 1992-02-01 27 223-0062 神奈川県横浜市港北区日吉本町****… S14011 20150228 C-20100421-9
4 │ CS029415000023 梅田 里穂 1 女性 1976-01-17 43 279-0043 千葉県浦安市富士見********** S12029 20150610 D-20100918-E
5 │ CS035415000029 寺沢 真希 9 不明 1977-09-27 41 158-0096 東京都世田谷区玉川台********** S13035 20141220 F-20101029-F
6 │ CS031415000106 宇野 由美子 1 女性 1970-02-26 49 151-0053 東京都渋谷区代々木********** S13031 20150201 F-20100511-E
7 │ CS029215000025 石倉 美帆 1 女性 1993-09-28 25 279-0022 千葉県浦安市今川********** S12029 20150708 B-20100820-C
8 │ CS033605000005 猪股 雄太 0 男性 1955-12-05 63 246-0031 神奈川県横浜市瀬谷区瀬谷********… S14033 20150425 F-20100917-E
9 │ CS033415000229 板垣 菜々美 1 女性 1977-11-07 41 246-0021 神奈川県横浜市瀬谷区二ツ橋町****… S14033 20150712 F-20100326-E
10 │ CS008415000145 黒谷 麻緒 1 女性 1977-06-27 41 157-0067 東京都世田谷区喜多見********** S13008 20150829 F-20100622-F
J-014: 顧客データ(df_customer)から、ステータスコード(status_cd)の末尾が数字の1〜9で終わるデータを全項目抽出し、10件表示せよ。
df = @rsubset(df_customer, occursin(r"[1-9]$", :status_cd))
head(df)
size = (4970, 11)
[1m10×11 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS001215000145 田崎 美紀 1 女性 1995-03-29 24 144-0055 東京都大田区仲六郷********** S13001 20170605 6-20090929-2
2 │ CS033513000180 安斎 遥 1 女性 1962-07-11 56 241-0823 神奈川県横浜市旭区善部町********… S14033 20150728 6-20080506-5
3 │ CS011215000048 芦田 沙耶 1 女性 1992-02-01 27 223-0062 神奈川県横浜市港北区日吉本町****… S14011 20150228 C-20100421-9
4 │ CS040412000191 川井 郁恵 1 女性 1977-01-05 42 226-0021 神奈川県横浜市緑区北八朔町******… S14040 20151101 1-20091025-4
5 │ CS009315000023 皆川 文世 1 女性 1980-04-15 38 154-0012 東京都世田谷区駒沢********** S13009 20150319 5-20080322-1
6 │ CS015315000033 福士 璃奈子 1 女性 1983-03-17 36 135-0043 東京都江東区塩浜********** S13015 20141024 4-20080219-3
7 │ CS023513000066 神戸 そら 1 女性 1961-12-17 57 210-0005 神奈川県川崎市川崎区東田町******… S14023 20150915 5-20100524-9
8 │ CS035513000134 市川 美帆 1 女性 1960-03-27 59 156-0053 東京都世田谷区桜********** S13035 20150227 8-20100711-9
9 │ CS001515000263 高松 夏空 1 女性 1962-11-09 56 144-0051 東京都大田区西蒲田********** S13001 20160812 1-20100804-1
10 │ CS040314000027 鶴田 きみまろ 9 不明 1986-03-26 33 226-0027 神奈川県横浜市緑区長津田********… S14040 20150122 2-20080426-4
J-015: 顧客データ(df_customer)から、ステータスコード(status_cd)の先頭がアルファベットのA〜Fで始まり、末尾が数字の1〜9で終わるデータを全項目抽出し、10件表示せよ。
df = @rsubset(df_customer, occursin(r"^[A-F].*[1-9]$", :status_cd))
head(df)
size = (620, 11)
[1m10×11 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS011215000048 芦田 沙耶 1 女性 1992-02-01 27 223-0062 神奈川県横浜市港北区日吉本町****… S14011 20150228 C-20100421-9
2 │ CS022513000105 島村 貴美子 1 女性 1962-03-12 57 249-0002 神奈川県逗子市山の根********** S14022 20150320 A-20091115-7
3 │ CS001515000096 水野 陽子 9 不明 1960-11-29 58 144-0053 東京都大田区蒲田本町********** S13001 20150614 A-20100724-7
4 │ CS013615000053 西脇 季衣 1 女性 1953-10-18 65 261-0026 千葉県千葉市美浜区幕張西********… S12013 20150128 B-20100329-6
5 │ CS020412000161 小宮 薫 1 女性 1974-05-21 44 174-0042 東京都板橋区東坂下********** S13020 20150822 B-20081021-3
6 │ CS001215000097 竹中 あさみ 1 女性 1990-07-25 28 146-0095 東京都大田区多摩川********** S13001 20170315 A-20100211-2
7 │ CS035212000007 内村 恵梨香 1 女性 1990-12-04 28 152-0023 東京都目黒区八雲********** S13035 20151013 B-20101018-6
8 │ CS002515000386 野田 コウ 1 女性 1963-05-30 55 185-0013 東京都国分寺市西恋ケ窪********** S13002 20160410 C-20100127-8
9 │ CS001615000372 稲垣 寿々花 1 女性 1956-10-29 62 144-0035 東京都大田区南蒲田********** S13001 20170403 A-20100104-1
10 │ CS032512000121 松井 知世 1 女性 1962-09-04 56 210-0011 神奈川県川崎市川崎区富士見******… S13032 20150727 A-20100103-5
J-016: 店舗データ(df_store)から、電話番号(tel_no)が3桁-3桁-4桁のデータを全項目表示せよ。
df = @rsubset(df_customer, occursin(r"[0-9]{3}-[0-9]{3}-[0-9]{4}", :status_cd))
head(df)
size = (0, 11)
[1m0×11 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m
─────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
df = df_store[occursin.(r"[0-9]{3}-[0-9]{3}-[0-9]{4}", df_store.tel_no), :]
println(df)
[1m34×10 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m store_name [0m[1m prefecture_cd [0m[1m prefecture [0m[1m address [0m[1m address_kana [0m[1m tel_no [0m[1m longitude [0m[1m latitude [0m[1m floor_area [0m
│[90m String7 [0m[90m String31 [0m[90m String [0m[90m String15 [0m[90m String [0m[90m String [0m[90m String15 [0m[90m Float64 [0m[90m Float64 [0m[90m Float64 [0m
─────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ S12014 千草台店 12 千葉県 千葉県千葉市稲毛区千草台一丁目 チバケンチバシイナゲクチグサダイ… 043-123-4003 140.118 35.6356 1698.0
2 │ S13002 国分寺店 13 東京都 東京都国分寺市本多二丁目 トウキョウトコクブンジシホンダニ… 042-123-4008 139.48 35.7057 1735.0
3 │ S14010 菊名店 14 神奈川県 神奈川県横浜市港北区菊名一丁目 カナガワケンヨコハマシコウホクク… 045-123-4032 139.633 35.5005 1732.0
4 │ S14033 阿久和店 14 神奈川県 神奈川県横浜市瀬谷区阿久和西一丁… カナガワケンヨコハマシセヤクアク… 045-123-4043 139.496 35.4592 1495.0
5 │ S14036 相模原中央店 14 神奈川県 神奈川県相模原市中央二丁目 カナガワケンサガミハラシチュウオ… 042-123-4045 139.372 35.5733 1679.0
6 │ S14040 長津田店 14 神奈川県 神奈川県横浜市緑区長津田みなみ台… カナガワケンヨコハマシミドリクナ… 045-123-4046 139.499 35.524 1548.0
7 │ S14050 阿久和西店 14 神奈川県 神奈川県横浜市瀬谷区阿久和西一丁… カナガワケンヨコハマシセヤクアク… 045-123-4053 139.496 35.4592 1830.0
8 │ S13052 森野店 13 東京都 東京都町田市森野三丁目 トウキョウトマチダシモリノサンチ… 042-123-4030 139.438 35.5529 1087.0
9 │ S14028 二ツ橋店 14 神奈川県 神奈川県横浜市瀬谷区二ツ橋町 カナガワケンヨコハマシセヤクフタ… 045-123-4042 139.496 35.463 1574.0
10 │ S14012 本牧和田店 14 神奈川県 神奈川県横浜市中区本牧和田 カナガワケンヨコハマシナカクホン… 045-123-4034 139.658 35.4216 1341.0
11 │ S14046 北山田店 14 神奈川県 神奈川県横浜市都筑区北山田一丁目 カナガワケンヨコハマシツヅキクキ… 045-123-4049 139.592 35.5619 831.0
12 │ S14022 逗子店 14 神奈川県 神奈川県逗子市逗子一丁目 カナガワケンズシシズシイッチョウ… 046-123-4036 139.579 35.2964 1838.0
13 │ S14011 日吉本町店 14 神奈川県 神奈川県横浜市港北区日吉本町四丁… カナガワケンヨコハマシコウホクク… 045-123-4033 139.632 35.5466 890.0
14 │ S13016 小金井店 13 東京都 東京都小金井市本町一丁目 トウキョウトコガネイシホンチョウ… 042-123-4015 139.509 35.7002 1399.0
15 │ S14034 川崎野川店 14 神奈川県 神奈川県川崎市宮前区野川 カナガワケンカワサキシミヤマエク… 044-123-4044 139.6 35.5769 1318.0
16 │ S14048 中川中央店 14 神奈川県 神奈川県横浜市都筑区中川中央二丁… カナガワケンヨコハマシツヅキクナ… 045-123-4051 139.576 35.5491 1657.0
17 │ S12007 佐倉店 12 千葉県 千葉県佐倉市上志津 チバケンサクラシカミシヅ 043-123-4001 140.145 35.7187 1895.0
18 │ S14026 辻堂西海岸店 14 神奈川県 神奈川県藤沢市辻堂西海岸二丁目 カナガワケンフジサワシツジドウニ… 046-123-4040 139.447 35.3246 1732.0
19 │ S13041 八王子店 13 東京都 東京都八王子市大塚 トウキョウトハチオウジシオオツカ 042-123-4026 139.423 35.6379 810.0
20 │ S14049 川崎大師店 14 神奈川県 神奈川県川崎市川崎区中瀬三丁目 カナガワケンカワサキシカワサキク… 044-123-4052 139.733 35.5376 962.0
21 │ S14023 川崎店 14 神奈川県 神奈川県川崎市川崎区本町二丁目 カナガワケンカワサキシカワサキク… 044-123-4037 139.703 35.536 1804.0
22 │ S13018 清瀬店 13 東京都 東京都清瀬市松山一丁目 トウキョウトキヨセシマツヤマイッ… 042-123-4017 139.518 35.7689 1220.0
23 │ S14027 南藤沢店 14 神奈川県 神奈川県藤沢市南藤沢 カナガワケンフジサワシミナミフジ… 046-123-4041 139.49 35.3376 1521.0
24 │ S14021 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨ… 046-123-4035 139.313 35.4017 962.0
25 │ S14047 相模原店 14 神奈川県 神奈川県相模原市千代田六丁目 カナガワケンサガミハラシチヨダロ… 042-123-4050 139.375 35.5596 1047.0
26 │ S12013 習志野店 12 千葉県 千葉県習志野市芝園一丁目 チバケンナラシノシシバゾノイッチ… 047-123-4002 140.022 35.6612 808.0
27 │ S14042 新山下店 14 神奈川県 神奈川県横浜市中区新山下二丁目 カナガワケンヨコハマシナカクシン… 045-123-4047 139.659 35.4389 1044.0
28 │ S12030 八幡店 12 千葉県 千葉県市川市八幡三丁目 チバケンイチカワシヤワタサンチョ… 047-123-4005 139.924 35.7232 1162.0
29 │ S14025 大和店 14 神奈川県 神奈川県大和市下和田 カナガワケンヤマトシシモワダ 046-123-4039 139.468 35.4341 1011.0
30 │ S14045 厚木店 14 神奈川県 神奈川県厚木市中町二丁目 カナガワケンアツギシナカチョウニ… 046-123-4048 139.365 35.4418 980.0
31 │ S12029 東野店 12 千葉県 千葉県浦安市東野一丁目 チバケンウラヤスシヒガシノイッチ… 047-123-4004 139.897 35.6509 1101.0
32 │ S12053 高洲店 12 千葉県 千葉県浦安市高洲五丁目 チバケンウラヤスシタカスゴチョウ… 047-123-4006 139.918 35.6375 1555.0
33 │ S14024 三田店 14 神奈川県 神奈川県川崎市多摩区三田四丁目 カナガワケンカワサキシタマクミタ… 044-123-4038 139.542 35.6077 972.0
34 │ S14006 葛が谷店 14 神奈川県 神奈川県横浜市都筑区葛が谷 カナガワケンヨコハマシツヅキクク… 045-123-4031 139.563 35.5357 1886.0
データフレームの並べ替え(sort)
5. 列でソート
J-017: 顧客データ(df_customer)を生年月日(birth_day)で高齢順にソートし、先頭から全項目を10件表示せよ。
df = @orderby(df_customer, :birth_day)
head(df)
size = (21971, 11)
[1m10×11 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS003813000014 村山 菜々美 1 女性 1928-11-26 90 182-0007 東京都調布市菊野台********** S13003 20160214 0-00000000-0
2 │ CS026813000004 吉村 朝陽 1 女性 1928-12-14 90 251-0043 神奈川県藤沢市辻堂元町********** S14026 20150723 0-00000000-0
3 │ CS018811000003 熊沢 美里 1 女性 1929-01-07 90 204-0004 東京都清瀬市野塩********** S13018 20150403 0-00000000-0
4 │ CS027803000004 内村 拓郎 0 男性 1929-01-12 90 251-0031 神奈川県藤沢市鵠沼藤が谷********… S14027 20151227 0-00000000-0
5 │ CS013801000003 天野 拓郎 0 男性 1929-01-15 90 274-0824 千葉県船橋市前原東********** S12013 20160120 0-00000000-0
6 │ CS001814000022 鶴田 里穂 1 女性 1929-01-28 90 144-0045 東京都大田区南六郷********** S13001 20161012 A-20090415-7
7 │ CS016815000002 山元 美紀 1 女性 1929-02-22 90 184-0005 東京都小金井市桜町********** S13016 20150629 C-20090923-C
8 │ CS009815000003 中田 里穂 1 女性 1929-04-08 89 154-0014 東京都世田谷区新町********** S13009 20150421 D-20091021-E
9 │ CS012813000013 宇野 南朋 1 女性 1929-04-09 89 231-0806 神奈川県横浜市中区本牧町********… S14012 20150712 0-00000000-0
10 │ CS005813000015 金谷 恵梨香 1 女性 1929-04-09 89 165-0032 東京都中野区鷺宮********** S13005 20150506 0-00000000-0
J-018: 顧客データ(df_customer)を生年月日(birth_day)で若い順にソートし、先頭から全項目を10件表示せよ。
文字列データの降順ソートはちょっとまだるっこしい。これは,@orderby()
の作りが悪いからであろう。
df = @orderby(df_customer, invperm(sortperm(:birth_day, rev=true)))
head(df)
size = (21971, 11)
[1m10×11 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS035114000004 大村 美里 1 女性 2007-11-25 11 156-0053 東京都世田谷区桜********** S13035 20150619 6-20091205-6
2 │ CS022103000002 福山 はじめ 9 不明 2007-10-02 11 249-0006 神奈川県逗子市逗子********** S14022 20160909 0-00000000-0
3 │ CS002113000009 柴田 真悠子 1 女性 2007-09-17 11 184-0014 東京都小金井市貫井南町********** S13002 20160304 0-00000000-0
4 │ CS004115000014 松井 京子 1 女性 2007-08-09 11 165-0031 東京都中野区上鷺宮********** S13004 20161120 1-20081231-1
5 │ CS002114000010 山内 遥 1 女性 2007-06-03 11 184-0015 東京都小金井市貫井北町********** S13002 20160920 6-20100510-1
6 │ CS025115000002 小柳 夏希 1 女性 2007-04-18 11 245-0018 神奈川県横浜市泉区上飯田町******… S14025 20160116 D-20100913-D
7 │ CS002113000025 広末 まなみ 1 女性 2007-03-30 12 184-0015 東京都小金井市貫井北町********** S13002 20171030 0-00000000-0
8 │ CS033112000003 長野 美紀 1 女性 2007-03-22 12 245-0051 神奈川県横浜市戸塚区名瀬町******… S14033 20150606 0-00000000-0
9 │ CS007115000006 福岡 瞬 1 女性 2007-03-10 12 285-0845 千葉県佐倉市西志津********** S12007 20151118 F-20101016-F
10 │ CS014113000008 矢口 莉緒 1 女性 2007-03-05 12 260-0041 千葉県千葉市中央区東千葉********… S12014 20150622 3-20091108-6
Base.sort のほうがわかりやすい。
df = sort(df_customer, :birth_day, rev=true)
head(df)
size = (21971, 11)
[1m10×11 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS035114000004 大村 美里 1 女性 2007-11-25 11 156-0053 東京都世田谷区桜********** S13035 20150619 6-20091205-6
2 │ CS022103000002 福山 はじめ 9 不明 2007-10-02 11 249-0006 神奈川県逗子市逗子********** S14022 20160909 0-00000000-0
3 │ CS002113000009 柴田 真悠子 1 女性 2007-09-17 11 184-0014 東京都小金井市貫井南町********** S13002 20160304 0-00000000-0
4 │ CS004115000014 松井 京子 1 女性 2007-08-09 11 165-0031 東京都中野区上鷺宮********** S13004 20161120 1-20081231-1
5 │ CS002114000010 山内 遥 1 女性 2007-06-03 11 184-0015 東京都小金井市貫井北町********** S13002 20160920 6-20100510-1
6 │ CS025115000002 小柳 夏希 1 女性 2007-04-18 11 245-0018 神奈川県横浜市泉区上飯田町******… S14025 20160116 D-20100913-D
7 │ CS002113000025 広末 まなみ 1 女性 2007-03-30 12 184-0015 東京都小金井市貫井北町********** S13002 20171030 0-00000000-0
8 │ CS033112000003 長野 美紀 1 女性 2007-03-22 12 245-0051 神奈川県横浜市戸塚区名瀬町******… S14033 20150606 0-00000000-0
9 │ CS007115000006 福岡 瞬 1 女性 2007-03-10 12 285-0845 千葉県佐倉市西志津********** S12007 20151118 F-20101016-F
10 │ CS014113000008 矢口 莉緒 1 女性 2007-03-05 12 260-0041 千葉県千葉市中央区東千葉********… S12014 20150622 3-20091108-6
6. 順位付けをしてソート
順位付けは StatsBase パッケージに tiedrank()
, competerank()
, ordinalrank()
がある。
J-019: レシート明細データ(df_receipt)に対し、1件あたりの売上金額(amount)が高い順にランクを付与し、先頭から10件表示せよ。項目は顧客ID(customer_id)、売上金額(amount)、付与したランクを表示させること。なお、売上金額(amount)が等しい場合は同一順位を付与するものとする。
using StatsBase
df = @chain df_receipt begin
@select(:customer_id, :amount, :rank = competerank(:amount, rev=true))
@orderby(:rank)
end
head(df)
size = (104681, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m amount [0m[1m rank [0m
│[90m String15 [0m[90m Int64 [0m[90m Int64 [0m
─────┼───────────────────────────────
1 │ CS011415000006 10925 1
2 │ ZZ000000000000 6800 2
3 │ CS028605000002 5780 3
4 │ CS015515000034 5480 4
5 │ ZZ000000000000 5480 4
6 │ ZZ000000000000 5480 4
7 │ ZZ000000000000 5440 7
8 │ CS021515000089 5440 7
9 │ CS015515000083 5280 9
10 │ CS017414000114 5280 9
J-020: レシート明細データ(df_receipt)に対し、1件あたりの売上金額(amount)が高い順にランクを付与し、先頭から10件表示せよ。項目は顧客ID(customer_id)、売上金額(amount)、付与したランクを表示させること。なお、売上金額(amount)が等しい場合でも別順位を付与すること。
using StatsBase
df = @chain df_receipt begin
@select(:customer_id, :amount, :rank = ordinalrank(:amount, rev=true))
@orderby(:rank)
end
head(df)
size = (104681, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m amount [0m[1m rank [0m
│[90m String15 [0m[90m Int64 [0m[90m Int64 [0m
─────┼───────────────────────────────
1 │ CS011415000006 10925 1
2 │ ZZ000000000000 6800 2
3 │ CS028605000002 5780 3
4 │ CS015515000034 5480 4
5 │ ZZ000000000000 5480 5
6 │ ZZ000000000000 5480 6
7 │ ZZ000000000000 5440 7
8 │ CS021515000089 5440 8
9 │ CS015515000083 5280 9
10 │ CS017414000114 5280 10
件数(行数)の確認
J-021: レシート明細データ(df_receipt)に対し、件数をカウントせよ。
nrow(df_receipt)
104681
J-022: レシート明細データ(df_receipt)の顧客ID(customer_id)に対し、ユニーク件数をカウントせよ。
ユニークなデータ,データフレームを作るには unique()
を使う。
length(unique(df_receipt.customer_id))
8307
@chain df_receipt begin
unique(:customer_id)
nrow
end
8307
@chain df_receipt begin
@distinct(:customer_id)
nrow
end
8307
グループ化して処理
groupby() によってグループ化して,それぞれのグループ化データフレームを combine()
によって処理して,その結果をデータフレームとして生成する。
7. 合計
J-023: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)と売上数量(quantity)を合計せよ。
df = @chain df_receipt begin
groupby(:store_cd)
@combine(:amount = sum(:amount), :quantity = sum(:quantity))
@orderby(:store_cd)
end
println(df)
[1m52×3 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m amount [0m[1m quantity [0m
│[90m String7 [0m[90m Int64 [0m[90m Int64 [0m
─────┼────────────────────────────
1 │ S12007 638761 2099
2 │ S12013 787513 2425
3 │ S12014 725167 2358
4 │ S12029 794741 2555
5 │ S12030 684402 2403
6 │ S13001 811936 2347
7 │ S13002 727821 2340
8 │ S13003 764294 2197
9 │ S13004 779373 2390
10 │ S13005 629876 2004
11 │ S13008 809288 2491
12 │ S13009 808870 2486
13 │ S13015 780873 2248
14 │ S13016 793773 2432
15 │ S13017 748221 2376
16 │ S13018 790535 2562
17 │ S13019 827833 2541
18 │ S13020 796383 2383
19 │ S13031 705968 2336
20 │ S13032 790501 2491
21 │ S13035 715869 2219
22 │ S13037 693087 2344
23 │ S13038 708884 2337
24 │ S13039 611888 1981
25 │ S13041 728266 2233
26 │ S13043 587895 1881
27 │ S13044 520764 1729
28 │ S13051 107452 354
29 │ S13052 100314 250
30 │ S14006 712839 2284
31 │ S14010 790361 2290
32 │ S14011 805724 2434
33 │ S14012 720600 2412
34 │ S14021 699511 2231
35 │ S14022 651328 2047
36 │ S14023 727630 2258
37 │ S14024 736323 2417
38 │ S14025 755581 2394
39 │ S14026 824537 2503
40 │ S14027 714550 2303
41 │ S14028 786145 2458
42 │ S14033 725318 2282
43 │ S14034 653681 2024
44 │ S14036 203694 635
45 │ S14040 701858 2233
46 │ S14042 534689 1935
47 │ S14045 458484 1398
48 │ S14046 412646 1354
49 │ S14047 338329 1041
50 │ S14048 234276 769
51 │ S14049 230808 788
52 │ S14050 167090 580
8. 最大値
J-024: レシート明細データ(df_receipt)に対し、顧客ID(customer_id)ごとに最も新しい売上年月日(sales_ymd)を求め、10件表示せよ。
df = @chain df_receipt begin
groupby(:customer_id)
@combine(:sales_ymd_maximum = maximum(:sales_ymd))
@orderby(:customer_id) # ソートする必要がある場合
end
head(df)
size = (8307, 2)
[1m10×2 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sales_ymd_maximum [0m
│[90m String15 [0m[90m Int64 [0m
─────┼───────────────────────────────────
1 │ CS001113000004 20190308
2 │ CS001114000005 20190731
3 │ CS001115000010 20190405
4 │ CS001205000004 20190625
5 │ CS001205000006 20190224
6 │ CS001211000025 20190322
7 │ CS001212000027 20170127
8 │ CS001212000031 20180906
9 │ CS001212000046 20170811
10 │ CS001212000070 20191018
9. 最小値
J-025: レシート明細データ(df_receipt)に対し、顧客ID(customer_id)ごとに最も古い売上年月日(sales_ymd)を求め、10件表示せよ。
df = @chain df_receipt begin
groupby(:customer_id)
@combine(:sales_ymd_minimum = minimum(:sales_ymd))
@orderby(:customer_id) # ソートする必要がある場合
end
head(df)
size = (8307, 2)
[1m10×2 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sales_ymd_minimum [0m
│[90m String15 [0m[90m Int64 [0m
─────┼───────────────────────────────────
1 │ CS001113000004 20190308
2 │ CS001114000005 20180503
3 │ CS001115000010 20171228
4 │ CS001205000004 20170914
5 │ CS001205000006 20180207
6 │ CS001211000025 20190322
7 │ CS001212000027 20170127
8 │ CS001212000031 20180906
9 │ CS001212000046 20170811
10 │ CS001212000070 20191018
10. 比較演算,論理演算
J-026: レシート明細データ(df_receipt)に対し、顧客ID(customer_id)ごとに最も新しい売上年月日(sales_ymd)と古い売上年月日を求め、両者が異なるデータを10件表示せよ。
df = @chain df_receipt begin
groupby(:customer_id)
@combine(:max_ymd = maximum(:sales_ymd), :min_ymd = minimum(:sales_ymd))
@rsubset(:min_ymd != :max_ymd)
@orderby(:customer_id) # ソートする必要がある場合
end
head(df)
size = (5546, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m max_ymd [0m[1m min_ymd [0m
│[90m String15 [0m[90m Int64 [0m[90m Int64 [0m
─────┼────────────────────────────────────
1 │ CS001114000005 20190731 20180503
2 │ CS001115000010 20190405 20171228
3 │ CS001205000004 20190625 20170914
4 │ CS001205000006 20190224 20180207
5 │ CS001214000009 20190902 20170306
6 │ CS001214000017 20191006 20180828
7 │ CS001214000048 20190929 20171109
8 │ CS001214000052 20190617 20180208
9 │ CS001215000005 20181021 20170206
10 │ CS001215000040 20171022 20170214
11. 平均値
J-027: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、降順でTOP5を表示せよ。
using StatsBase
df = @chain df_receipt begin
groupby(:store_cd)
@combine(:mean_amount = mean(:amount))
@orderby(-:mean_amount)
end
head(df, 5)
size = (52, 2)
[1m5×2 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m mean_amount [0m
│[90m String7 [0m[90m Float64 [0m
─────┼───────────────────────
1 │ S13052 402.867
2 │ S13015 351.112
3 │ S13003 350.916
4 │ S14010 348.791
5 │ S13001 348.47
12. 中央値
J-028: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の中央値を計算し、降順でTOP5を表示せよ。
df = @chain df_receipt begin
groupby(:store_cd)
@combine(:median_amount = median(:amount))
@orderby(-:median_amount)
end
head(df, 5)
size = (52, 2)
[1m5×2 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m median_amount [0m
│[90m String7 [0m[90m Float64 [0m
─────┼─────────────────────────
1 │ S13052 190.0
2 │ S14010 188.0
3 │ S14050 185.0
4 │ S13003 180.0
5 │ S14040 180.0
13. 最頻値
J-029: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに商品コード(product_cd)の最頻値を求め、10件表示させよ。
using FreqTables
df = @chain df_receipt begin
groupby(:store_cd)
@combine(:product_cd_mode = mode(:product_cd), :cnt = maximum(freqtable(:product_cd)))
@orderby(:store_cd)
end
head(df)
size = (52, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m product_cd_mode [0m[1m cnt [0m
│[90m String7 [0m[90m String15 [0m[90m Int64 [0m
─────┼──────────────────────────────────
1 │ S12007 P060303001 72
2 │ S12013 P060303001 107
3 │ S12014 P060303001 65
4 │ S12029 P060303001 92
5 │ S12030 P060303001 115
6 │ S13001 P060303001 67
7 │ S13002 P060303001 78
8 │ S13003 P071401001 65
9 │ S13004 P060303001 88
10 │ S13005 P040503001 36
14. 分散
J-030: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の分散を計算し、降順で5件表示せよ。
df = @chain df_receipt begin
groupby(:store_cd)
@combine(:var_amount = var(:amount, corrected=false))
@orderby(-:var_amount)
end
head(df, 5)
size = (52, 2)
[1m5×2 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m var_amount [0m
│[90m String7 [0m[90m Float64 [0m
─────┼──────────────────────────
1 │ S13052 4.40089e5
2 │ S14011 3.06315e5
3 │ S14034 2.9692e5
4 │ S13001 295432.0
5 │ S13015 2.95294e5
15. 標準偏差
J-031: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の標準偏差を計算し、降順で5件表示せよ。
df = @chain df_receipt begin
groupby(:store_cd)
@combine(:std_amount = std(:amount, corrected=false))
@orderby(-:std_amount)
end
head(df, 5)
size = (52, 2)
[1m5×2 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m std_amount [0m
│[90m String7 [0m[90m Float64 [0m
─────┼──────────────────────
1 │ S13052 663.392
2 │ S14011 553.457
3 │ S14034 544.904
4 │ S13001 543.537
5 │ S13015 543.41
16. パーセンタイル値(第1四分位数,中央値,第3四分位数)
J-032: レシート明細データ(df_receipt)の売上金額(amount)について、25%刻みでパーセンタイル値を求めよ。
df = @combine(df_receipt, :quantile = quantile(:amount, 0.25:0.25:1))
println(df)
[1m4×1 DataFrame[0m
[1m Row [0m│[1m quantile [0m
│[90m Float64 [0m
─────┼──────────
1 │ 102.0
2 │ 170.0
3 │ 288.0
4 │ 10925.0
17. 比較演算,論理演算
J-033: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、330以上のものを抽出せよ。
df = @chain df_receipt begin
groupby(:store_cd)
@combine(:mean_amount = mean(:amount))
@rsubset(:mean_amount >= 330)
@orderby(:store_cd)
end
println(df)
[1m13×2 DataFrame[0m
[1m Row [0m│[1m store_cd [0m[1m mean_amount [0m
│[90m String7 [0m[90m Float64 [0m
─────┼───────────────────────
1 │ S12013 330.194
2 │ S13001 348.47
3 │ S13003 350.916
4 │ S13004 330.944
5 │ S13015 351.112
6 │ S13019 330.209
7 │ S13020 337.88
8 │ S13052 402.867
9 │ S14010 348.791
10 │ S14011 335.718
11 │ S14026 332.341
12 │ S14045 330.082
13 │ S14047 330.077
18. グループ化されたデータフレームごとの集計結果との比較
J-034: レシート明細データ(df_receipt)に対し、顧客ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求めよ。ただし、顧客IDが"Z"から始まるものは非会員を表すため、除外して計算すること。
df = @chain df_receipt begin
@rsubset(!occursin(r"^Z", :customer_id))
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
end
mean(df.sum_amount)
2547.742234529256
J-035: レシート明細データ(df_receipt)に対し、顧客ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求め、平均以上に買い物をしている顧客を抽出し、10件表示せよ。ただし、顧客IDが"Z"から始まるものは非会員を表すため、除外して計算すること。
df = @chain df_receipt begin
@rsubset(!occursin(r"^Z", :customer_id))
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
end
# mean(df.sum_amount)
df2 = @chain df begin
@rsubset(:sum_amount > mean(df.sum_amount))
@orderby(:customer_id)
end
head(df2)
size = (2996, 2)
[1m10×2 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sum_amount [0m
│[90m String15 [0m[90m Int64 [0m
─────┼────────────────────────────
1 │ CS001115000010 3044
2 │ CS001205000006 3337
3 │ CS001214000009 4685
4 │ CS001214000017 4132
5 │ CS001214000052 5639
6 │ CS001215000040 3496
7 │ CS001304000006 3726
8 │ CS001305000005 3485
9 │ CS001305000011 4370
10 │ CS001315000180 3300
データフレームの結合(join)
19. innnerjoin()
J-036: レシート明細データ(df_receipt)と店舗データ(df_store)を内部結合し、レシート明細データの全項目と店舗データの店舗名(store_name)を10件表示せよ。
df = innerjoin(df_receipt, df_store[!, [:store_cd, :store_name]], on=:store_cd)
head(df)
size = (104681, 10)
[1m10×10 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m sales_epoch [0m[1m store_cd [0m[1m receipt_no [0m[1m receipt_sub_no [0m[1m customer_id [0m[1m product_cd [0m[1m quantity [0m[1m amount [0m[1m store_name [0m
│[90m Int64 [0m[90m Int64 [0m[90m String7 [0m[90m Int64 [0m[90m Int64 [0m[90m String15 [0m[90m String15 [0m[90m Int64 [0m[90m Int64 [0m[90m String31 [0m
─────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ 20181103 1541203200 S14006 112 1 CS006214000001 P070305012 1 158 葛が谷店
2 │ 20181118 1542499200 S13008 1132 2 CS008415000097 P070701017 1 81 成城店
3 │ 20170712 1499817600 S14028 1102 1 CS028414000014 P060101005 1 170 二ツ橋店
4 │ 20190205 1549324800 S14042 1132 1 ZZ000000000000 P050301001 1 25 新山下店
5 │ 20180821 1534809600 S14025 1102 2 CS025415000050 P060102007 1 90 大和店
6 │ 20190605 1559692800 S13003 1112 1 CS003515000195 P050102002 1 138 狛江店
7 │ 20181205 1543968000 S14024 1102 2 CS024514000042 P080101005 1 30 三田店
8 │ 20190922 1569110400 S14040 1102 1 CS040415000178 P070501004 1 128 長津田店
9 │ 20170504 1493856000 S13020 1112 2 ZZ000000000000 P071302010 1 770 十条仲原店
10 │ 20191010 1570665600 S14027 1102 1 CS027514000015 P071101003 1 680 南藤沢店
J-037: 商品データ(df_product)とカテゴリデータ(df_category)を内部結合し、商品データの全項目とカテゴリデータのカテゴリ小区分名(category_small_name)を10件表示せよ。
df = innerjoin(df_product, df_category[!, [:category_small_name, :category_small_cd]], on=:category_small_cd)
head(df)
size = (10030, 7)
[1m10×7 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m category_major_cd [0m[1m category_medium_cd [0m[1m category_small_cd [0m[1m unit_price [0m[1m unit_cost [0m[1m category_small_name [0m
│[90m String15 [0m[90m String [0m[90m String [0m[90m String [0m[90m Int64? [0m[90m Int64? [0m[90m String [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ P040101001 04 0401 040101 198 149 弁当類
2 │ P040101002 04 0401 040101 218 164 弁当類
3 │ P040101003 04 0401 040101 230 173 弁当類
4 │ P040101004 04 0401 040101 248 186 弁当類
5 │ P040101005 04 0401 040101 268 201 弁当類
6 │ P040101006 04 0401 040101 298 224 弁当類
7 │ P040101007 04 0401 040101 338 254 弁当類
8 │ P040101008 04 0401 040101 420 315 弁当類
9 │ P040101009 04 0401 040101 498 374 弁当類
10 │ P040101010 04 0401 040101 580 435 弁当類
20. leftjoin()
J-038: 顧客データ(df_customer)とレシート明細データ(df_receipt)から、顧客ごとの売上金額合計を求め、10件表示せよ。ただし、売上実績がない顧客については売上金額を0として表示させること。また、顧客は性別コード(gender_cd)が女性(1)であるものを対象とし、非会員(顧客IDが"Z"から始まるもの)は除外すること。
df = leftjoin(df_customer[!, [:customer_id, :gender_cd]], df_receipt[!, [:customer_id, :amount]], on=:customer_id)
df2 = @chain df begin
@rsubset(!occursin(r"^Z", :customer_id) && :gender_cd == "1")
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
#@rtransform(:sum_amount = ismissing(:sum_amount) ? 0 : :sum_amount) # coalesce() は missing の置換に使える
@rtransform(:sum_amount = coalesce(:sum_amount, 0))
@orderby(:customer_id)
end
head(df2)
size = (17918, 2)
[1m10×2 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sum_amount [0m
│[90m String15 [0m[90m Int64 [0m
─────┼────────────────────────────
1 │ CS001112000009 0
2 │ CS001112000019 0
3 │ CS001112000021 0
4 │ CS001112000023 0
5 │ CS001112000024 0
6 │ CS001112000029 0
7 │ CS001112000030 0
8 │ CS001113000004 1298
9 │ CS001113000010 0
10 │ CS001114000005 626
21. outerjoin()
J-039: レシート明細データ(df_receipt)から、売上日数の多い顧客の上位20件を抽出したデータと、売上金額合計の多い顧客の上位20件を抽出したデータをそれぞれ作成し、さらにその2つを完全外部結合せよ。ただし、非会員(顧客IDが"Z"から始まるもの)は除外すること。
df = @chain df_receipt begin
@rsubset(!occursin(r"^Z", :customer_id))
groupby(:customer_id)
end
df2 = @chain df begin
@combine(:come_days = length(unique(:sales_ymd)))
@orderby(-:come_days)
end
df3 = @chain df begin
@combine(:sum_amount = sum(:amount))
@orderby(-:sum_amount)
end
df4 = outerjoin(df2[1:20, :], df3[1:20, :], on=:customer_id)
println(df4)
[1m34×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m come_days [0m[1m sum_amount [0m
│[90m String15 [0m[90m Int64? [0m[90m Int64? [0m
─────┼───────────────────────────────────────
1 │ CS017415000097 20 23086
2 │ CS015415000185 22 20153
3 │ CS031414000051 19 19202
4 │ CS028415000007 21 19127
5 │ CS010214000010 22 18585
6 │ CS016415000141 20 18372
7 │ CS040214000008 23 [90m missing [0m
8 │ CS010214000002 21 [90m missing [0m
9 │ CS039414000052 19 [90m missing [0m
10 │ CS021514000045 19 [90m missing [0m
11 │ CS022515000226 19 [90m missing [0m
12 │ CS014214000023 19 [90m missing [0m
13 │ CS021515000172 19 [90m missing [0m
14 │ CS014415000077 18 [90m missing [0m
15 │ CS030214000008 18 [90m missing [0m
16 │ CS021515000056 18 [90m missing [0m
17 │ CS031414000073 18 [90m missing [0m
18 │ CS032415000209 18 [90m missing [0m
19 │ CS007515000107 18 [90m missing [0m
20 │ CS021515000211 18 [90m missing [0m
21 │ CS001605000009 [90m missing [0m 18925
22 │ CS006515000023 [90m missing [0m 18372
23 │ CS011414000106 [90m missing [0m 18338
24 │ CS038415000104 [90m missing [0m 17847
25 │ CS035414000024 [90m missing [0m 17615
26 │ CS021515000089 [90m missing [0m 17580
27 │ CS032414000072 [90m missing [0m 16563
28 │ CS016415000101 [90m missing [0m 16348
29 │ CS011415000006 [90m missing [0m 16094
30 │ CS034415000047 [90m missing [0m 16083
31 │ CS007514000094 [90m missing [0m 15735
32 │ CS009414000059 [90m missing [0m 15492
33 │ CS030415000034 [90m missing [0m 15468
34 │ CS015515000034 [90m missing [0m 15300
J-040: 全ての店舗と全ての商品を組み合わせたデータを作成したい。店舗データ(df_store)と商品データ(df_product)を直積し、件数を計算せよ。
件数を計算するだけなら,それぞれの件数の積である。
nrow(df_store) * nrow(df_product)
531590
# 別解
df_store2 = copy(df_store);
insertcols!(df_store2, 1, :key => 0);
df_product2 = copy(df_product);
insertcols!(df_product2, 1, :key => 0);
outerjoin(df_store2, df_product2, on=:key) |>
nrow
531590
差分
J-041: レシート明細データ(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、前回売上があった日からの売上金額増減を計算せよ。そして結果を10件表示せよ。
df = @chain df_receipt begin
groupby(:sales_ymd)
@combine(:amount_sum = sum(:amount))
@orderby(:sales_ymd)
@transform(:lag_sales_ymd = vcat(missing, :sales_ymd[1:end-1]))
@transform(:lag_amount_sum = vcat(missing, :amount_sum[1:end-1]))
@transform(:diff_amount = :amount_sum - :lag_amount_sum)
end
head(df)
size = (1034, 5)
[1m10×5 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m amount_sum [0m[1m lag_sales_ymd [0m[1m lag_amount_sum [0m[1m diff_amount [0m
│[90m Int64 [0m[90m Int64 [0m[90m Int64? [0m[90m Int64? [0m[90m Int64? [0m
─────┼───────────────────────────────────────────────────────────────────
1 │ 20170101 33723 [90m missing [0m[90m missing [0m[90m missing [0m
2 │ 20170102 24165 20170101 33723 -9558
3 │ 20170103 27503 20170102 24165 3338
4 │ 20170104 36165 20170103 27503 8662
5 │ 20170105 37830 20170104 36165 1665
6 │ 20170106 32387 20170105 37830 -5443
7 │ 20170107 23415 20170106 32387 -8972
8 │ 20170108 24737 20170107 23415 1322
9 │ 20170109 26718 20170108 24737 1981
10 │ 20170110 20143 20170109 26718 -6575
J-042: レシート明細データ(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、各日付のデータに対し、前回、前々回、3回前に売上があった日のデータを結合せよ。そして結果を10件表示せよ。
df = @chain df_receipt begin
groupby(:sales_ymd)
@combine(:amount = sum(:amount))
@orderby(:sales_ymd)
end
df2 = DataFrame() # sales_ymd = 0, amount = 0, lag_ymd = 0, lag_amount = 0)
for i = 2:nrow(df)
i >= 4 && append!(df2, DataFrame(sales_ymd = df[i, 1], amount = df[i, 2], lag_ymd = df[i-3, 1], lag_amount = df[i-3, 2]))
i >= 3 && append!(df2, DataFrame(sales_ymd = df[i, 1], amount = df[i, 2], lag_ymd = df[i-2, 1], lag_amount = df[i-2, 2]))
append!(df2, DataFrame(sales_ymd = df[i, 1], amount = df[i, 2], lag_ymd = df[i-1, 1], lag_amount = df[i-1, 2]))
end
head(df2)
size = (3096, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m amount [0m[1m lag_ymd [0m[1m lag_amount [0m
│[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m
─────┼─────────────────────────────────────────
1 │ 20170102 24165 20170101 33723
2 │ 20170103 27503 20170101 33723
3 │ 20170103 27503 20170102 24165
4 │ 20170104 36165 20170101 33723
5 │ 20170104 36165 20170102 24165
6 │ 20170104 36165 20170103 27503
7 │ 20170105 37830 20170102 24165
8 │ 20170105 37830 20170103 27503
9 │ 20170105 37830 20170104 36165
10 │ 20170106 32387 20170103 27503
# 別解
df = @chain df_receipt begin
groupby(:sales_ymd)
@combine(:amount = sum(:amount))
@orderby(:sales_ymd)
end
df3 = DataFrame() # sales_ymd = 0, amount = 0,
# lag_ymd_1 = 0, lag_amount_1 = 0,
# lag_ymd_2 = 0, lag_amount_2 = 0,
# lag_ymd_3 = 0, lag_amount_3 = 0)
for i = 4:nrow(df)
append!(df3,
DataFrame(sales_ymd = df[i, 1], amount = df[i, 2],
lag_ymd_1 = df[i-1, 1], lag_amount_1 = df[i-1, 2],
lag_ymd_2 = df[i-2, 1], lag_amount_2 = df[i-2, 2],
lag_ymd_3 = df[i-3, 1], lag_amount_3 = df[i-3, 2]
))
end
head(df3)
size = (1031, 8)
[1m10×8 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m amount [0m[1m lag_ymd_1 [0m[1m lag_amount_1 [0m[1m lag_ymd_2 [0m[1m lag_amount_2 [0m[1m lag_ymd_3 [0m[1m lag_amount_3 [0m
│[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────
1 │ 20170104 36165 20170103 27503 20170102 24165 20170101 33723
2 │ 20170105 37830 20170104 36165 20170103 27503 20170102 24165
3 │ 20170106 32387 20170105 37830 20170104 36165 20170103 27503
4 │ 20170107 23415 20170106 32387 20170105 37830 20170104 36165
5 │ 20170108 24737 20170107 23415 20170106 32387 20170105 37830
6 │ 20170109 26718 20170108 24737 20170107 23415 20170106 32387
7 │ 20170110 20143 20170109 26718 20170108 24737 20170107 23415
8 │ 20170111 24287 20170110 20143 20170109 26718 20170108 24737
9 │ 20170112 23526 20170111 24287 20170110 20143 20170109 26718
10 │ 20170113 28004 20170112 23526 20170111 24287 20170110 20143
クロス集計
J-043: レシート明細データ(df_receipt)と顧客データ(df_customer)を結合し、性別コード(gender_cd)と年代(ageから計算)ごとに売上金額(amount)を合計した売上サマリデータを作成せよ。性別コードは0が男性、1が女性、9が不明を表すものとする。
ただし、項目構成は年代、女性の売上金額、男性の売上金額、性別不明の売上金額の4項目とすること(縦に年代、横に性別のクロス集計)。また、年代は10歳ごとの階級とすること。
df = @chain innerjoin(df_receipt[!, [:customer_id, :amount]],
df_customer[!, [:customer_id, :gender_cd, :age]],
on=:customer_id, makeunique=true) begin
@rtransform(:age = div(:age, 10) * 10)
groupby([:age, :gender_cd])
@combine(:amount_sum = sum(:amount))
end
head(df)
size = (25, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m age [0m[1m gender_cd [0m[1m amount_sum [0m
│[90m Int64 [0m[90m String [0m[90m Int64 [0m
─────┼──────────────────────────────
1 │ 10 1 149836
2 │ 10 9 4317
3 │ 10 0 1591
4 │ 20 1 1363724
5 │ 20 9 44328
6 │ 20 0 72940
7 │ 30 1 693047
8 │ 30 9 50441
9 │ 30 0 177322
10 │ 40 1 9320791
using NamedArrays
using FreqTables
table = freqtable(df.age, df.gender_cd, weights=df.amount_sum)
df043 = hcat(10:10:90, DataFrame(Matrix(table), :auto), makeunique=true)
println(rename!(df043, [:era, :male, :female, :unknown]))
[1m9×4 DataFrame[0m
[1m Row [0m│[1m era [0m[1m male [0m[1m female [0m[1m unknown [0m
│[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m
─────┼─────────────────────────────────
1 │ 10 1591 149836 4317
2 │ 20 72940 1363724 44328
3 │ 30 177322 693047 50441
4 │ 40 19355 9320791 483512
5 │ 50 54320 6685192 342923
6 │ 60 272469 987741 71418
7 │ 70 13435 29764 2427
8 │ 80 46360 262923 5111
9 │ 90 0 6260 0
# 別解
df0 = @chain innerjoin(df_receipt[!, [:customer_id, :amount]],
df_customer[!, [:customer_id, :gender_cd, :age]],
on=:customer_id, makeunique=true) begin
@rtransform(:age = div(:age, 10) * 10)
end
freqtable(df0.age, df0.gender_cd, weights=df0.amount)
9×3 Named Matrix{Int64}
Dim1 ╲ Dim2 │ 0 1 9
────────────┼──────────────────────────
10 │ 1591 149836 4317
20 │ 72940 1363724 44328
30 │ 177322 693047 50441
40 │ 19355 9320791 483512
50 │ 54320 6685192 342923
60 │ 272469 987741 71418
70 │ 13435 29764 2427
80 │ 46360 262923 5111
90 │ 0 6260 0
縦長フォーマット
J-044: 043で作成した売上サマリデータ(df_sales_summary)は性別の売上を横持ちさせたものであった。このデータから性別を縦持ちさせ、年代、性別コード、売上金額の3項目に変換せよ。ただし、性別コードは男性を"00"、女性を"01"、不明を"99"とする。
df2 = stack(df043, 2:4)
df2[df2[:, 2] .== "male", 2] .= "00"
df2[df2[:, 2] .== "female", 2] .= "01"
df2[df2[:, 2] .== "unknown", 2] .= "99";
println(df2)
[1m27×3 DataFrame[0m
[1m Row [0m│[1m era [0m[1m variable [0m[1m value [0m
│[90m Int64 [0m[90m String [0m[90m Int64 [0m
─────┼──────────────────────────
1 │ 10 00 1591
2 │ 20 00 72940
3 │ 30 00 177322
4 │ 40 00 19355
5 │ 50 00 54320
6 │ 60 00 272469
7 │ 70 00 13435
8 │ 80 00 46360
9 │ 90 00 0
10 │ 10 01 149836
11 │ 20 01 1363724
12 │ 30 01 693047
13 │ 40 01 9320791
14 │ 50 01 6685192
15 │ 60 01 987741
16 │ 70 01 29764
17 │ 80 01 262923
18 │ 90 01 6260
19 │ 10 99 4317
20 │ 20 99 44328
21 │ 30 99 50441
22 │ 40 99 483512
23 │ 50 99 342923
24 │ 60 99 71418
25 │ 70 99 2427
26 │ 80 99 5111
27 │ 90 99 0
日付データ
22. 日付型を文字列に変換
J-045: 顧客データ(df_customer)の生年月日(birth_day)は日付型でデータを保有している。これをYYYYMMDD形式の文字列に変換し、顧客ID(customer_id)とともに10件表示せよ。
using Dates
df = @chain df_customer begin
@rtransform(:birthday = Dates.format(:birth_day, "yyyymmdd"))
@select(:customer_id, :birthday)
end
head(df)
size = (21971, 2)
[1m10×2 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m birthday [0m
│[90m String15 [0m[90m String [0m
─────┼──────────────────────────
1 │ CS021313000114 19810429
2 │ CS037613000071 19520401
3 │ CS031415000172 19761004
4 │ CS028811000001 19330327
5 │ CS001215000145 19950329
6 │ CS020401000016 19740915
7 │ CS015414000103 19770809
8 │ CS029403000008 19730817
9 │ CS015804000004 19310502
10 │ CS033513000180 19620711
23. 文字列を日付型に変換
J-046: 顧客データ(df_customer)の申し込み日(application_date)はYYYYMMDD形式の文字列型でデータを保有している。これを日付型に変換し、顧客ID(customer_id)とともに10件表示せよ。
df = @chain df_customer begin
@transform(:yyyy = [parse(Int, s[1:4]) for s in :application_date])
@transform(:mm = [parse(Int, s[5:6]) for s in :application_date])
@transform(:dd = [parse(Int, s[7:8]) for s in :application_date])
@rtransform(:application_date = Date(:yyyy, :mm, :dd))
@select(:customer_id, :application_date)
end
head(df)
size = (21971, 2)
[1m10×2 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m application_date [0m
│[90m String15 [0m[90m Date [0m
─────┼──────────────────────────────────
1 │ CS021313000114 2015-09-05
2 │ CS037613000071 2015-04-14
3 │ CS031415000172 2015-05-29
4 │ CS028811000001 2016-01-15
5 │ CS001215000145 2017-06-05
6 │ CS020401000016 2015-02-25
7 │ CS015414000103 2015-07-22
8 │ CS029403000008 2015-05-15
9 │ CS015804000004 2015-06-07
10 │ CS033513000180 2015-07-28
J-047: レシート明細データ(df_receipt)の売上日(sales_ymd)はYYYYMMDD形式の数値型でデータを保有している。これを日付型に変換し、レシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。
df = @chain df_receipt begin
@rtransform(:yyyy = :sales_ymd ÷ 10000)
@rtransform(:mm = :sales_ymd % 10000 ÷ 100)
@rtransform(:dd = :sales_ymd % 100)
@rtransform(:sales_ymd = Date(:yyyy, :mm, :dd))
@select(:receipt_no, :receipt_sub_no, :sales_ymd)
end
head(df)
size = (104681, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m receipt_no [0m[1m receipt_sub_no [0m[1m sales_ymd [0m
│[90m Int64 [0m[90m Int64 [0m[90m Date [0m
─────┼────────────────────────────────────────
1 │ 112 1 2018-11-03
2 │ 1132 2 2018-11-18
3 │ 1102 1 2017-07-12
4 │ 1132 1 2019-02-05
5 │ 1102 2 2018-08-21
6 │ 1112 1 2019-06-05
7 │ 1102 2 2018-12-05
8 │ 1102 1 2019-09-22
9 │ 1112 2 2017-05-04
10 │ 1102 1 2019-10-10
J-048: レシート明細データ(df_receipt)の売上エポック秒(sales_epoch)は数値型のUNIX秒でデータを保有している。これを日付型に変換し、レシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。
df = @chain df_receipt begin
@rtransform(:sales_ymd = Date(unix2datetime(:sales_epoch)))
@select(:receipt_no, :receipt_sub_no, :sales_ymd)
end
head(df)
size = (104681, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m receipt_no [0m[1m receipt_sub_no [0m[1m sales_ymd [0m
│[90m Int64 [0m[90m Int64 [0m[90m Date [0m
─────┼────────────────────────────────────────
1 │ 112 1 2018-11-03
2 │ 1132 2 2018-11-18
3 │ 1102 1 2017-07-12
4 │ 1132 1 2019-02-05
5 │ 1102 2 2018-08-21
6 │ 1112 1 2019-06-05
7 │ 1102 2 2018-12-05
8 │ 1102 1 2019-09-22
9 │ 1112 2 2017-05-04
10 │ 1102 1 2019-10-10
24. エポック秒を日付型に変換
J-049: レシート明細データ(df_receipt)の売上エポック秒(sales_epoch)を日付型に変換し、「年」だけ取り出してレシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。
df = @chain df_receipt begin
@rtransform(:salse_year = year(unix2datetime(:sales_epoch)))
@select(:receipt_no, :receipt_sub_no, :salse_year)
end
head(df)
size = (104681, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m receipt_no [0m[1m receipt_sub_no [0m[1m salse_year [0m
│[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m
─────┼────────────────────────────────────────
1 │ 112 1 2018
2 │ 1132 2 2018
3 │ 1102 1 2017
4 │ 1132 1 2019
5 │ 1102 2 2018
6 │ 1112 1 2019
7 │ 1102 2 2018
8 │ 1102 1 2019
9 │ 1112 2 2017
10 │ 1102 1 2019
J-050: レシート明細データ(df_receipt)の売上エポック秒(sales_epoch)を日付型に変換し、「月」だけ取り出してレシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。なお、「月」は0埋め2桁で取り出すこと。
df = @chain df_receipt begin
@rtransform(:salse_month = string(month(unix2datetime(:sales_epoch)), pad=2))
@select(:receipt_no, :receipt_sub_no, :salse_month)
end
head(df)
size = (104681, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m receipt_no [0m[1m receipt_sub_no [0m[1m salse_month [0m
│[90m Int64 [0m[90m Int64 [0m[90m String [0m
─────┼─────────────────────────────────────────
1 │ 112 1 11
2 │ 1132 2 11
3 │ 1102 1 07
4 │ 1132 1 02
5 │ 1102 2 08
6 │ 1112 1 06
7 │ 1102 2 12
8 │ 1102 1 09
9 │ 1112 2 05
10 │ 1102 1 10
J-051: レシート明細データ(df_receipt)の売上エポック秒を日付型に変換し、「日」だけ取り出してレシート番号(receipt_no)、レシートサブ番号(receipt_sub_no)とともに10件表示せよ。なお、「日」は0埋め2桁で取り出すこと。
df = @chain df_receipt begin
@rtransform(:salse_day = string(day(unix2datetime(:sales_epoch)), pad=2))
@select(:receipt_no, :receipt_sub_no, :salse_day)
end
head(df)
size = (104681, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m receipt_no [0m[1m receipt_sub_no [0m[1m salse_day [0m
│[90m Int64 [0m[90m Int64 [0m[90m String [0m
─────┼───────────────────────────────────────
1 │ 112 1 03
2 │ 1132 2 18
3 │ 1102 1 12
4 │ 1132 1 05
5 │ 1102 2 21
6 │ 1112 1 05
7 │ 1102 2 05
8 │ 1102 1 22
9 │ 1112 2 04
10 │ 1102 1 10
変数の作成と数式変形
J-052: レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計の上、売上金額合計に対して2,000円以下を0、2,000円より大きい金額を1に二値化し、顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
df = @chain df_receipt begin
@rsubset(!occursin(r"^Z", :customer_id))
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
@rtransform(:sale_flag = (:sum_amount >= 2000) + 0)
@orderby(:customer_id)
end
head(df)
size = (8306, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sum_amount [0m[1m sale_flag [0m
│[90m String15 [0m[90m Int64 [0m[90m Int64 [0m
─────┼───────────────────────────────────────
1 │ CS001113000004 1298 0
2 │ CS001114000005 626 0
3 │ CS001115000010 3044 1
4 │ CS001205000004 1988 0
5 │ CS001205000006 3337 1
6 │ CS001211000025 456 0
7 │ CS001212000027 448 0
8 │ CS001212000031 296 0
9 │ CS001212000046 228 0
10 │ CS001212000070 456 0
J-053: 顧客データ(df_customer)の郵便番号(postal_cd)に対し、東京(先頭3桁が100〜209のもの)を1、それ以外のものを0に二値化せよ。さらにレシート明細データ(df_receipt)と結合し、全期間において売上実績のある顧客数を、作成した二値ごとにカウントせよ。
df = @rtransform(df_customer, :postal_flg = (100 <= parse(Int, SubString(:postal_cd, 1, 3)) <= 209) + 0)
df2 = @select(df_receipt, :customer_id)
df3 = @chain unique(innerjoin(df, df2, on=:customer_id)) begin
unique()
# @select(:customer_id, :postal_flg)
groupby(:postal_flg)
@combine(:n = length(:postal_flg))
end
head(df3)
size = (2, 2)
[1m2×2 DataFrame[0m
[1m Row [0m│[1m postal_flg [0m[1m n [0m
│[90m Int64 [0m[90m Int64 [0m
─────┼───────────────────
1 │ 0 3906
2 │ 1 4400
J-054: 顧客データ(df_customer)の住所(address)は、埼玉県、千葉県、東京都、神奈川県のいずれかとなっている。都道府県毎にコード値を作成し、顧客ID、住所とともに10件表示せよ。値は埼玉県を11、千葉県を12、東京都を13、神奈川県を14とすること。
df = @chain df_customer begin
@select(:customer_id, :address)
@transform(:prefecture_cd = [indexin(s[1], ['埼', '千', '東', '神'])[1]+10 for s in :address])
end
head(df)
size = (21971, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m address [0m[1m prefecture_cd [0m
│[90m String15 [0m[90m String [0m[90m Int64 [0m
─────┼──────────────────────────────────────────────────────────────────
1 │ CS021313000114 神奈川県伊勢原市粟窪********** 14
2 │ CS037613000071 東京都江東区南砂********** 13
3 │ CS031415000172 東京都渋谷区代々木********** 13
4 │ CS028811000001 神奈川県横浜市泉区和泉町********… 14
5 │ CS001215000145 東京都大田区仲六郷********** 13
6 │ CS020401000016 東京都板橋区若木********** 13
7 │ CS015414000103 東京都江東区北砂********** 13
8 │ CS029403000008 千葉県浦安市海楽********** 12
9 │ CS015804000004 東京都江東区北砂********** 13
10 │ CS033513000180 神奈川県横浜市旭区善部町********… 14
J-055: レシート明細(df_receipt)データの売上金額(amount)を顧客ID(customer_id)ごとに合計し、その合計金額の四分位点を求めよ。その上で、顧客ごとの売上金額合計に対して以下の基準でカテゴリ値を作成し、顧客ID、売上金額合計とともに10件表示せよ。カテゴリ値は順に1〜4とする。
- 最小値以上第1四分位未満 ・・・ 1を付与
- 第1四分位以上第2四分位未満 ・・・ 2を付与
- 第2四分位以上第3四分位未満 ・・・ 3を付与
- 第3四分位以上 ・・・ 4を付与
using StatsBase
function encode(df)
result = fill(4, length(df))
for (i, x) in enumerate(df)
if x < Q[1]
result[i] = 1
elseif x < Q[2]
result[i] = 2
elseif x < Q[3]
result[i] = 3
end
end
return result
end
df = @chain df_receipt begin
@select(:amount, :customer_id)
groupby(:customer_id)
@combine(:amount_sum = sum(:amount))
@orderby(:customer_id)
end
Q = quantile(df.amount_sum, [0.25, 0.50, 0.75]);
println(Q)
df2 = @transform(df, :pct_group = encode(:amount_sum))
head(df2);
[548.5, 1478.0, 3651.0]
size = (8307, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m amount_sum [0m[1m pct_group [0m
│[90m String15 [0m[90m Int64 [0m[90m Int64 [0m
─────┼───────────────────────────────────────
1 │ CS001113000004 1298 2
2 │ CS001114000005 626 2
3 │ CS001115000010 3044 3
4 │ CS001205000004 1988 3
5 │ CS001205000006 3337 3
6 │ CS001211000025 456 1
7 │ CS001212000027 448 1
8 │ CS001212000031 296 1
9 │ CS001212000046 228 1
10 │ CS001212000070 456 1
J-056: 顧客データ(df_customer)の年齢(age)をもとに10歳刻みで年代を算出し、顧客ID(customer_id)、生年月日(birth_day)とともに10件表示せよ。ただし、60歳以上は全て60歳代とすること。年代を表すカテゴリ名は任意とする。
df = @chain df_customer begin
@select(:customer_id, :birth_day, :age)
@rtransform(:era = min((:age ÷ 10) * 10, 60))
end
head(df)
size = (21971, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m birth_day [0m[1m age [0m[1m era [0m
│[90m String15 [0m[90m Date [0m[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────────────────────────
1 │ CS021313000114 1981-04-29 37 30
2 │ CS037613000071 1952-04-01 66 60
3 │ CS031415000172 1976-10-04 42 40
4 │ CS028811000001 1933-03-27 86 60
5 │ CS001215000145 1995-03-29 24 20
6 │ CS020401000016 1974-09-15 44 40
7 │ CS015414000103 1977-08-09 41 40
8 │ CS029403000008 1973-08-17 45 40
9 │ CS015804000004 1931-05-02 87 60
10 │ CS033513000180 1962-07-11 56 50
J-057: 056の抽出結果と性別コード(gender_cd)により、新たに性別×年代の組み合わせを表すカテゴリデータを作成し、10件表示せよ。組み合わせを表すカテゴリの値は任意とする。
df = @chain df_customer begin
@select(:customer_id, :gender_cd, :birth_day, :age)
@rtransform(:era = min((:age ÷ 10) * 10, 60))
@rtransform(:gender_era = string(:gender_cd) * string(:era))
end
head(df)
size = (21971, 6)
[1m10×6 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m gender_cd [0m[1m birth_day [0m[1m age [0m[1m era [0m[1m gender_era [0m
│[90m String15 [0m[90m String [0m[90m Date [0m[90m Int64 [0m[90m Int64 [0m[90m String [0m
─────┼─────────────────────────────────────────────────────────────────
1 │ CS021313000114 1 1981-04-29 37 30 130
2 │ CS037613000071 9 1952-04-01 66 60 960
3 │ CS031415000172 1 1976-10-04 42 40 140
4 │ CS028811000001 1 1933-03-27 86 60 160
5 │ CS001215000145 1 1995-03-29 24 20 120
6 │ CS020401000016 0 1974-09-15 44 40 040
7 │ CS015414000103 1 1977-08-09 41 40 140
8 │ CS029403000008 0 1973-08-17 45 40 040
9 │ CS015804000004 0 1931-05-02 87 60 060
10 │ CS033513000180 1 1962-07-11 56 50 150
25. ダミー変数の作成
J-058: 顧客データ(df_customer)の性別コード(gender_cd)をダミー変数化し、顧客ID(customer_id)とともに10件表示せよ。
# トリッキー(スマート)な方法
dummydatamatrix = Matrix(permutedims(["0", "1", "9"]) .== df_customer.gender_cd) .+ 0
df = hcat(df_customer[!, [:customer_id]], DataFrame(dummydatamatrix, :auto))
rename!(df, [:customer_id, :gender_cd0, :gender_cd1, :gender_cd9])
head(df)
size = (21971, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m gender_cd0 [0m[1m gender_cd1 [0m[1m gender_cd9 [0m
│[90m String15 [0m[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m
─────┼────────────────────────────────────────────────────
1 │ CS021313000114 0 1 0
2 │ CS037613000071 0 0 1
3 │ CS031415000172 0 1 0
4 │ CS028811000001 0 1 0
5 │ CS001215000145 0 1 0
6 │ CS020401000016 1 0 0
7 │ CS015414000103 0 1 0
8 │ CS029403000008 1 0 0
9 │ CS015804000004 1 0 0
10 │ CS033513000180 0 1 0
# 地道な方法
df = @chain df_customer begin
@select(:customer_id, :gender_cd)
@rtransform begin
:gender_cd0 = (:gender_cd == "0") + 0
:gender_cd1 = (:gender_cd == "1") + 0
:gender_cd9 = (:gender_cd == "9") + 0
end
@select($(Not(:gender_cd)))
end
head(df)
size = (21971, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m gender_cd0 [0m[1m gender_cd1 [0m[1m gender_cd9 [0m
│[90m String15 [0m[90m Int64 [0m[90m Int64 [0m[90m Int64 [0m
─────┼────────────────────────────────────────────────────
1 │ CS021313000114 0 1 0
2 │ CS037613000071 0 0 1
3 │ CS031415000172 0 1 0
4 │ CS028811000001 0 1 0
5 │ CS001215000145 0 1 0
6 │ CS020401000016 1 0 0
7 │ CS015414000103 0 1 0
8 │ CS029403000008 1 0 0
9 │ CS015804000004 1 0 0
10 │ CS033513000180 0 1 0
26. 標準化
J-059: レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を平均0、標準偏差1に標準化して顧客ID、売上金額合計とともに10件表示せよ。標準化に使用する標準偏差は、分散の平方根、もしくは不偏分散の平方根のどちらでも良いものとする。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
TIPS:
~- query()の引数engineで'python'か'numexpr'かを選択でき、デフォルトはインストールされていればnumexprが、無ければpythonが使われます。さらに、文字列メソッドはengine='python'でないとquery()内で使えません。
df = @chain df_receipt begin
@rsubset(!occursin(r"^Z", :customer_id))
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
end
df2 = @chain df begin
@rtransform(:standardized_amount = (:sum_amount - mean(df.sum_amount)) / std(df.sum_amount))
@orderby(:customer_id)
end
head(df2)
size = (8306, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sum_amount [0m[1m standardized_amount [0m
│[90m String15 [0m[90m Int64 [0m[90m Float64 [0m
─────┼─────────────────────────────────────────────────
1 │ CS001113000004 1298 -0.45935
2 │ CS001114000005 626 -0.706348
3 │ CS001115000010 3044 0.182403
4 │ CS001205000004 1988 -0.205737
5 │ CS001205000006 3337 0.290096
6 │ CS001211000025 456 -0.768832
7 │ CS001212000027 448 -0.771773
8 │ CS001212000031 296 -0.827641
9 │ CS001212000046 228 -0.852635
10 │ CS001212000070 456 -0.768832
J-060: レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を最小値0、最大値1に正規化して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
df = @chain df_receipt begin
@rsubset(!occursin(r"^Z", :customer_id))
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
end
df2 = @chain df begin
@rtransform(:standardized_amount = (:sum_amount - minimum(df.sum_amount)) / (maximum(df.sum_amount) - minimum(df.sum_amount)))
@orderby(:customer_id)
end
head(df2)
size = (8306, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sum_amount [0m[1m standardized_amount [0m
│[90m String15 [0m[90m Int64 [0m[90m Float64 [0m
─────┼─────────────────────────────────────────────────
1 │ CS001113000004 1298 0.0533542
2 │ CS001114000005 626 0.0241571
3 │ CS001115000010 3044 0.129214
4 │ CS001205000004 1988 0.0833333
5 │ CS001205000006 3337 0.141945
6 │ CS001211000025 456 0.0167709
7 │ CS001212000027 448 0.0164234
8 │ CS001212000031 296 0.00981926
9 │ CS001212000046 228 0.00686479
10 │ CS001212000070 456 0.0167709
27. 対数変換
J-061: レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を常用対数化(底10)して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
df = @chain df_receipt begin
@rsubset(!occursin(r"^Z", :customer_id))
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
@rtransform(:log_amount = log10(:sum_amount))
@orderby(:customer_id)
end
head(df)
size = (8306, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sum_amount [0m[1m log_amount [0m
│[90m String15 [0m[90m Int64 [0m[90m Float64 [0m
─────┼────────────────────────────────────────
1 │ CS001113000004 1298 3.11327
2 │ CS001114000005 626 2.79657
3 │ CS001115000010 3044 3.48344
4 │ CS001205000004 1988 3.29842
5 │ CS001205000006 3337 3.52336
6 │ CS001211000025 456 2.65896
7 │ CS001212000027 448 2.65128
8 │ CS001212000031 296 2.47129
9 │ CS001212000046 228 2.35793
10 │ CS001212000070 456 2.65896
J-062: レシート明細データ(df_receipt)の売上金額(amount)を顧客ID(customer_id)ごとに合計し、売上金額合計を自然対数化(底e)して顧客ID、売上金額合計とともに10件表示せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。
df = @chain df_receipt begin
@rsubset(!occursin(r"^Z", :customer_id))
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
@rtransform(:log_amount = log(:sum_amount))
@orderby(:customer_id)
end
head(df)
size = (8306, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sum_amount [0m[1m log_amount [0m
│[90m String15 [0m[90m Int64 [0m[90m Float64 [0m
─────┼────────────────────────────────────────
1 │ CS001113000004 1298 7.16858
2 │ CS001114000005 626 6.43935
3 │ CS001115000010 3044 8.02093
4 │ CS001205000004 1988 7.59488
5 │ CS001205000006 3337 8.11283
6 │ CS001211000025 456 6.12249
7 │ CS001212000027 448 6.10479
8 │ CS001212000031 296 5.69036
9 │ CS001212000046 228 5.42935
10 │ CS001212000070 456 6.12249
欠損値処理
J-063: 商品データ(df_product)の単価(unit_price)と原価(unit_cost)から各商品の利益額を算出し、結果を10件表示せよ。
df = @transform(df_product, :unit_profit = :unit_price - :unit_cost)
head(df)
size = (10030, 7)
[1m10×7 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m category_major_cd [0m[1m category_medium_cd [0m[1m category_small_cd [0m[1m unit_price [0m[1m unit_cost [0m[1m unit_profit [0m
│[90m String15 [0m[90m String [0m[90m String [0m[90m String [0m[90m Int64? [0m[90m Int64? [0m[90m Int64? [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ P040101001 04 0401 040101 198 149 49
2 │ P040101002 04 0401 040101 218 164 54
3 │ P040101003 04 0401 040101 230 173 57
4 │ P040101004 04 0401 040101 248 186 62
5 │ P040101005 04 0401 040101 268 201 67
6 │ P040101006 04 0401 040101 298 224 74
7 │ P040101007 04 0401 040101 338 254 84
8 │ P040101008 04 0401 040101 420 315 105
9 │ P040101009 04 0401 040101 498 374 124
10 │ P040101010 04 0401 040101 580 435 145
J-064: 商品データ(df_product)の単価(unit_price)と原価(unit_cost)から、各商品の利益率の全体平均を算出せよ。ただし、単価と原価には欠損が生じていることに注意せよ。
mean(skipmissing(1 .- df_product.unit_cost ./ df_product.unit_price))
0.24911389885176904
df = @rtransform(df_product, :unit_profit_rate = 1 - :unit_cost / :unit_price)
mean(skipmissing(df.unit_profit_rate))
0.24911389885176904
J-065: 商品データ(df_product)の各商品について、利益率が30%となる新たな単価を求めよ。ただし、1円未満は切り捨てること。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。
df = @chain df_product begin
@rtransform @passmissing :new_price = trunc(Int, :unit_cost / 0.7)
@rtransform @passmissing :new_profit_rate = 1 - :unit_cost / :new_price
@select(:product_cd, :unit_price, :unit_cost, :new_price, :new_profit_rate)
end
head(df)
size = (10030, 5)
[1m10×5 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m unit_price [0m[1m unit_cost [0m[1m new_price [0m[1m new_profit_rate [0m
│[90m String15 [0m[90m Int64? [0m[90m Int64? [0m[90m Int64? [0m[90m Float64? [0m
─────┼───────────────────────────────────────────────────────────────
1 │ P040101001 198 149 212 0.29717
2 │ P040101002 218 164 234 0.299145
3 │ P040101003 230 173 247 0.299595
4 │ P040101004 248 186 265 0.298113
5 │ P040101005 268 201 287 0.299652
6 │ P040101006 298 224 320 0.3
7 │ P040101007 338 254 362 0.298343
8 │ P040101008 420 315 450 0.3
9 │ P040101009 498 374 534 0.299625
10 │ P040101010 580 435 621 0.299517
J-066: 商品データ(df_product)の各商品について、利益率が30%となる新たな単価を求めよ。今回は、1円未満を丸めること(四捨五入または偶数への丸めで良い)。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。
df = @chain df_product begin
@rtransform @passmissing :new_price = round(Int, :unit_cost / 0.7)
@rtransform @passmissing :new_profit_rate = 1 - :unit_cost / :new_price
@select(:product_cd, :unit_price, :unit_cost, :new_price, :new_profit_rate)
end
head(df)
size = (10030, 5)
[1m10×5 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m unit_price [0m[1m unit_cost [0m[1m new_price [0m[1m new_profit_rate [0m
│[90m String15 [0m[90m Int64? [0m[90m Int64? [0m[90m Int64? [0m[90m Float64? [0m
─────┼───────────────────────────────────────────────────────────────
1 │ P040101001 198 149 213 0.300469
2 │ P040101002 218 164 234 0.299145
3 │ P040101003 230 173 247 0.299595
4 │ P040101004 248 186 266 0.300752
5 │ P040101005 268 201 287 0.299652
6 │ P040101006 298 224 320 0.3
7 │ P040101007 338 254 363 0.300275
8 │ P040101008 420 315 450 0.3
9 │ P040101009 498 374 534 0.299625
10 │ P040101010 580 435 621 0.299517
J-067: 商品データ(df_product)の各商品について、利益率が30%となる新たな単価を求めよ。今回は、1円未満を切り上げること。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。
df = @chain df_product begin
@rtransform @passmissing :new_price = ceil(Int, :unit_cost / 0.7)
@rtransform @passmissing :new_profit_rate = 1 - :unit_cost / :new_price
@select(:product_cd, :unit_price, :unit_cost, :new_price, :new_profit_rate)
end
head(df)
size = (10030, 5)
[1m10×5 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m unit_price [0m[1m unit_cost [0m[1m new_price [0m[1m new_profit_rate [0m
│[90m String15 [0m[90m Int64? [0m[90m Int64? [0m[90m Int64? [0m[90m Float64? [0m
─────┼───────────────────────────────────────────────────────────────
1 │ P040101001 198 149 213 0.300469
2 │ P040101002 218 164 235 0.302128
3 │ P040101003 230 173 248 0.302419
4 │ P040101004 248 186 266 0.300752
5 │ P040101005 268 201 288 0.302083
6 │ P040101006 298 224 320 0.3
7 │ P040101007 338 254 363 0.300275
8 │ P040101008 420 315 451 0.301552
9 │ P040101009 498 374 535 0.300935
10 │ P040101010 580 435 622 0.300643
J-068: 商品データ(df_product)の各商品について、消費税率10%の税込み金額を求めよ。1円未満の端数は切り捨てとし、結果を10件表示せよ。ただし、単価(unit_price)には欠損が生じていることに注意せよ。
df = @chain df_product begin
@rtransform @passmissing :tax_price = trunc(Int, :unit_price * 1.1)
@select(:product_cd, :unit_price, :tax_price)
end
head(df)
size = (10030, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m unit_price [0m[1m tax_price [0m
│[90m String15 [0m[90m Int64? [0m[90m Int64? [0m
─────┼───────────────────────────────────
1 │ P040101001 198 217
2 │ P040101002 218 239
3 │ P040101003 230 253
4 │ P040101004 248 272
5 │ P040101005 268 294
6 │ P040101006 298 327
7 │ P040101007 338 371
8 │ P040101008 420 462
9 │ P040101009 498 547
10 │ P040101010 580 638
J-069: レシート明細データ(df_receipt)と商品データ(df_product)を結合し、顧客毎に全商品の売上金額合計と、カテゴリ大区分コード(category_major_cd)が"07"(瓶詰缶詰)の売上金額合計を計算の上、両者の比率を求めよ。抽出対象はカテゴリ大区分コード"07"(瓶詰缶詰)の売上実績がある顧客のみとし、結果を10件表示せよ。
df = innerjoin(df_receipt[!, [:customer_id, :product_cd, :amount]],
df_product[!, [:category_major_cd, :product_cd]],
on=:product_cd);
df1 = @chain df begin
groupby(:customer_id)
@combine(:sum_all = sum(:amount))
end
df2 = @chain df begin
@rsubset(:category_major_cd == "07")
groupby(:customer_id)
@combine(:sum_07 = sum(:amount))
end
df3 = @chain innerjoin(df1, df2, on=:customer_id) begin
@rtransform(:sales_rate = :sum_07 / :sum_all)
@orderby(:customer_id)
end
head(df3)
size = (6865, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sum_all [0m[1m sum_07 [0m[1m sales_rate [0m
│[90m String15 [0m[90m Int64 [0m[90m Int64 [0m[90m Float64 [0m
─────┼─────────────────────────────────────────────
1 │ CS001113000004 1298 1298 1.0
2 │ CS001114000005 626 486 0.776358
3 │ CS001115000010 3044 2694 0.88502
4 │ CS001205000004 1988 346 0.174044
5 │ CS001205000006 3337 2004 0.600539
6 │ CS001212000027 448 200 0.446429
7 │ CS001212000031 296 296 1.0
8 │ CS001212000046 228 108 0.473684
9 │ CS001212000070 456 308 0.675439
10 │ CS001213000018 243 145 0.596708
経過日数,月数,年数
J-070: レシート明細データ(df_receipt)の売上日(sales_ymd)に対し、顧客データ(df_customer)の会員申込日(application_date)からの経過日数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに10件表示せよ(sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。
using Dates
date(d) = @. Date(d ÷ 10000, (d % 10000) ÷ 100, d % 100)
df = @rtransform(innerjoin(df_receipt[!, [:customer_id, :sales_ymd]],
df_customer[!, [:customer_id, :application_date]],
on=:customer_id),
:elapsed_days = Dates.value(date(:sales_ymd) - date(parse(Int, :application_date))))
head(df, 10)
size = (65682, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sales_ymd [0m[1m application_date [0m[1m elapsed_days [0m
│[90m String15 [0m[90m Int64 [0m[90m String [0m[90m Int64 [0m
─────┼───────────────────────────────────────────────────────────
1 │ CS006214000001 20181103 20150201 1371
2 │ CS008415000097 20181118 20150322 1337
3 │ CS028414000014 20170712 20150711 732
4 │ CS025415000050 20180821 20160131 933
5 │ CS003515000195 20190605 20150306 1552
6 │ CS024514000042 20181205 20151010 1152
7 │ CS040415000178 20190922 20150627 1548
8 │ CS027514000015 20191010 20151101 1439
9 │ CS025415000134 20190918 20150720 1521
10 │ CS021515000126 20171010 20150508 886
J-071: レシート明細データ(df_receipt)の売上日(sales_ymd)に対し、顧客データ(df_customer)の会員申込日(application_date)からの経過月数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに10件表示せよ(sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。1ヶ月未満は切り捨てること。
using Dates
date2(d) = @. (d ÷ 10000, (d % 10000) ÷ 100, d % 100)
function date3(d_begin, d_end)
y, m, d = date2(d_end) .- date2(parse(Int, d_begin))
12y + m + (d < 0)*(-1)
end;
df = @rtransform(innerjoin(df_receipt[!, [:customer_id, :sales_ymd]],
df_customer[!, [:customer_id, :application_date]],
on=:customer_id),
:elapsed_months = date3(:application_date, :sales_ymd))
head(df)
size = (65682, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sales_ymd [0m[1m application_date [0m[1m elapsed_months [0m
│[90m String15 [0m[90m Int64 [0m[90m String [0m[90m Int64 [0m
─────┼─────────────────────────────────────────────────────────────
1 │ CS006214000001 20181103 20150201 45
2 │ CS008415000097 20181118 20150322 43
3 │ CS028414000014 20170712 20150711 24
4 │ CS025415000050 20180821 20160131 30
5 │ CS003515000195 20190605 20150306 50
6 │ CS024514000042 20181205 20151010 37
7 │ CS040415000178 20190922 20150627 50
8 │ CS027514000015 20191010 20151101 47
9 │ CS025415000134 20190918 20150720 49
10 │ CS021515000126 20171010 20150508 29
J-072: レシート明細データ(df_receipt)の売上日(df_customer)に対し、顧客データ(df_customer)の会員申込日(application_date)からの経過年数を計算し、顧客ID(customer_id)、売上日、会員申込日とともに10件表示せよ(sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。1年未満は切り捨てること。
year2(ymd, ymd2) = (ymd2 .- ymd) .÷ 10000
df = @rtransform(innerjoin(df_receipt[!, [:customer_id, :sales_ymd]],
df_customer[!, [:customer_id, :application_date]],
on=:customer_id),
:elapsed_years = year2(parse(Int, :application_date), :sales_ymd))
head(df)
size = (65682, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sales_ymd [0m[1m application_date [0m[1m elapsed_years [0m
│[90m String15 [0m[90m Int64 [0m[90m String [0m[90m Int64 [0m
─────┼────────────────────────────────────────────────────────────
1 │ CS006214000001 20181103 20150201 3
2 │ CS008415000097 20181118 20150322 3
3 │ CS028414000014 20170712 20150711 2
4 │ CS025415000050 20180821 20160131 2
5 │ CS003515000195 20190605 20150306 4
6 │ CS024514000042 20181205 20151010 3
7 │ CS040415000178 20190922 20150627 4
8 │ CS027514000015 20191010 20151101 3
9 │ CS025415000134 20190918 20150720 4
10 │ CS021515000126 20171010 20150508 2
J-073: レシート明細データ(df_receipt)の売上日(sales_ymd)に対し、顧客データ(df_customer)の会員申込日(application_date)からのエポック秒による経過時間を計算し、顧客ID(customer_id)、売上日、会員申込日とともに10件表示せよ(なお、sales_ymdは数値、application_dateは文字列でデータを保持している点に注意)。なお、時間情報は保有していないため各日付は0時0分0秒を表すものとする。
datetime(d) = DateTime(d ÷ 10000, (d % 10000) ÷ 100, d % 100, 0, 0, 0)
df = @chain innerjoin(df_receipt[!, [:customer_id, :sales_ymd]],
df_customer[!, [:customer_id, :application_date]],
on=:customer_id) begin
@rtransform(:elapsed_epoch = convert(Int64, Dates.value(datetime(:sales_ymd) - datetime(parse(Int, :application_date)))/1000))
end
head(df)
size = (65682, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sales_ymd [0m[1m application_date [0m[1m elapsed_epoch [0m
│[90m String15 [0m[90m Int64 [0m[90m String [0m[90m Int64 [0m
─────┼────────────────────────────────────────────────────────────
1 │ CS006214000001 20181103 20150201 118454400
2 │ CS008415000097 20181118 20150322 115516800
3 │ CS028414000014 20170712 20150711 63244800
4 │ CS025415000050 20180821 20160131 80611200
5 │ CS003515000195 20190605 20150306 134092800
6 │ CS024514000042 20181205 20151010 99532800
7 │ CS040415000178 20190922 20150627 133747200
8 │ CS027514000015 20191010 20151101 124329600
9 │ CS025415000134 20190918 20150720 131414400
10 │ CS021515000126 20171010 20150508 76550400
J-074: レシート明細データ(df_receipt)の売上日(sales_ymd)に対し、当該週の月曜日からの経過日数を計算し、売上日、直前の月曜日付とともに10件表示せよ(sales_ymdは数値でデータを保持している点に注意)。
date(d) = Date(d ÷ 10000, (d % 10000) ÷ 100, d % 100)
df = @chain df_receipt begin
@rtransform(:monday = firstdayofweek(date(:sales_ymd)))
@rtransform(:elapsed_days = Dates.value(date(:sales_ymd) - :monday))
@select(:sales_ymd, :elapsed_days, :monday)
end
head(df)
size = (104681, 3)
[1m10×3 DataFrame[0m
[1m Row [0m│[1m sales_ymd [0m[1m elapsed_days [0m[1m monday [0m
│[90m Int64 [0m[90m Int64 [0m[90m Date [0m
─────┼─────────────────────────────────────
1 │ 20181103 5 2018-10-29
2 │ 20181118 6 2018-11-12
3 │ 20170712 2 2017-07-10
4 │ 20190205 1 2019-02-04
5 │ 20180821 1 2018-08-20
6 │ 20190605 2 2019-06-03
7 │ 20181205 2 2018-12-03
8 │ 20190922 6 2019-09-16
9 │ 20170504 3 2017-05-01
10 │ 20191010 3 2019-10-07
無作為抽出
J-075: 顧客データ(df_customer)からランダムに1%のデータを抽出し、先頭から10件表示せよ。
using StatsBase
n = nrow(df_customer)
df = df_customer[sample(1:n, floor(Int, n*0.01), replace=false), :]
head(df)
size = (219, 11)
[1m10×11 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m
─────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS025414000027 川本 美紀 1 女性 1970-12-12 48 242-0024 神奈川県大和市福田********** S14025 20151010 F-20100721-D
2 │ CS037602000013 伊集院 竜也 0 男性 1952-03-25 67 135-0021 東京都江東区白河********** S13037 20151128 0-00000000-0
3 │ CS002314000261 伴 茜 9 不明 1980-07-08 38 185-0011 東京都国分寺市本多********** S13002 20180112 0-00000000-0
4 │ CS031515000016 板垣 結衣 1 女性 1962-03-25 57 151-0072 東京都渋谷区幡ヶ谷********** S13031 20150518 C-20100707-D
5 │ CS008414000039 土屋 りえ 1 女性 1971-07-11 47 157-0067 東京都世田谷区喜多見********** S13008 20151127 F-20090822-D
6 │ CS020713000052 矢口 陽子 1 女性 1944-12-21 74 173-0005 東京都板橋区仲宿********** S13020 20150204 0-00000000-0
7 │ CS004315000319 金田 陽子 1 女性 1984-02-23 35 176-0025 東京都練馬区中村南********** S13004 20160410 2-20090925-1
8 │ CS007412000215 三好 愛 1 女性 1969-02-08 50 276-0022 千葉県八千代市上高野********** S12007 20150510 0-00000000-0
9 │ CS001613000230 長澤 千夏 1 女性 1949-07-20 69 144-0046 東京都大田区東六郷********** S13001 20160505 0-00000000-0
10 │ CS020315000061 藤島 華子 1 女性 1986-09-19 32 115-0055 東京都北区赤羽西********** S13020 20150724 6-20090925-7
以下の方法は,各行に [0,1) の一様乱数を与え,その値が希望する抽出率の数値未満の行を抽出するというものである。実際に抽出される件数が若干の幅を持つが,実用上の問題はないであろう。
# 別解
using StatsBase
df = @chain df_customer begin
@rtransform(:uniformrandom = rand(1)[1])
@rsubset(:uniformrandom < 0.01)
@select($(Not(:uniformrandom))) # 乱数列は用済みなので削除
end
println("df_customer の件数 = $(nrow(df_customer)), 抽出された件数 = $(nrow(df)), 抽出率 = $(100nrow(df)/nrow(df_customer)) %")
head(df)
df_customer の件数 = 21971, 抽出された件数 = 218, 抽出率 = 0.9922170133357607 %
size = (218, 11)
[1m10×11 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS001215000145 田崎 美紀 1 女性 1995-03-29 24 144-0055 東京都大田区仲六郷********** S13001 20170605 6-20090929-2
2 │ CS035513000025 松永 桃子 1 女性 1964-08-10 54 154-0015 東京都世田谷区桜新町********** S13035 20150401 9-20091109-A
3 │ CS004514000338 島崎 貴美子 1 女性 1964-12-07 54 165-0033 東京都中野区若宮********** S13004 20170301 0-00000000-0
4 │ CS011515000108 久野 幸子 1 女性 1965-04-11 53 223-0064 神奈川県横浜市港北区下田町******… S14011 20150315 C-20100828-C
5 │ CS004413000614 藤村 朝陽 1 女性 1977-06-25 41 165-0033 東京都中野区若宮********** S13004 20170603 0-00000000-0
6 │ CS011612000101 渡部 あや子 1 女性 1949-04-11 69 211-0025 神奈川県川崎市中原区木月********… S14011 20150711 0-00000000-0
7 │ CS008313000158 入江 真悠子 1 女性 1986-02-08 33 182-0004 東京都調布市入間町********** S13008 20150511 0-00000000-0
8 │ CS024615000029 水谷 由美子 1 女性 1957-12-24 61 214-0034 神奈川県川崎市多摩区三田********… S14024 20150414 9-20091207-6
9 │ CS004504000015 小幡 良介 0 男性 1961-07-01 57 176-0024 東京都練馬区中村********** S13004 20160906 0-00000000-0
10 │ CS013213000006 野田 文世 1 女性 1991-12-01 27 261-0026 千葉県千葉市美浜区幕張西********… S12013 20160102 0-00000000-0
層化抽出
J-076: 顧客データ(df_customer)から性別コード(gender_cd)の割合に基づきランダムに10%のデータを層化抽出し、性別コードごとに件数を集計せよ。
df = @chain df_customer begin
groupby(:gender_cd)
@combine(:customer_num = length(:gender_cd))
end
head(df)
size = (3, 2)
[1m3×2 DataFrame[0m
[1m Row [0m│[1m gender_cd [0m[1m customer_num [0m
│[90m String [0m[90m Int64 [0m
─────┼─────────────────────────
1 │ 1 17918
2 │ 9 1072
3 │ 0 2981
function sampling(df)
n = nrow(df)
return df[sample(1:n, floor(Int, n*0.1), replace=false), :]
end
gd = groupby(df_customer, :gender_cd)
df = sampling(gd[1])
for i in 2:3
df = vcat(df, sampling(gd[i]))
end
gd = groupby(df, :gender_cd)
combine(gd, nrow)
Row | gender_cd | nrow |
---|---|---|
String | Int64 | |
1 | 1 | 1791 |
2 | 9 | 107 |
3 | 0 | 298 |
データフレームをグループ化し,それぞれのデータフレームに対して一定の処理を行い,再度一つのデータフレームにまとめるという作業は以下のようにすれば簡単になる。
# 別解
gd = groupby(df_customer, :gender_cd) # グループ化
df = [sampling(df) for df in gd] # 処理(関数内で行う)
df2 = vcat(df...) # 再度一つのデータフレームにまとめる
gd2 = groupby(df2, :gender_cd)
combine(gd2, nrow)
Row | gender_cd | nrow |
---|---|---|
String | Int64 | |
1 | 1 | 1791 |
2 | 9 | 107 |
3 | 0 | 298 |
外れ値
J-077: レシート明細データ(df_receipt)の売上金額を顧客単位に合計し、合計した売上金額の外れ値を抽出せよ。なお、外れ値は売上金額合計を対数化したうえで平均と標準偏差を計算し、その平均から3σを超えて離れたものとする(自然対数と常用対数のどちらでも可)。結果は10件表示せよ。
df = @chain df_receipt begin
groupby(:customer_id)
@combine(:sum_amount = sum(:amount), :log_sum_amount = log(sum(:amount)))
end;
using StatsBase
df2 = @rsubset(df, abs(:log_sum_amount - mean(df.log_sum_amount)) / std(df.log_sum_amount) > 3)
head(df2)
size = (1, 3)
[1m1×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sum_amount [0m[1m log_sum_amount [0m
│[90m String15 [0m[90m Int64 [0m[90m Float64 [0m
─────┼────────────────────────────────────────────
1 │ ZZ000000000000 12395003 16.3328
J-078: レシート明細データ(df_receipt)の売上金額(amount)を顧客単位に合計し、合計した売上金額の外れ値を抽出せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。なお、ここでは外れ値を第1四分位と第3四分位の差であるIQRを用いて、「第1四分位数-1.5×IQR」を下回るもの、または「第3四分位数+1.5×IQR」を超えるものとする。結果は10件表示せよ。
df = @chain df_receipt begin
@rsubset(!occursin(r"^Z", :customer_id))
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
end;
(Q1, Q3) = quantile(df.sum_amount, [0.25, 0.75])
(qt1, qt3) = (Q1 - 1.5(Q3 - Q1), Q3 + 1.5(Q3 - Q1))
println("qt1 = $qt1, qt3 = $qt3")
qt1 = -4104.0, qt3 = 8302.0
df2 = @chain df begin
@rsubset(:sum_amount < qt1 || :sum_amount > qt3)
@orderby(:customer_id)
end
df2 = sort(df2, :customer_id)
head(df2)
size = (393, 2)
[1m10×2 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m sum_amount [0m
│[90m String15 [0m[90m Int64 [0m
─────┼────────────────────────────
1 │ CS001414000048 8584
2 │ CS001605000009 18925
3 │ CS002415000594 9568
4 │ CS004414000181 9584
5 │ CS005415000137 8734
6 │ CS006414000001 9156
7 │ CS006414000029 9179
8 │ CS006415000105 10042
9 │ CS006415000147 12723
10 │ CS006415000157 10648
欠損値の補完
J-079: 商品データ(df_product)の各項目に対し、欠損数を確認せよ。
a = map(eachcol(df_product)) do col
length(col) - length(collect(skipmissing(col)))
end;
DataFrame(variable = names(df_product), missings = a)
Row | variable | missings |
---|---|---|
String | Int64 | |
1 | product_cd | 0 |
2 | category_major_cd | 0 |
3 | category_medium_cd | 0 |
4 | category_small_cd | 0 |
5 | unit_price | 7 |
6 | unit_cost | 7 |
J-080: 商品データ(df_product)のいずれかの項目に欠損が発生しているレコードを全て削除した新たな商品データを作成せよ。なお、削除前後の件数を表示させ、079で確認した件数だけ減少していることも確認すること。
df = df_product |> dropmissing
println("欠損値削除前の件数 = $(nrow(df_product)), 欠損値削除後の件数 = $(nrow(df))")
欠損値削除前の件数 = 10030, 欠損値削除後の件数 = 10023
J-081: 単価(unit_price)と原価(unit_cost)の欠損値について、それぞれの平均値で補完した新たな商品データを作成せよ。なお、平均値については1円未満を丸めること(四捨五入または偶数への丸めで良い)。補完実施後、各項目について欠損が生じていないことも確認すること。
price_mean = round(Int, mean(skipmissing(df_product.unit_price)))
cost_mean = round(Int, mean(skipmissing(df_product.unit_cost)))
println("price_mean = $price_mean, cost_mean = $cost_mean")
println(df[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
println("nrow = $(nrow(df))")
df2 = @chain df_product begin
@rtransform(:unit_price = coalesce(:unit_price, price_mean))
@rtransform(:unit_cost = coalesce(:unit_cost, cost_mean))
end
println(df2[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
println("nrow = $(nrow(df2))")
price_mean = 403, cost_mean = 302
[1m8×6 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m category_major_cd [0m[1m category_medium_cd [0m[1m category_small_cd [0m[1m unit_price [0m[1m unit_cost [0m
│[90m String15 [0m[90m String [0m[90m String [0m[90m String [0m[90m Int64 [0m[90m Int64 [0m
─────┼─────────────────────────────────────────────────────────────────────────────────────────────
1 │ P040802006 04 0408 040802 438 329
2 │ P041302001 04 0413 041302 450 338
3 │ P050104002 05 0501 050104 115 86
4 │ P050406003 05 0504 050406 128 96
5 │ P060804002 06 0608 060804 450 347
6 │ P070203005 07 0702 070203 100 75
7 │ P080603001 08 0806 080603 80 63
8 │ P090205007 09 0902 090205 285 214
nrow = 10023
[1m8×6 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m category_major_cd [0m[1m category_medium_cd [0m[1m category_small_cd [0m[1m unit_price [0m[1m unit_cost [0m
│[90m String15 [0m[90m String [0m[90m String [0m[90m String [0m[90m Int64 [0m[90m Int64 [0m
─────┼─────────────────────────────────────────────────────────────────────────────────────────────
1 │ P040802006 04 0408 040802 438 329
2 │ P040802007 04 0408 040802 403 302
3 │ P050103021 05 0501 050103 403 302
4 │ P050405009 05 0504 050405 403 302
5 │ P060802026 06 0608 060802 403 302
6 │ P070202092 07 0702 070202 403 302
7 │ P080504027 08 0805 080504 403 302
8 │ P090204185 09 0902 090204 403 302
nrow = 10030
J-082: 単価(unit_price)と原価(unit_cost)の欠損値について、それぞれの中央値で補完した新たな商品データを作成せよ。なお、中央値については1円未満を丸めること(四捨五入または偶数への丸めで良い)。補完実施後、各項目について欠損が生じていないことも確認すること。
price_median = round(Int, median(skipmissing(df_product.unit_price)))
cost_median = round(Int, median(skipmissing(df_product.unit_cost)))
println("price_median = $price_median, cost_median = $cost_median")
println(df[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
println("nrow = $(nrow(df))")
df2 = @chain df_product begin
@rtransform(:unit_price = coalesce(:unit_price, price_median))
@rtransform(:unit_cost = coalesce(:unit_cost, cost_median))
end
println(df2[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
println("nrow = $(nrow(df2))")
price_median = 252, cost_median = 189
[1m8×6 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m category_major_cd [0m[1m category_medium_cd [0m[1m category_small_cd [0m[1m unit_price [0m[1m unit_cost [0m
│[90m String15 [0m[90m String [0m[90m String [0m[90m String [0m[90m Int64 [0m[90m Int64 [0m
─────┼─────────────────────────────────────────────────────────────────────────────────────────────
1 │ P040802006 04 0408 040802 438 329
2 │ P041302001 04 0413 041302 450 338
3 │ P050104002 05 0501 050104 115 86
4 │ P050406003 05 0504 050406 128 96
5 │ P060804002 06 0608 060804 450 347
6 │ P070203005 07 0702 070203 100 75
7 │ P080603001 08 0806 080603 80 63
8 │ P090205007 09 0902 090205 285 214
nrow = 10023
[1m8×6 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m category_major_cd [0m[1m category_medium_cd [0m[1m category_small_cd [0m[1m unit_price [0m[1m unit_cost [0m
│[90m String15 [0m[90m String [0m[90m String [0m[90m String [0m[90m Int64 [0m[90m Int64 [0m
─────┼─────────────────────────────────────────────────────────────────────────────────────────────
1 │ P040802006 04 0408 040802 438 329
2 │ P040802007 04 0408 040802 252 189
3 │ P050103021 05 0501 050103 252 189
4 │ P050405009 05 0504 050405 252 189
5 │ P060802026 06 0608 060802 252 189
6 │ P070202092 07 0702 070202 252 189
7 │ P080504027 08 0805 080504 252 189
8 │ P090204185 09 0902 090204 252 189
nrow = 10030
J-083: 単価(unit_price)と原価(unit_cost)の欠損値について、各商品のカテゴリ小区分コード(category_small_cd)ごとに算出した中央値で補完した新たな商品データを作成せよ。なお、中央値については1円未満を丸めること(四捨五入または偶数への丸めで良い)。補完実施後、各項目について欠損が生じていないことも確認すること。
using StatsBase
df = @chain df_product begin
groupby(:category_small_cd)
@combine(:unit_price_median = round(Int, median(skipmissing(:unit_price))),
:unit_cost_median = round(Int, median(skipmissing(:unit_cost))))
end;
df2 = innerjoin(df_product, df, on=:category_small_cd);
println("Before")
println(df2[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
for i in 1:nrow(df2)
ismissing(df2.unit_price[i]) && (df2.unit_price[i] = df2.unit_price_median[i])
ismissing(df2.unit_cost[i]) && (df2.unit_cost[i] = df2.unit_cost_median[i])
end
println("After")
println(df2[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
Before
[1m8×8 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m category_major_cd [0m[1m category_medium_cd [0m[1m category_small_cd [0m[1m unit_price [0m[1m unit_cost [0m[1m unit_price_median [0m[1m unit_cost_median [0m
│[90m String15 [0m[90m String [0m[90m String [0m[90m String [0m[90m Int64? [0m[90m Int64? [0m[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ P040802006 04 0408 040802 438 329 313 235
2 │ P040802007 04 0408 040802 [90m missing [0m[90m missing [0m 313 235
3 │ P050103021 05 0501 050103 [90m missing [0m[90m missing [0m 132 100
4 │ P050405009 05 0504 050405 [90m missing [0m[90m missing [0m 178 134
5 │ P060802026 06 0608 060802 [90m missing [0m[90m missing [0m 270 200
6 │ P070202092 07 0702 070202 [90m missing [0m[90m missing [0m 238 179
7 │ P080504027 08 0805 080504 [90m missing [0m[90m missing [0m 258 196
8 │ P090204185 09 0902 090204 [90m missing [0m[90m missing [0m 694 521
After
[1m8×8 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m category_major_cd [0m[1m category_medium_cd [0m[1m category_small_cd [0m[1m unit_price [0m[1m unit_cost [0m[1m unit_price_median [0m[1m unit_cost_median [0m
│[90m String15 [0m[90m String [0m[90m String [0m[90m String [0m[90m Int64? [0m[90m Int64? [0m[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ P040802006 04 0408 040802 438 329 313 235
2 │ P040802007 04 0408 040802 313 235 313 235
3 │ P050103021 05 0501 050103 132 100 132 100
4 │ P050405009 05 0504 050405 178 134 178 134
5 │ P060802026 06 0608 060802 270 200 270 200
6 │ P070202092 07 0702 070202 238 179 238 179
7 │ P080504027 08 0805 080504 258 196 258 196
8 │ P090204185 09 0902 090204 694 521 694 521
J-084: 顧客データ(df_customer)の全顧客に対して全期間の売上金額に占める2019年売上金額の割合を計算し、新たなデータを作成せよ。ただし、売上実績がない場合は0として扱うこと。そして計算した割合が0超のものを抽出し、結果を10件表示せよ。また、作成したデータに欠損が存在しないことを確認せよ。
df2019 = @chain df_receipt begin
@rsubset(:sales_ymd ÷ 10000 == 2019)
@select(:customer_id, :amount)
groupby(:customer_id)
@combine(:amount_2019 = sum(:amount))
end;
dfall = @chain df_receipt begin
@select(:customer_id, :amount)
groupby(:customer_id)
@combine(:amount_all = sum(:amount))
end;
df = @chain leftjoin(df2019, dfall, on=:customer_id) begin
coalesce(0)
@rtransform(:amount_rate = :amount_2019 / :amount_all)
@rsubset(:amount_rate > 0)
@orderby(:customer_id)
end;
head(df)
size = (5020, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m amount_2019 [0m[1m amount_all [0m[1m amount_rate [0m
│[90m String15 [0m[90m Int64 [0m[90m Int64? [0m[90m Float64 [0m
─────┼──────────────────────────────────────────────────────
1 │ CS001113000004 1298 1298 1.0
2 │ CS001114000005 188 626 0.300319
3 │ CS001115000010 578 3044 0.189882
4 │ CS001205000004 702 1988 0.353119
5 │ CS001205000006 486 3337 0.14564
6 │ CS001211000025 456 456 1.0
7 │ CS001212000070 456 456 1.0
8 │ CS001214000009 664 4685 0.141729
9 │ CS001214000017 2962 4132 0.716844
10 │ CS001214000048 1889 2374 0.795703
a = map(eachcol(df)) do col
length(col) - length(collect(skipmissing(col)))
end;
DataFrame(variable = names(df), missings = a)
Row | variable | missings |
---|---|---|
String | Int64 | |
1 | customer_id | 0 |
2 | amount_2019 | 0 |
3 | amount_all | 0 |
4 | amount_rate | 0 |
位置情報(経緯度と距離)
J-085: 顧客データ(df_customer)の全顧客に対し、郵便番号(postal_cd)を用いてジオコードデータ(df_geocode)を紐付け、新たな顧客データを作成せよ。ただし、1つの郵便番号(postal_cd)に複数の経度(longitude)、緯度(latitude)情報が紐づく場合は、経度(longitude)、緯度(latitude)の平均値を算出して使用すること。また、作成結果を確認するために結果を10件表示せよ。
using StatsBase
df = @chain df_geocode begin
@rselect(:postal_cd, :longitude, :latitude)
groupby(:postal_cd)
@combine(:m_longitude = mean(:longitude), :m_latitude = mean(:latitude))
end;
df_customer2 = innerjoin(df_customer, df, on=:postal_cd)
head(df_customer2)
size = (21971, 13)
[1m10×13 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m[1m m_longitude [0m[1m m_latitude [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m[90m Float64 [0m[90m Float64 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS020301000012 都築 育二 0 男性 1985-08-20 33 332-0031 埼玉県川口市青木********** S13020 20161018 0-00000000-0 139.727 35.8088
2 │ CS051412000011 奥村 愛 1 女性 1969-06-04 49 332-0023 埼玉県川口市飯塚********** S13051 20180702 0-00000000-0 139.711 35.7965
3 │ CS051412000012 おかやま 未華子 1 女性 1977-03-13 42 332-0023 埼玉県川口市飯塚********** S13051 20180511 0-00000000-0 139.711 35.7965
4 │ CS051212000001 美木 瞬 1 女性 1991-10-19 27 332-0023 埼玉県川口市飯塚********** S13051 20180509 2-20101018-4 139.711 35.7965
5 │ CS020112000003 荒川 まなみ 1 女性 2004-05-13 14 332-0015 埼玉県川口市川口********** S13020 20151116 0-00000000-0 139.716 35.8023
6 │ CS020212000016 藤沢 恵梨香 1 女性 1991-08-08 27 332-0015 埼玉県川口市川口********** S13020 20150122 4-20100207-3 139.716 35.8023
7 │ CS051512000001 田原 夏希 1 女性 1959-11-21 59 332-0015 埼玉県川口市川口********** S13051 20190325 0-00000000-0 139.716 35.8023
8 │ CS020212000004 前田 美佐 1 女性 1989-12-11 29 332-0015 埼玉県川口市川口********** S13020 20150814 C-20090906-9 139.716 35.8023
9 │ CS051502000001 若山 哲平 0 男性 1961-10-07 57 332-0015 埼玉県川口市川口********** S13051 20180209 0-00000000-0 139.716 35.8023
10 │ CS020212000008 板垣 瞳 1 女性 1997-01-05 22 332-0015 埼玉県川口市川口********** S13020 20150105 0-00000000-0 139.716 35.8023
J-086: 085で作成した緯度経度つき顧客データに対し、会員申込店舗コード(application_store_cd)をキーに店舗データ(df_store)と結合せよ。そして申込み店舗の緯度(latitude)・経度情報(longitude)と顧客住所(address)の緯度・経度を用いて申込み店舗と顧客住所の距離(単位:km)を求め、顧客ID(customer_id)、顧客住所(address)、店舗住所(address)とともに表示せよ。計算式は以下の簡易式で良いものとするが、その他精度の高い方式を利用したライブラリを利用してもかまわない。結果は10件表示せよ。
$$
\mbox{緯度(ラジアン)}:\phi \
\mbox{経度(ラジアン)}:\lambda \
\mbox{距離}L = 6371 * \arccos(\sin \phi_1 * \sin \phi_2
- \cos \phi_1 * \cos \phi_2 * \cos(\lambda_1 − \lambda_2))
$$
calc_distance(x1, y1, x2, y2) = 6371 .* acos.(
sin.(x1 * pi / 180)
* sin.(x2 .* pi / 180)
+ cos.(x1 .* pi / 180)
* cos.(x2 .* pi / 180)
* cos.((y1 .* pi / 180) - (y2 .* pi / 180 )))
calc_distance (generic function with 1 method)
result = innerjoin(df_customer2, df_store, on=:application_store_cd => :store_cd, makeunique=true);
result_df = @chain result begin
@rtransform(:distance = calc_distance(:m_latitude, :m_longitude, :latitude, :longitude))
@select(:customer_id, :customer_address = :address, :store_address = :address_1, :distance)
@orderby(:customer_id)
end
head(result_df)
size = (21971, 4)
[1m10×4 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_address [0m[1m store_address [0m[1m distance [0m
│[90m String15 [0m[90m String [0m[90m String [0m[90m Float64 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────
1 │ CS001105000001 東京都大田区西六郷********** 東京都大田区仲六郷二丁目 1.47979
2 │ CS001112000009 東京都大田区西馬込********** 東京都大田区仲六郷二丁目 4.02049
3 │ CS001112000019 東京都大田区昭和島********** 東京都大田区仲六郷二丁目 3.78301
4 │ CS001112000021 東京都大田区西六郷********** 東京都大田区仲六郷二丁目 1.47979
5 │ CS001112000023 東京都大田区昭和島********** 東京都大田区仲六郷二丁目 3.78301
6 │ CS001112000024 東京都大田区西六郷********** 東京都大田区仲六郷二丁目 1.47979
7 │ CS001112000029 東京都大田区西六郷********** 東京都大田区仲六郷二丁目 1.47979
8 │ CS001112000030 東京都大田区西六郷********** 東京都大田区仲六郷二丁目 1.47979
9 │ CS001113000004 東京都大田区西六郷********** 東京都大田区仲六郷二丁目 1.47979
10 │ CS001113000010 東京都大田区西六郷********** 東京都大田区仲六郷二丁目 1.47979
名寄データ
J-087: 顧客データ(df_customer)では、異なる店舗での申込みなどにより同一顧客が複数登録されている。名前(customer_name)と郵便番号(postal_cd)が同じ顧客は同一顧客とみなして1顧客1レコードとなるように名寄せした名寄顧客データを作成し、顧客データの件数、名寄顧客データの件数、重複数を算出せよ。ただし、同一顧客に対しては売上金額合計が最も高いものを残し、売上金額合計が同一もしくは売上実績がない顧客については顧客ID(customer_id)の番号が小さいものを残すこととする。
df = @chain df_receipt begin
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
end;
df2 = leftjoin(df_customer, df, on=:customer_id);
gd = groupby(df2, [:customer_name, :postal_cd]);
count = 0
df_customer_u = DataFrame()
for dfx in gd
if nrow(dfx) > 1
for i in 1:nrow(dfx)
if ismissing(dfx.sum_amount[i])
dfx.sum_amount[i] = 0
end
end
count += 1
dfx2 = @rorderby(dfx, -:sum_amount, :customer_id)
push!(df_customer_u, dfx2[1,:])
else
append!(df_customer_u, dfx)
end
end
println("df_customer の行数 = ", nrow(df_customer))
println("df_customer_u の行数 = ", nrow(df_customer_u))
println("差 = ", count)
head(df_customer_u)
df_customer の行数 = 21971
df_customer_u の行数 = 21941
差 = 30
size = (21941, 12)
[1m10×12 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m[1m sum_amount [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m[90m Int64? [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS031415000172 宇多田 貴美子 1 女性 1976-10-04 42 151-0053 東京都渋谷区代々木********** S13031 20150529 D-20100325-C 5088
2 │ CS001215000145 田崎 美紀 1 女性 1995-03-29 24 144-0055 東京都大田区仲六郷********** S13001 20170605 6-20090929-2 875
3 │ CS015414000103 奥野 陽子 1 女性 1977-08-09 41 136-0073 東京都江東区北砂********** S13015 20150722 B-20100609-B 3122
4 │ CS033513000180 安斎 遥 1 女性 1962-07-11 56 241-0823 神奈川県横浜市旭区善部町********… S14033 20150728 6-20080506-5 868
5 │ CS011215000048 芦田 沙耶 1 女性 1992-02-01 27 223-0062 神奈川県横浜市港北区日吉本町****… S14011 20150228 C-20100421-9 3444
6 │ CS040412000191 川井 郁恵 1 女性 1977-01-05 42 226-0021 神奈川県横浜市緑区北八朔町******… S14040 20151101 1-20091025-4 210
7 │ CS029415000023 梅田 里穂 1 女性 1976-01-17 43 279-0043 千葉県浦安市富士見********** S12029 20150610 D-20100918-E 5167
8 │ CS009315000023 皆川 文世 1 女性 1980-04-15 38 154-0012 東京都世田谷区駒沢********** S13009 20150319 5-20080322-1 780
9 │ CS035415000029 寺沢 真希 9 不明 1977-09-27 41 158-0096 東京都世田谷区玉川台********** S13035 20141220 F-20101029-F 7504
10 │ CS015315000033 福士 璃奈子 1 女性 1983-03-17 36 135-0043 東京都江東区塩浜********** S13015 20141024 4-20080219-3 576
J-088: 087で作成したデータを元に、顧客データに統合名寄IDを付与したデータを作成せよ。ただし、統合名寄IDは以下の仕様で付与するものとする。
- 重複していない顧客:顧客ID(customer_id)を設定
- 重複している顧客:前設問で抽出したレコードの顧客IDを設定
顧客IDのユニーク件数と、統合名寄IDのユニーク件数の差も確認すること。
df = innerjoin(df_customer, df_customer_u[!, [:customer_id, :customer_name, :postal_cd]], on=[:customer_name, :postal_cd], makeunique=true)
df_customer_n = @chain df begin
@rtransform(:integration_id = :customer_id_1)
@select($(Not(:customer_id_1)))
end
println("件数の差 = $(length(unique(df_customer_n.customer_id)) - length(unique(df_customer_n.integration_id)))")
head(df_customer_n)
件数の差 = 30
size = (21971, 12)
[1m10×12 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m[1m integration_id [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m[90m String15 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS021313000114 大野 あや子 1 女性 1981-04-29 37 259-1113 神奈川県伊勢原市粟窪********** S14021 20150905 0-00000000-0 CS021313000114
2 │ CS037613000071 六角 雅彦 9 不明 1952-04-01 66 136-0076 東京都江東区南砂********** S13037 20150414 0-00000000-0 CS037613000071
3 │ CS031415000172 宇多田 貴美子 1 女性 1976-10-04 42 151-0053 東京都渋谷区代々木********** S13031 20150529 D-20100325-C CS031415000172
4 │ CS028811000001 堀井 かおり 1 女性 1933-03-27 86 245-0016 神奈川県横浜市泉区和泉町********… S14028 20160115 0-00000000-0 CS028811000001
5 │ CS001215000145 田崎 美紀 1 女性 1995-03-29 24 144-0055 東京都大田区仲六郷********** S13001 20170605 6-20090929-2 CS001215000145
6 │ CS020401000016 宮下 達士 0 男性 1974-09-15 44 174-0065 東京都板橋区若木********** S13020 20150225 0-00000000-0 CS020401000016
7 │ CS015414000103 奥野 陽子 1 女性 1977-08-09 41 136-0073 東京都江東区北砂********** S13015 20150722 B-20100609-B CS015414000103
8 │ CS029403000008 釈 人志 0 男性 1973-08-17 45 279-0003 千葉県浦安市海楽********** S12029 20150515 0-00000000-0 CS029403000008
9 │ CS015804000004 松谷 米蔵 0 男性 1931-05-02 87 136-0073 東京都江東区北砂********** S13015 20150607 0-00000000-0 CS015804000004
10 │ CS033513000180 安斎 遥 1 女性 1962-07-11 56 241-0823 神奈川県横浜市旭区善部町********… S14033 20150728 6-20080506-5 CS033513000180
データの分割
J-089: 売上実績がある顧客を、予測モデル構築のため学習用データとテスト用データに分割したい。それぞれ8:2の割合でランダムにデータを分割せよ。
df_sales_customer = @chain df_receipt begin
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
end
df = innerjoin(df_customer, df_sales_customer, on=:customer_id)
using Random
n = nrow(df)
index = shuffle(collect(1:n))
df_customer_train = df[index[1:floor(Int, n*0.8)], :]
df_customer_test = df[index[floor(Int, n*0.8)+1:n], :]
println((nrow(df_customer_train)/n, nrow(df_customer_test)/n))
head(df_customer_train, 5)
head(df_customer_test, 5)
(0.7999036840837949, 0.20009631591620516)
size = (6644, 12)
[1m5×12 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m[1m sum_amount [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m[90m Int64 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS038515000133 沼田 佳乃 1 女性 1966-06-18 52 279-0043 千葉県浦安市富士見********** S13038 20141210 9-20100702-B 1871
2 │ CS008515000115 川瀬 璃奈子 1 女性 1960-12-08 58 157-0066 東京都世田谷区成城********** S13008 20151110 C-20100524-C 3712
3 │ CS013515000140 津川 窈 1 女性 1961-02-17 58 275-0025 千葉県習志野市秋津********** S12013 20141109 F-20100102-D 7476
4 │ CS012815000001 羽田 ちえみ 1 女性 1929-07-05 89 231-0826 神奈川県横浜市中区本牧荒井******… S14012 20150811 9-20100924-7 2130
5 │ CS025615000081 上原 真奈美 1 女性 1954-12-27 64 242-0015 神奈川県大和市下和田********** S14025 20150703 B-20100705-6 2843
size = (1662, 12)
[1m5×12 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m gender [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m[1m sum_amount [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m String7 [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m[90m Int64 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS003413000532 紺野 恵麻 1 女性 1975-11-10 43 182-0004 東京都調布市入間町********** S13003 20171219 2-20100418-2 306
2 │ CS013514000080 金城 佳乃 1 女性 1961-08-04 57 261-0025 千葉県千葉市美浜区浜田********** S12013 20150803 8-20100822-A 1453
3 │ CS038513000088 森岡 菜々美 1 女性 1966-12-30 52 279-0043 千葉県浦安市富士見********** S13038 20150508 6-20100816-9 807
4 │ CS028513000121 田原 あや子 1 女性 1967-06-17 51 241-0816 神奈川県横浜市旭区笹野台********… S14028 20150524 8-20100711-6 1548
5 │ CS037415000261 牧 奈々 1 女性 1976-02-07 43 135-0002 東京都江東区住吉********** S13037 20150120 D-20100205-B 4596
J-090: レシート明細データ(df_receipt)は2017年1月1日〜2019年10月31日までのデータを有している。売上金額(amount)を月次で集計し、学習用に12ヶ月、テスト用に6ヶ月の時系列モデル構築用データを3セット作成せよ。
df = @chain df_receipt begin
@rtransform(:sales_ym = :sales_ymd ÷ 100)
groupby(:sales_ym)
@combine(:sum_amount = sum(:amount))
@select(:sales_ym, :sum_amount)
end
function sampling()
start12 = rand(1:23, 1)[1]
start6 = rand(1:29, 1)[1]
df_train_1 = df[start12:start12+11, :];
df_test_1 = df[start6:start6+5, :];
return df_train_1, df_test_1
end
train, test = sampling();
println("***** first set")
println(train)
println(test)
println("***** second set")
train, test = sampling();
println(train)
println(test)
println("***** third set")
train, test = sampling();
println(train)
println(test)
***** first set
[1m12×2 DataFrame[0m
[1m Row [0m│[1m sales_ym [0m[1m sum_amount [0m
│[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────
1 │ 201806 1012329
2 │ 201807 1058472
3 │ 201808 1045793
4 │ 201809 977114
5 │ 201810 1069939
6 │ 201811 967479
7 │ 201812 1016425
8 │ 201901 1064085
9 │ 201902 959538
10 │ 201903 1093753
11 │ 201904 1044210
12 │ 201905 1111985
[1m6×2 DataFrame[0m
[1m Row [0m│[1m sales_ym [0m[1m sum_amount [0m
│[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────
1 │ 201806 1012329
2 │ 201807 1058472
3 │ 201808 1045793
4 │ 201809 977114
5 │ 201810 1069939
6 │ 201811 967479
***** second set
[1m12×2 DataFrame[0m
[1m Row [0m│[1m sales_ym [0m[1m sum_amount [0m
│[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────
1 │ 201711 932157
2 │ 201712 939654
3 │ 201801 944509
4 │ 201802 864128
5 │ 201803 946588
6 │ 201804 937099
7 │ 201805 1004438
8 │ 201806 1012329
9 │ 201807 1058472
10 │ 201808 1045793
11 │ 201809 977114
12 │ 201810 1069939
[1m6×2 DataFrame[0m
[1m Row [0m│[1m sales_ym [0m[1m sum_amount [0m
│[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────
1 │ 201812 1016425
2 │ 201901 1064085
3 │ 201902 959538
4 │ 201903 1093753
5 │ 201904 1044210
6 │ 201905 1111985
***** third set
[1m12×2 DataFrame[0m
[1m Row [0m│[1m sales_ym [0m[1m sum_amount [0m
│[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────
1 │ 201712 939654
2 │ 201801 944509
3 │ 201802 864128
4 │ 201803 946588
5 │ 201804 937099
6 │ 201805 1004438
7 │ 201806 1012329
8 │ 201807 1058472
9 │ 201808 1045793
10 │ 201809 977114
11 │ 201810 1069939
12 │ 201811 967479
[1m6×2 DataFrame[0m
[1m Row [0m│[1m sales_ym [0m[1m sum_amount [0m
│[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────
1 │ 201708 954836
2 │ 201709 902037
3 │ 201710 905739
4 │ 201711 932157
5 │ 201712 939654
6 │ 201801 944509
J-091: 顧客データ(df_customer)の各顧客に対し、売上実績がある顧客数と売上実績がない顧客数が1:1となるようにアンダーサンプリングで抽出せよ。
df = @chain df_receipt begin
groupby(:customer_id)
@combine(:sum_amount = sum(:amount))
end
df2 = @chain leftjoin(df_customer, df, on=:customer_id) begin
# @replacena(0) |>
@rtransform(:flag = :sum_amount > 0)
end;
gd2 = groupby(df2, :flag)
(n1, n2) = (nrow(gd2[1]), nrow(gd2[2]))
(8306, 13665)
using StatsBase
index = shuffle(collect(1:n2))
df_amount_0 = gd2[1];
df_amount_1 = gd2[2][index[1:n1], :]
nrow(df_amount_0), nrow(df_amount_1)
(8306, 8306)
第三正規形,非正規化
J-092: 顧客データ(df_customer)の性別について、第三正規形へと正規化せよ。
df_customer_std = @chain df_customer begin
@select($(Not(:gender)))
end
head(df_customer_std, 3)
size = (21971, 10)
[1m3×10 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m customer_name [0m[1m gender_cd [0m[1m birth_day [0m[1m age [0m[1m postal_cd [0m[1m address [0m[1m application_store_cd [0m[1m application_date [0m[1m status_cd [0m
│[90m String15 [0m[90m String31 [0m[90m String [0m[90m Date [0m[90m Int64 [0m[90m String15 [0m[90m String [0m[90m String7 [0m[90m String [0m[90m String15 [0m
─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ CS021313000114 大野 あや子 1 1981-04-29 37 259-1113 神奈川県伊勢原市粟窪********** S14021 20150905 0-00000000-0
2 │ CS037613000071 六角 雅彦 9 1952-04-01 66 136-0076 東京都江東区南砂********** S13037 20150414 0-00000000-0
3 │ CS031415000172 宇多田 貴美子 1 1976-10-04 42 151-0053 東京都渋谷区代々木********** S13031 20150529 D-20100325-C
df_gender_std = @chain df_customer begin
@select(:gender_cd, :gender)
unique()
end
head(df_gender_std, 3)
size = (3, 2)
[1m3×2 DataFrame[0m
[1m Row [0m│[1m gender_cd [0m[1m gender [0m
│[90m String [0m[90m String7 [0m
─────┼────────────────────
1 │ 1 女性
2 │ 9 不明
3 │ 0 男性
J-093: 商品データ(df_product)では各カテゴリのコード値だけを保有し、カテゴリ名は保有していない。カテゴリデータ(df_category)と組み合わせて非正規化し、カテゴリ名を保有した新たな商品データを作成せよ。
df_product_full = innerjoin(df_product, df_category[!, [:category_small_cd, :category_major_name, :category_medium_name, :category_small_name]], on=:category_small_cd);
head(df_product_full, 3)
size = (10030, 9)
[1m3×9 DataFrame[0m
[1m Row [0m│[1m product_cd [0m[1m category_major_cd [0m[1m category_medium_cd [0m[1m category_small_cd [0m[1m unit_price [0m[1m unit_cost [0m[1m category_major_name [0m[1m category_medium_name [0m[1m category_small_name [0m
│[90m String15 [0m[90m String [0m[90m String [0m[90m String [0m[90m Int64? [0m[90m Int64? [0m[90m String [0m[90m String [0m[90m String [0m
─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ P040101001 04 0401 040101 198 149 惣菜 御飯類 弁当類
2 │ P040101002 04 0401 040101 218 164 惣菜 御飯類 弁当類
3 │ P040101003 04 0401 040101 230 173 惣菜 御飯類 弁当類
ファイル入出力
J-094: 093で作成したカテゴリ名付き商品データを以下の仕様でファイル出力せよ。
ファイル形式 ヘッダ有無 文字エンコーディング CSV(カンマ区切り) 有り UTF-8 ファイル出力先のパスは以下のようにすること
出力先 ./data
CSV.write("-094.csv", df_product_full)
"-094.csv"
これ以降の問題は重要なものではないのでパスする
J-095: 093で作成したカテゴリ名付き商品データを以下の仕様でファイル出力せよ。
ファイル形式 ヘッダ有無 文字エンコーディング CSV(カンマ区切り) 有り CP932 ファイル出力先のパスは以下のようにすること。
出力先 ./data
J-096: 093で作成したカテゴリ名付き商品データを以下の仕様でファイル出力せよ。
ファイル形式 ヘッダ有無 文字エンコーディング CSV(カンマ区切り) 無し UTF-8 ファイル出力先のパスは以下のようにすること。
出力先 ./data
J-097: 094で作成した以下形式のファイルを読み込み、データを3件を表示させて正しく取り込まれていることを確認せよ。
ファイル形式 ヘッダ有無 文字エンコーディング CSV(カンマ区切り) 有り UTF-8
J-098: 096で作成した以下形式のファイルを読み込み、データを3件を表示させて正しく取り込まれていることを確認せよ。
ファイル形式 ヘッダ有無 文字エンコーディング CSV(カンマ区切り) ヘッダ無し UTF-8
J-099: 093で作成したカテゴリ名付き商品データを以下の仕様でファイル出力せよ。
ファイル形式 ヘッダ有無 文字エンコーディング TSV(タブ区切り) 有り UTF-8 ファイル出力先のパスは以下のようにすること
出力先 ./data
J-100: 099で作成した以下形式のファイルを読み込み、データを3件を表示させて正しく取り込まれていることを確認せよ。
ファイル形式 ヘッダ有無 文字エンコーディング TSV(タブ区切り) 有り UTF-8
~~# これで100本終わりです。おつかれさまでした!