データサイエンス100本ノック(構造化データ加工編) - Julia/BaseR/Query
別稿では DataFramesMeta を使う場合の解答例を示した。
https://qiita.com/WolfMoon/items/387d18e4ea3f65768997
本稿では BaseR の場合と Query を使う場合の解答例を示す。
ファイル等の準備
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 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);
はじめに
初めに以下のセルを実行してください
必要なライブラリのインポートとデータベース(PostgreSQL)からのデータ読み込みを行います
pandas等、利用が想定されるライブラリは以下セルでインポートしています
その他利用したいライブラリがあれば適宜インストールしてください("!pip install ライブラリ名"でインストールも可能)
- 処理は複数回に分けても構いません
- 名前、住所等はダミーデータであり、実在するものではありません
入力したデータフレームの確認
入力後のデータフレームの確認は,ここでは先頭 10 件を表示させ,目視で確認するということであるが,それぞれの列がどのように読み取られているかを確認すべきである。
実際には,各項目の度数分布を求めたり,ヒストグラムを描いたりして不適切なデータがあるかないかを確認すべきである。また,欠損値の有無と欠損値に特別の値が与えられているかどうかなどを確認しておく必要がある。
1. 単純な目視確認
J-001: レシート明細データ(df_receipt)から全項目の先頭10件を表示し、どのようなデータを保有しているか目視で確認せよ。
df_receipt[1:10, :] # 範囲を指定できる
Row |
sales_ymd |
sales_epoch |
store_cd |
receipt_no |
receipt_sub_no |
customer_id |
product_cd |
quantity |
amount |
|
Int64 |
Int64 |
String7 |
Int64 |
Int64 |
String15 |
String15 |
Int64 |
Int64 |
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 |
# 別解
first(df_receipt, 10) # 特定の処理に特化したの関数が用意されていることもある
Row |
sales_ymd |
sales_epoch |
store_cd |
receipt_no |
receipt_sub_no |
customer_id |
product_cd |
quantity |
amount |
|
Int64 |
Int64 |
String7 |
Int64 |
Int64 |
String15 |
String15 |
Int64 |
Int64 |
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 |
Query,パイプを使うことを好む人もいるが,多くの場合面倒くさい。以下しばらくの間,パイプと組み合わせて Query を使う(R の tidyverse のような)やり方を別解として記しておく。
# 別解2
df_receipt |>
@take(10) |>
DataFrame
Row |
sales_ymd |
sales_epoch |
store_cd |
receipt_no |
receipt_sub_no |
customer_id |
product_cd |
quantity |
amount |
|
Int64 |
Int64 |
String7 |
Int64 |
Int64 |
String15 |
String15 |
Int64 |
Int64 |
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件表示せよ。
df_receipt[1:10, [:sales_ymd, :customer_id, :product_cd, :amount]] # 行と列を指定できる(順序も)
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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 |
# 別解
df = df_receipt[!, [:sales_ymd, :customer_id, :product_cd, :amount]]
first(df, 10)
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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 |
df[] の中の最初の次元の ! または : はすべての行を意味する。! は直接参照するが,: はコピーしたものを参照する。そのため,! を使うほうが処理時間は短い。
@time df = df_receipt[!, [:sales_ymd, :customer_id, :product_cd, :amount]];
0.000022 seconds (24 allocations: 1.875 KiB)
@time df = df_receipt[:, [:sales_ymd, :customer_id, :product_cd, :amount]];
0.004656 seconds (11.01 k allocations: 5.386 MiB, 88.53% compilation time)
# 別解2
df_receipt |>
@select(:sales_ymd, :customer_id, :product_cd, :amount) |>
@take(10) |>
DataFrame
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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に項目名を変更しながら抽出すること。
df = df_receipt[!, [:sales_ymd, :customer_id, :product_cd, :amount]]
df = rename(df, :sales_ymd => :sales_date) # rename!() を使うときには注意
first(df, 10)
Row |
sales_date |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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 |
# 別解
df_receipt |>
@select(:sales_ymd, :customer_id, :product_cd, :amount) |>
@rename(:sales_ymd => :sales_date) |>
@take(10) |>
DataFrame
Row |
sales_date |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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. 論理演算式による行の選択
J-004: レシート明細データ(df_receipt)から売上日(sales_ymd)、顧客ID(customer_id)、商品コード(product_cd)、売上金額(amount)の順に列を指定し、以下の条件を満たすデータを抽出せよ。
- 顧客ID(customer_id)が"CS018205000001"
-
列の選択はシンボルベクトル(:foo など)で行う。
- 指定した順で選択される。
- 1 列だけを指定するときもベクトルで指定する([:foo] のように)。
-
行を選択するための条件式(論理式)を書くことができる。
- 条件式中の演算子は通常は先行するドット(.)が必要である。
- 条件式中の列 :foo の指定は df.foo のようにする。
df_receipt[df_receipt.customer_id .== "CS018205000001", [:sales_ymd, :customer_id, :product_cd, :amount]]
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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 |
# 別解
df_receipt |>
@select(:sales_ymd, :customer_id, :product_cd, :amount) |>
@filter(_.customer_id == "CS018205000001") |>
DataFrame
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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_receipt[df_receipt.customer_id .== "CS018205000001" .&& df_receipt.amount .>= 1000, [:sales_ymd, :customer_id, :product_cd, :amount]]
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
1 |
20180911 |
CS018205000001 |
P071401012 |
2200 |
2 |
20190226 |
CS018205000001 |
P071401020 |
2200 |
3 |
20180911 |
CS018205000001 |
P071401005 |
1100 |
# 別解
df = select(df_receipt, [:sales_ymd, :customer_id, :product_cd, :amount])
filter([:customer_id, :amount] => (x, y) -> x == "CS018205000001" && y >= 1000, df)
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
1 |
20180911 |
CS018205000001 |
P071401012 |
2200 |
2 |
20190226 |
CS018205000001 |
P071401020 |
2200 |
3 |
20180911 |
CS018205000001 |
P071401005 |
1100 |
# 別解2
df_receipt |>
@select(:sales_ymd, :customer_id, :product_cd, :amount) |>
@filter(_.customer_id == "CS018205000001" && _.amount >= 1000) |>
DataFrame
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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_receipt[df_receipt.customer_id .== "CS018205000001" .&& (df_receipt.amount .>= 1000 .|| df_receipt.quantity .>= 5), [:sales_ymd, :customer_id, :product_cd, :quantity, :amount]]
Row |
sales_ymd |
customer_id |
product_cd |
quantity |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
Int64 |
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 |
# 別解
df = select(df_receipt, [:sales_ymd, :customer_id, :product_cd, :quantity, :amount])
filter([:customer_id, :amount, :quantity] => (x, y, z) -> x == "CS018205000001" && (y >= 1000 || z >= 5), df)
Row |
sales_ymd |
customer_id |
product_cd |
quantity |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
Int64 |
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 |
# 別解2
df_receipt |>
@select(:sales_ymd, :customer_id, :product_cd, :quantity, :amount) |>
@filter(_.customer_id == "CS018205000001" && (_.amount >= 1000 || _.quantity >= 5)) |>
DataFrame
Row |
sales_ymd |
customer_id |
product_cd |
quantity |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
Int64 |
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_receipt[df_receipt.customer_id .== "CS018205000001" .&& 1000 .<= df_receipt.amount .<= 2000, [:sales_ymd, :customer_id, :product_cd, :amount]]
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
1 |
20180911 |
CS018205000001 |
P071401005 |
1100 |
# 別解
df = select(df_receipt, [:sales_ymd, :customer_id, :product_cd, :amount])
filter([:customer_id, :amount] => (x, y) -> x == "CS018205000001" && y >= 1000 <= y <= 2000, df)
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
1 |
20180911 |
CS018205000001 |
P071401005 |
1100 |
# 別解2
df_receipt |>
@select(:sales_ymd, :customer_id, :product_cd, :amount) |>
@filter(_.customer_id == "CS018205000001" && 1000 <= _.amount <= 2000) |>
DataFrame
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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_receipt[df_receipt.customer_id .== "CS018205000001" .&& df_receipt.product_cd .!= "P071401019", [:sales_ymd, :customer_id, :product_cd, :amount]]
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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 |
# 別解
df = select(df_receipt, [:sales_ymd, :customer_id, :product_cd, :amount])
filter([:customer_id, :product_cd] => (x, y) -> x == "CS018205000001" && y != "P071401019", df)
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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 |
# 別解2
df_receipt |>
@select(:sales_ymd, :customer_id, :product_cd, :amount) |>
@filter(_.customer_id == "CS018205000001" && _.product_cd != "P071401019") |>
DataFrame
Row |
sales_ymd |
customer_id |
product_cd |
amount |
|
Int64 |
String15 |
String15 |
Int64 |
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_store[df_store.prefecture_cd .!= "13" .&& df_store.floor_area .<= 900, :]
Row |
store_cd |
store_name |
prefecture_cd |
prefecture |
address |
address_kana |
tel_no |
longitude |
latitude |
floor_area |
|
String7 |
String31 |
String |
String15 |
String |
String |
String15 |
Float64 |
Float64 |
Float64 |
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_store |>
@filter(_.prefecture_cd != "13" && _.floor_area <= 900) |>
DataFrame
Row |
store_cd |
store_name |
prefecture_cd |
prefecture |
address |
address_kana |
tel_no |
longitude |
latitude |
floor_area |
|
String7 |
String31 |
String |
String15 |
String |
String |
String15 |
Float64 |
Float64 |
Float64 |
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 = df_store[occursin.(r"^S14", df_store.store_cd), :] # occursin のあとに . が必要
first(df, 10)
Row |
store_cd |
store_name |
prefecture_cd |
prefecture |
address |
address_kana |
tel_no |
longitude |
latitude |
floor_area |
|
String7 |
String31 |
String |
String15 |
String |
String |
String15 |
Float64 |
Float64 |
Float64 |
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 |
# 別解
df_store |>
@filter(occursin(r"^S14", _.store_cd)) |>
@take(10) |>
DataFrame
Row |
store_cd |
store_name |
prefecture_cd |
prefecture |
address |
address_kana |
tel_no |
longitude |
latitude |
floor_area |
|
String7 |
String31 |
String |
String15 |
String |
String |
String15 |
Float64 |
Float64 |
Float64 |
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 = df_customer[occursin.(r"1$", df_customer.customer_id), :]
first(df, 10)
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 |
# 別解2
df_customer |>
@filter(occursin(r"1$", _.customer_id)) |>
@take(10) |>
DataFrame
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 = df_store[occursin.(r"横浜市", df_store.address), :]
df
Row |
store_cd |
store_name |
prefecture_cd |
prefecture |
address |
address_kana |
tel_no |
longitude |
latitude |
floor_area |
|
String7 |
String31 |
String |
String15 |
String |
String |
String15 |
Float64 |
Float64 |
Float64 |
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 |
# 別解
df_store |>
@filter(occursin(r"横浜市", _.address)) |>
DataFrame
Row |
store_cd |
store_name |
prefecture_cd |
prefecture |
address |
address_kana |
tel_no |
longitude |
latitude |
floor_area |
|
String7 |
String31 |
String |
String15 |
String |
String |
String15 |
Float64 |
Float64 |
Float64 |
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 = df_customer[occursin.(r"^[A-F]", df_customer.status_cd), :]
first(df, 10)
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 |
# 別解
df_customer |>
@filter(occursin(r"^[A-F]", _.status_cd)) |>
@take(10) |>
DataFrame
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 = df_customer[occursin.(r"[1-9]$", df_customer.status_cd), :]
first(df, 10)
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 |
# 別解
df_customer |>
@filter(occursin(r"[1-9]$", _.status_cd)) |>
@take(10) |>
DataFrame
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 = df_customer[occursin.(r"^[A-F].*[0-9]$", df_customer.status_cd), :]
first(df, 10)
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 |
# 別解
df_customer |>
@filter(occursin(r"^[A-F].*[0-9]$", _.status_cd)) |>
@take(10) |>
DataFrame
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 = df_store[occursin.(r"[0-9]{3}-[0-9]{3}-[0-9]{4}", df_store.tel_no), :]
first(df, 10)
Row |
store_cd |
store_name |
prefecture_cd |
prefecture |
address |
address_kana |
tel_no |
longitude |
latitude |
floor_area |
|
String7 |
String31 |
String |
String15 |
String |
String |
String15 |
Float64 |
Float64 |
Float64 |
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 |
# 別解
df_store |>
@filter(occursin(r"[0-9]{3}-[0-9]{3}-[0-9]{4}", _.tel_no)) |>
DataFrame
34×10 DataFrame
9 rows omitted
Row |
store_cd |
store_name |
prefecture_cd |
prefecture |
address |
address_kana |
tel_no |
longitude |
latitude |
floor_area |
|
String7 |
String31 |
String |
String15 |
String |
String |
String15 |
Float64 |
Float64 |
Float64 |
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 |
⋮ |
⋮ |
⋮ |
⋮ |
⋮ |
⋮ |
⋮ |
⋮ |
⋮ |
⋮ |
⋮ |
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 = sort(df_customer, :birth_day)
first(df, 10)
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 |
# 別解
df_customer |>
@orderby(_.birth_day) |>
@take(10) |>
DataFrame
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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件表示せよ。
降順にソートするには ref=true
を指定する。
df = sort(df_customer, :birth_day, rev=true)
first(df, 10)
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 |
# 別解
df_customer |>
@orderby_descending(_.birth_day) |>
@take(10) |>
DataFrame
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 = select(df_receipt, [:customer_id, :amount])
df.rank = competerank(df_receipt.amount, rev=true)
df = sort(df, :rank)
first(df, 10)
Row |
customer_id |
amount |
rank |
|
String15 |
Int64 |
Int64 |
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 |
# 別解
using StatsBase
df_receipt |>
x -> hcat(x, DataFrame(rank = competerank(df_receipt[:, :amount], rev=true))) |>
@select(:customer_id, :amount, :rank) |>
@orderby(_.rank) |>
@take(10) |>
DataFrame
Row |
customer_id |
amount |
rank |
|
String15 |
Int64 |
Int64 |
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 = select(df_receipt, [:customer_id, :amount])
df.rank = ordinalrank(df_receipt.amount, rev=true)
df = sort(df, :rank)
first(df, 10)
Row |
customer_id |
amount |
rank |
|
String15 |
Int64 |
Int64 |
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 |
# 別解
df_receipt |>
x -> hcat(x, DataFrame(rank = ordinalrank(df_receipt[:, :amount], rev=true))) |>
@select(:customer_id, :amount, :rank) |>
@orderby(_.rank) |>
@take(10) |>
DataFrame
Row |
customer_id |
amount |
rank |
|
String15 |
Int64 |
Int64 |
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)に対し、件数をカウントせよ。
J-022: レシート明細データ(df_receipt)の顧客ID(customer_id)に対し、ユニーク件数をカウントせよ。
ユニークなデータ,データフレームを作るには unique()
を使う。
length(unique(df_receipt.customer_id))
# 別解
df_receipt |>
@unique(_.customer_id) |>
collect |>
length
# 別解2
df_receipt |>
@select(:customer_id) |>
@unique() |>
DataFrame |>
nrow
# 別解3
df_receipt |>
@select(:customer_id) |>
@unique() |>
collect |>
length
グループ化して処理
groupby() によってグループ化して,それぞれのグループ化データフレームを combine()
によって処理して,その結果をデータフレームとして生成する。
7. 合計
J-023: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)と売上数量(quantity)を合計せよ。
gd = groupby(df_receipt, :store_cd);
df = combine(gd, :amount => sum => :amount, :quantity => sum => :quantity)
sort(df, :store_cd)
52×3 DataFrame
27 rows omitted
Row |
store_cd |
amount |
quantity |
|
String7 |
Int64 |
Int64 |
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 |
⋮ |
⋮ |
⋮ |
⋮ |
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 |
# 別解
df_receipt |>
@groupby(_.store_cd) |>
@map({store_cd=key(_), amount=sum(_.amount), quantity=sum(_.quantity)}) |>
@orderby(_.store_cd) |>
DataFrame
52×3 DataFrame
27 rows omitted
Row |
store_cd |
amount |
quantity |
|
String7 |
Int64 |
Int64 |
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 |
⋮ |
⋮ |
⋮ |
⋮ |
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件表示せよ。
gd = groupby(df_receipt, :customer_id);
df = combine(gd, :sales_ymd => maximum)
df = sort(df, :customer_id) # ソートする必要がある場合
first(df, 10)
Row |
customer_id |
sales_ymd_maximum |
|
String15 |
Int64 |
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 |
# 別解
df_receipt |>
@groupby(_.customer_id) |>
@map({customer_id=key(_), sales_ymd_maximum=maximum(_.sales_ymd)}) |>
@orderby(_.customer_id) |>
@take(10) |>
DataFrame
Row |
customer_id |
sales_ymd_maximum |
|
String15 |
Int64 |
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件表示せよ。
gd = groupby(df_receipt, :customer_id);
df = combine(gd, :sales_ymd => minimum)
df2 = sort(df, :customer_id)
first(df2, 10)
Row |
customer_id |
sales_ymd_minimum |
|
String15 |
Int64 |
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 |
# 別解
df_receipt |>
@groupby(_.customer_id) |>
@map({customer_id=key(_), sales_ymd_minimum=minimum(_.sales_ymd)}) |>
@orderby(_.customer_id) |>
@take(10) |>
DataFrame
Row |
customer_id |
sales_ymd_minimum |
|
String15 |
Int64 |
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件表示せよ。
gd = groupby(df_receipt, :customer_id);
df = combine(gd, :sales_ymd => maximum => :max_ymd, :sales_ymd => minimum => :min_ymd) |>
@filter(_.min_ymd != _.max_ymd) |>
@orderby(_.customer_id) |>
DataFrame
first(df, 10)
Row |
customer_id |
max_ymd |
min_ymd |
|
String15 |
Int64 |
Int64 |
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 |
# 別解
df_receipt |>
@groupby(_.customer_id) |>
@map({customer_id=key(_), max_ymd=maximum(_.sales_ymd), min_ymd=minimum(_.sales_ymd)}) |>
@filter(_.min_ymd != _.max_ymd) |>
@orderby(_.customer_id) |>
@take(10) |>
DataFrame
Row |
customer_id |
max_ymd |
min_ymd |
|
String15 |
Int64 |
Int64 |
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
gd = groupby(df_receipt, :store_cd);
combine(gd, :amount => mean => :mean_amount) |>
@orderby_descending(_.mean_amount) |>
@take(5) |>
DataFrame
Row |
store_cd |
mean_amount |
|
String7 |
Float64 |
1 |
S13052 |
402.867 |
2 |
S13015 |
351.112 |
3 |
S13003 |
350.916 |
4 |
S14010 |
348.791 |
5 |
S13001 |
348.47 |
# 別解
using StatsBase
df_receipt |>
@groupby(_.store_cd) |>
@map({store_cd=key(_), mean_amount=mean(_.amount)}) |>
@orderby_descending(_.mean_amount) |>
@take(5) |>
DataFrame
Row |
store_cd |
mean_amount |
|
String7 |
Float64 |
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を表示せよ。
gd = groupby(df_receipt, :store_cd);
combine(gd, :amount => median => :median_amount) |>
@orderby_descending(_.median_amount) |>
@thenby(_.store_cd) |>
@take(5) |>
DataFrame
Row |
store_cd |
median_amount |
|
String7 |
Float64 |
1 |
S13052 |
190.0 |
2 |
S14010 |
188.0 |
3 |
S14050 |
185.0 |
4 |
S13003 |
180.0 |
5 |
S13018 |
180.0 |
13. 最頻値
J-029: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに商品コード(product_cd)の最頻値を求め、10件表示させよ。
gd = groupby(df_receipt, :store_cd);
combine(gd, :product_cd => mode) |>
@orderby(_.store_cd) |>
@take(10) |>
DataFrame
Row |
store_cd |
product_cd_mode |
|
String7 |
String15 |
1 |
S12007 |
P060303001 |
2 |
S12013 |
P060303001 |
3 |
S12014 |
P060303001 |
4 |
S12029 |
P060303001 |
5 |
S12030 |
P060303001 |
6 |
S13001 |
P060303001 |
7 |
S13002 |
P060303001 |
8 |
S13003 |
P071401001 |
9 |
S13004 |
P060303001 |
10 |
S13005 |
P040503001 |
# 別解
using StatsBase
df_receipt |>
@groupby(_.store_cd) |>
@map({store_cd=key(_), product_cd_mode=mode(_.product_cd)}) |>
@orderby(_.store_cd) |>
@take(10) |>
DataFrame
Row |
store_cd |
product_cd_mode |
|
String7 |
String15 |
1 |
S12007 |
P060303001 |
2 |
S12013 |
P060303001 |
3 |
S12014 |
P060303001 |
4 |
S12029 |
P060303001 |
5 |
S12030 |
P060303001 |
6 |
S13001 |
P060303001 |
7 |
S13002 |
P060303001 |
8 |
S13003 |
P071401001 |
9 |
S13004 |
P060303001 |
10 |
S13005 |
P040503001 |
14. 分散
J-030: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の分散を計算し、降順で5件表示せよ。
gd = groupby(df_receipt, :store_cd);
combine(gd, :amount => (x -> var(x, corrected=false)) => :var_amount) |>
@orderby_descending(_.var_amount) |>
@take(5) |>
DataFrame
Row |
store_cd |
var_amount |
|
String7 |
Float64 |
1 |
S13052 |
4.40089e5 |
2 |
S14011 |
3.06315e5 |
3 |
S14034 |
2.9692e5 |
4 |
S13001 |
295432.0 |
5 |
S13015 |
2.95294e5 |
# 別解
df_receipt |>
@groupby(_.store_cd) |>
@map({store_cd=key(_), var_amount=var(_.amount, corrected=false)}) |>
@orderby_descending(_.var_amount) |>
@take(5) |>
DataFrame
Row |
store_cd |
var_amount |
|
String7 |
Float64 |
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件表示せよ。
gd = groupby(df_receipt, :store_cd);
combine(gd, :amount => (x -> std(x, corrected=false)) => :std_amount) |>
@orderby_descending(_.std_amount) |>
@take(5) |>
DataFrame
Row |
store_cd |
std_amount |
|
String7 |
Float64 |
1 |
S13052 |
663.392 |
2 |
S14011 |
553.457 |
3 |
S14034 |
544.904 |
4 |
S13001 |
543.537 |
5 |
S13015 |
543.41 |
# 別解
df_receipt |>
@groupby(_.store_cd) |>
@map({store_cd=key(_), std_amount=std(_.amount, corrected=false)}) |>
@orderby_descending(_.std_amount) |>
@take(5) |>
DataFrame
Row |
store_cd |
std_amount |
|
String7 |
Float64 |
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%刻みでパーセンタイル値を求めよ。
quantile(df_receipt.amount, 0.25:0.25:1)
4-element Vector{Float64}:
102.0
170.0
288.0
10925.0
# 別解
combine(df_receipt, :amount => x -> quantile(x, 0.25:0.25:1))
Row |
amount_function |
|
Float64 |
1 |
102.0 |
2 |
170.0 |
3 |
288.0 |
4 |
10925.0 |
17. 比較演算,論理演算
J-033: レシート明細データ(df_receipt)に対し、店舗コード(store_cd)ごとに売上金額(amount)の平均を計算し、330以上のものを抽出せよ。
gd = groupby(df_receipt, :store_cd);
combine(gd, :amount => mean => :mean_amount) |>
@filter(_.mean_amount >= 330) |>
@orderby(_.store_cd) |>
DataFrame
Row |
store_cd |
mean_amount |
|
String7 |
Float64 |
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 |
# 別解
df_receipt |>
@groupby(_.store_cd) |>
@map({store_cd=key(_), mean_amount=mean(_.amount)}) |>
@filter(_.mean_amount >= 330) |>
@orderby(_.store_cd) |>
DataFrame
Row |
store_cd |
mean_amount |
|
String7 |
Float64 |
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"から始まるものは非会員を表すため、除外して計算すること。
using StatsBase
df2 = df_receipt |>
@filter(!occursin(r"^Z", _.customer_id)) |>
DataFrame;
gd = groupby(df2, :customer_id);
df3 = combine(gd, :amount => sum => :sum_amount)
using StatsBase
mean(df3.sum_amount)
# 別解
df2 = df_receipt |>
@filter(!occursin(r"^Z", _.customer_id)) |>
@groupby(_.customer_id) |>
@map({sum=sum(_.amount)}) |>
DataFrame |>
x -> mean(x.sum)
J-035: レシート明細データ(df_receipt)に対し、顧客ID(customer_id)ごとに売上金額(amount)を合計して全顧客の平均を求め、平均以上に買い物をしている顧客を抽出し、10件表示せよ。ただし、顧客IDが"Z"から始まるものは非会員を表すため、除外して計算すること。
df2 = df_receipt |>
@filter(!occursin(r"^Z", _.customer_id)) |>
DataFrame;
gd = groupby(df2, :customer_id);
df3 = combine(gd, :amount => sum => :sum_amount)
using StatsBase
mean_amount = mean(df3.sum_amount)
df3 |>
@filter(_.sum_amount > mean_amount) |>
@orderby(_.customer_id) |>
@take(10) |>
DataFrame
Row |
customer_id |
sum_amount |
|
String15 |
Int64 |
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 |
# 別解
df2 = df_receipt |>
@filter(!occursin(r"^Z", _.customer_id)) |>
@groupby(_.customer_id) |>
@map({customer_id=_.customer_id[1], sum_amount=sum(_.amount)}) |>
DataFrame
grandmean = mean(df2.sum_amount)
df2 |>
@filter(_.sum_amount > grandmean) |>
@orderby(_.customer_id) |>
@take(10) |>
DataFrame
Row |
customer_id |
sum_amount |
|
String15 |
Int64 |
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件表示せよ。
innerjoin(df_receipt, df_store[!, [:store_cd, :store_name]], on=:store_cd) |> (x -> first(x, 10))
Row |
sales_ymd |
sales_epoch |
store_cd |
receipt_no |
receipt_sub_no |
customer_id |
product_cd |
quantity |
amount |
store_name |
|
Int64 |
Int64 |
String7 |
Int64 |
Int64 |
String15 |
String15 |
Int64 |
Int64 |
String31 |
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 |
南藤沢店 |
# 別解
df_receipt |>
@join(df_store, _.store_cd, _.store_cd,
{_.sales_ymd, _.sales_epoch, _.store_cd, _.receipt_no,
_.receipt_sub_no, _.customer_id, _.product_cd, _.quantity,
_.amount, __.store_name}) |>
@take(10) |>
DataFrame
Row |
sales_ymd |
sales_epoch |
store_cd |
receipt_no |
receipt_sub_no |
customer_id |
product_cd |
quantity |
amount |
store_name |
|
Int64 |
Int64 |
String7 |
Int64 |
Int64 |
String15 |
String15 |
Int64 |
Int64 |
String31 |
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件表示せよ。
first(innerjoin(df_product, df_category[!, [:category_small_name, :category_small_cd]], on=:category_small_cd, makeunique=true), 10)
Row |
product_cd |
category_major_cd |
category_medium_cd |
category_small_cd |
unit_price |
unit_cost |
category_small_name |
|
String15 |
String |
String |
String |
Int64? |
Int64? |
String |
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 |
弁当類 |
# 別解
df_product |>
@join(df_category, _.category_small_cd, _.category_small_cd,
{_.product_cd, _.category_major_cd, _.category_medium_cd,
_.category_small_cd, _.unit_price, _.unit_cost,
__.category_small_name}) |>
@take(10) |>
DataFrame
Row |
product_cd |
category_major_cd |
category_medium_cd |
category_small_cd |
unit_price |
unit_cost |
category_small_name |
|
String15 |
String |
String |
String |
Int64? |
Int64? |
String |
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)
filter!(:customer_id => x -> !occursin(r"^Z", x), df)
filter!(:gender_cd => x -> x == "1", df);
df2 = groupby(df, :customer_id)
df3 = combine(df2, :amount => sum => :sum_amount);
df3.sum_amount .= coalesce.(df3.sum_amount, 0); # coalesce() は missing の置換に使える
first(sort(df3, :customer_id), 10)
Row |
customer_id |
sum_amount |
|
String15 |
Int64 |
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 |
# 別解
leftjoin(df_customer[!, [:customer_id, :gender_cd]], df_receipt[!, [:customer_id, :amount]], on=:customer_id) |>
@filter(!occursin(r"^Z", _.customer_id)) |>
@filter(_.gender_cd == "1") |>
@groupby(_.customer_id) |>
@map({customer_id=key(_), sum_amount=sum(_.amount)}) |>
@replacena(:sum_amount => 0) |>
@orderby(_.customer_id) |>
@take(10) |>
DataFrame
Row |
customer_id |
sum_amount |
|
String15 |
Int64 |
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"から始まるもの)は除外すること。
df2 = groupby(filter(:customer_id => x -> !occursin(r"^Z", x), df_receipt), :customer_id)
df3 = sort(combine(df2, :sales_ymd => (x -> length(unique(x))) => :come_days), :come_days, rev=true)[1:20, :];
df4 = sort(combine(df2, :amount => sum => :sum_amount), :sum_amount, rev=true)[1:20, :];
io = IOContext(stdout, :limit => false)
println(outerjoin(df3, df4, on=:customer_id, makeunique=true))
io = IOContext(stdout, :limit => true)
[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
IOContext(Base.PipeEndpoint(RawFD(40) open, 0 bytes waiting))
# 別解
df2 = df_receipt |>
@filter(!occursin(r"^Z", _.customer_id)) |>
DataFrame
gd = groupby(df2, :customer_id)
df3 = combine(gd, :sales_ymd => (x -> length(unique(x))) => :come_days) |>
@orderby_descending(_.come_days) |>
@take(20) |>
DataFrame
df4 = combine(gd, :amount => sum) |>
@orderby_descending(_.amount_sum) |>
@take(20) |>
DataFrame;
io = IOContext(stdout, :limit => false)
println(outerjoin(df3, df4, on=:customer_id))
io = IOContext(stdout, :limit => true)
[1m34×3 DataFrame[0m
[1m Row [0m│[1m customer_id [0m[1m come_days [0m[1m amount_sum [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
IOContext(Base.PipeEndpoint(RawFD(40) open, 0 bytes waiting))
J-040: 全ての店舗と全ての商品を組み合わせたデータを作成したい。店舗データ(df_store)と商品データ(df_product)を直積し、件数を計算せよ。
件数を計算するだけなら,それぞれの件数の積である。
nrow(df_store) * nrow(df_product)
# 別解
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
差分
J-041: レシート明細データ(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、前回売上があった日からの売上金額増減を計算せよ。そして結果を10件表示せよ。
gd = groupby(df_receipt, :sales_ymd)
df = combine(gd, :amount => sum) |>
@orderby(_.sales_ymd) |>
DataFrame;
df2 = df[1:end-1, :] |>
@rename(:sales_ymd => :lag_sales_ymd, :amount_sum => :lag_amount_sum) |>
DataFrame;
df4 = vcat(DataFrame(lag_sales_ymd = missing, lag_amount_sum = missing), df2);
hcat(df, df4) |>
@mutate(diff_amount = _.amount_sum - _.lag_amount_sum) |>
@take(10) |>
DataFrame
Row |
sales_ymd |
amount_sum |
lag_sales_ymd |
lag_amount_sum |
diff_amount |
|
Int64 |
Int64 |
Int64? |
Int64? |
Int64? |
1 |
20170101 |
33723 |
missing |
missing |
missing |
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 |
# 別解
gd = groupby(df_receipt, :sales_ymd);
df = combine(gd, :amount => sum) |>
@orderby(_.sales_ymd) |>
DataFrame
d = Vector{Union{Int64, Missing}}(missing, nrow(df))
d[2:end] = diff(df[:, :amount_sum]);
DataFrame(sales_ymd = df.sales_ymd, diff_amount = d) |>
@take(10)
sales_ymd |
diff_amount |
20170101 |
#NA |
20170102 |
-9558 |
20170103 |
3338 |
20170104 |
8662 |
20170105 |
1665 |
20170106 |
-5443 |
20170107 |
-8972 |
20170108 |
1322 |
20170109 |
1981 |
20170110 |
-6575 |
1 行目(amount_sum が missing)が必要なければ,以下よりもさらに簡単になる。
# 別解2
gd = groupby(df_receipt, :sales_ymd);
df = combine(gd, :amount => sum) |>
@orderby(_.sales_ymd) |>
DataFrame |>
allowmissing!; # これをしないと missing を代入できない
df[2:end, :amount_sum] = diff(df[:, :amount_sum]);
df[1, :amount_sum] = missing # 代入の順番も考慮する
df |>
@rename(:amount_sum => :diff_amount) |>
@take(10)
sales_ymd |
diff_amount |
20170101 |
#NA |
20170102 |
-9558 |
20170103 |
3338 |
20170104 |
8662 |
20170105 |
1665 |
20170106 |
-5443 |
20170107 |
-8972 |
20170108 |
1322 |
20170109 |
1981 |
20170110 |
-6575 |
# 別解3
gd = groupby(df_receipt, :sales_ymd);
df = combine(gd, :amount => sum) |>
@orderby(_.sales_ymd) |>
DataFrame;
DataFrame(sales_ymd = df[2:end, 1], diff_amount = diff(df[:, :amount_sum])) |>
@take(10)
sales_ymd |
diff_amount |
20170102 |
-9558 |
20170103 |
3338 |
20170104 |
8662 |
20170105 |
1665 |
20170106 |
-5443 |
20170107 |
-8972 |
20170108 |
1322 |
20170109 |
1981 |
20170110 |
-6575 |
20170111 |
4144 |
J-042: レシート明細データ(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、各日付のデータに対し、前回、前々回、3回前に売上があった日のデータを結合せよ。そして結果を10件表示せよ。
gd = groupby(df_receipt, :sales_ymd);
df = combine(gd, :amount => sum) |>
@orderby(_.sales_ymd) |>
DataFrame;
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
delete!(df2, 1)
first(df2, 10)
Row |
sales_ymd |
amount |
lag_ymd |
lag_amount |
|
Int64 |
Int64 |
Int64 |
Int64 |
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 |
# 別解
gd = groupby(df_receipt, :sales_ymd);
df = combine(gd, :amount => sum) |>
@orderby(_.sales_ymd) |>
DataFrame;
df2 = 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!(df2,
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
delete!(df2, 1)
first(df2, 10)
Row |
sales_ymd |
amount |
lag_ymd_1 |
lag_amount_1 |
lag_ymd_2 |
lag_amount_2 |
lag_ymd_3 |
lag_amount_3 |
|
Int64 |
Int64 |
Int64 |
Int64 |
Int64 |
Int64 |
Int64 |
Int64 |
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 = innerjoin(df_receipt[!, [:customer_id, :amount]],
df_customer[!, [:customer_id, :gender_cd, :age]],
on=:customer_id, makeunique=true)
df.age = div.(df.age, 10) .* 10
gd = groupby(df, [:age, :gender_cd])
df2 = combine(gd, :amount => sum);
using NamedArrays
using FreqTables
table = freqtable(df2.age, df2.gender_cd, weights=df2.amount_sum)
df043 = hcat(10:10:90, DataFrame(Matrix(table), :auto), makeunique=true)
rename!(df043, [:era, :male, :female, :unknown])
Row |
era |
male |
female |
unknown |
|
Int64 |
Int64 |
Int64 |
Int64 |
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 |
縦長フォーマット
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";
27×3 DataFrame
2 rows omitted
Row |
era |
variable |
value |
|
Int64 |
String |
Int64 |
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 |
⋮ |
⋮ |
⋮ |
⋮ |
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 |
# 別解
df2 |>
@rename(:variable => :gender_cd, :value => :amount) |>
@orderby(_.gender_cd) |>
@thenby(_.era) |>
# @filter(_.amount > 0) |>
DataFrame
27×3 DataFrame
2 rows omitted
Row |
era |
gender_cd |
amount |
|
Int64 |
String |
Int64 |
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 |
⋮ |
⋮ |
⋮ |
⋮ |
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件表示せよ。
first(df_customer[!, [:birth_day]], 10)
Row |
birth_day |
|
Date |
1 |
1981-04-29 |
2 |
1952-04-01 |
3 |
1976-10-04 |
4 |
1933-03-27 |
5 |
1995-03-29 |
6 |
1974-09-15 |
7 |
1977-08-09 |
8 |
1973-08-17 |
9 |
1931-05-02 |
10 |
1962-07-11 |
using Dates
df = df_customer[!, [:customer_id]]
df.birthday = Dates.format.(df_customer.birth_day, "yyyymmdd")
first(df, 10)
Row |
customer_id |
birthday |
|
String15 |
String |
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 |
# 別解
df_customer |>
@mutate(birthday=Dates.format(_.birth_day, "yyyymmdd")) |>
@select(:customer_id, :birthday) |>
@take(10) |>
DataFrame
Row |
customer_id |
birthday |
|
String15 |
String |
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 =df_customer[!, [:customer_id]]
str = df_customer.application_date
yyyy = [parse(Int, s[1:4]) for s in str];
mm = [parse(Int, s[5:6]) for s in str];
dd = [parse(Int, s[7:8]) for s in str];
df.application_date = Date.(yyyy, mm, dd)
first(df, 10)
Row |
customer_id |
application_date |
|
String15 |
Date |
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 |
# 別解
df_customer |>
@select(:customer_id, :application_date) |>
@mutate(yyyy = parse(Int, _.application_date[1:4]),
mm = parse(Int, _.application_date[5:6]),
dd = parse(Int, _.application_date[7:8])) |>
@mutate(application_date = Date(_.yyyy, _.mm, _.dd)) |>
@select(:customer_id, :application_date) |>
@take(10) |>
DataFrame
Row |
customer_id |
application_date |
|
String15 |
Date |
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 = df_receipt[!, [:receipt_no, :receipt_sub_no]]
yyyy = @. df_receipt.sales_ymd ÷ 10000;
mm = @. df_receipt.sales_ymd % 10000 ÷ 100;
dd = @. df_receipt.sales_ymd % 100;
df.sales_ymd = Date.(yyyy, mm, dd)
first(df, 10)
Row |
receipt_no |
receipt_sub_no |
sales_ymd |
|
Int64 |
Int64 |
Date |
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 |
# 別解
df_receipt |>
@select(:receipt_no, :receipt_sub_no, :sales_ymd) |>
@mutate(yyyy = _.sales_ymd ÷ 10000,
mm = _.sales_ymd % 10000 ÷ 100,
dd = _.sales_ymd % 100) |>
@mutate(salse_ymd = Date.(_.yyyy, _.mm, _.dd)) |>
@select(:receipt_no, :receipt_sub_no, :salse_ymd) |>
@take(10) |>
DataFrame
Row |
receipt_no |
receipt_sub_no |
salse_ymd |
|
Int64 |
Int64 |
Date |
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 = df_receipt[!, [:receipt_no, :receipt_sub_no]]
df.sales_ymd = Date.(unix2datetime.(df_receipt.sales_epoch))
first(df, 10)
Row |
receipt_no |
receipt_sub_no |
sales_ymd |
|
Int64 |
Int64 |
Date |
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 |
# 別解
df_receipt |>
@mutate(sales_ymd = Date(unix2datetime(_.sales_epoch))) |>
@select(:receipt_no, :receipt_sub_no, :sales_ymd) |>
@take(10) |>
DataFrame
Row |
receipt_no |
receipt_sub_no |
sales_ymd |
|
Int64 |
Int64 |
Date |
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 = df_receipt[!, [:receipt_no, :receipt_sub_no]]
df.salse_year = year.(unix2datetime.(df_receipt.sales_epoch))
first(df, 10)
Row |
receipt_no |
receipt_sub_no |
salse_year |
|
Int64 |
Int64 |
Int64 |
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 |
#別解
df_receipt |>
@mutate(salse_year = year(unix2datetime(_.sales_epoch))) |>
@select(:receipt_no, :receipt_sub_no, :salse_year) |>
@take(10) |>
DataFrame
Row |
receipt_no |
receipt_sub_no |
salse_year |
|
Int64 |
Int64 |
Int64 |
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 = df_receipt[!, [:receipt_no, :receipt_sub_no]]
df.salse_month = @. string(month(unix2datetime(df_receipt.sales_epoch)), pad=2)
first(df, 10)
Row |
receipt_no |
receipt_sub_no |
salse_month |
|
Int64 |
Int64 |
String |
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 |
# 別解
df_receipt |>
@mutate(salse_month = string(month(unix2datetime(_.sales_epoch)), pad=2)) |>
@select(:receipt_no, :receipt_sub_no, :salse_month) |>
@take(10) |>
DataFrame
Row |
receipt_no |
receipt_sub_no |
salse_month |
|
Int64 |
Int64 |
String |
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 = df_receipt[!, [:receipt_no, :receipt_sub_no]]
df.salse_day = @. string(day(unix2datetime(df_receipt.sales_epoch)), pad=2)
first(df, 10)
Row |
receipt_no |
receipt_sub_no |
salse_day |
|
Int64 |
Int64 |
String |
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 |
# 別解
df_receipt |>
@mutate(salse_day = string(day(unix2datetime(_.sales_epoch)), pad=2)) |>
@select(:receipt_no, :receipt_sub_no, :salse_day) |>
@take(10) |>
DataFrame
Row |
receipt_no |
receipt_sub_no |
salse_day |
|
Int64 |
Int64 |
String |
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"から始まるのものは非会員を表すため、除外して計算すること。
gd = groupby(filter(:customer_id => x -> !occursin(r"^Z", x), df_receipt), :customer_id)
df2 = combine(gd, :amount => sum => :sum_amount)
df2.salse_flg = (df2.sum_amount .> 2000) .+ 0
df3 = sort(df2, :customer_id)
first(df3, 10)
Row |
customer_id |
sum_amount |
salse_flg |
|
String15 |
Int64 |
Int64 |
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 |
# 別解
df_receipt |>
@filter(!occursin(r"^Z", _.customer_id)) |>
@groupby(_.customer_id) |>
@map({customer_id = key(_), sum_amount = sum(_.amount)}) |>
@mutate(salse_flg = (_.sum_amount > 2000) + 0) |>
@orderby(_.customer_id) |>
@take(10) |>
DataFrame
Row |
customer_id |
sum_amount |
salse_flg |
|
String15 |
Int64 |
Int64 |
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)と結合し、全期間において売上実績のある顧客数を、作成した二値ごとにカウントせよ。
df2 = df_customer[!, [:customer_id, :postal_cd]]
df2.postal_flg = @. (100 <= parse(Int, SubString(df2.postal_cd, 1, 3)) <= 209) + 0
df3 = unique(innerjoin(df2, df_receipt[!, [:customer_id]], on=:customer_id))
combine(groupby(df3, :postal_flg), nrow)
Row |
postal_flg |
nrow |
|
Int64 |
Int64 |
1 |
0 |
3906 |
2 |
1 |
4400 |
# 別解
using StatsBase
df2 = df_customer[!, [:customer_id, :postal_cd]] |>
@mutate(postal_flg = (100 <= parse(Int, SubString(_.postal_cd, 1, 3)) <= 209) + 0) |>
DataFrame;
df3 = innerjoin(df2, df_receipt[!, [:customer_id]], on=:customer_id) |>
@unique() |>
@groupby(_.postal_flg) |>
@map({postal_flg = key(_), nrow = length(_.postal_flg)}) |>
DataFrame
Row |
postal_flg |
nrow |
|
Int64 |
Int64 |
1 |
0 |
3906 |
2 |
1 |
4400 |
J-054: 顧客データ(df_customer)の住所(address)は、埼玉県、千葉県、東京都、神奈川県のいずれかとなっている。都道府県毎にコード値を作成し、顧客ID、住所とともに10件表示せよ。値は埼玉県を11、千葉県を12、東京都を13、神奈川県を14とすること。
df = df_customer[!, [:customer_id, :address]]
df.prefecture_cd = [indexin(s[1], ['埼', '千', '東', '神'])[1]+10 for s in df.address];
first(df, 10)
Row |
customer_id |
address |
prefecture_cd |
|
String15 |
String |
Int64 |
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 |
# 別解
df_customer[!, [:customer_id, :address]] |>
@mutate(prefecture_cd = occursin(r"^東京都", _.address) ? 13 :
(occursin(r"^千葉県", _.address) ? 12 :
(occursin(r"^埼玉県", _.address) ? 11 : 14))) |>
@take(10) |>
DataFrame
Row |
customer_id |
address |
prefecture_cd |
|
String15 |
String |
Int64 |
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を付与
function encode(df)
for x in df
x < Q[1] && return 1
x < Q[2] && return 2
x < Q[3] && return 3
return 4
end
end
using StatsBase
gd = groupby(df_receipt[:, [:amount, :customer_id]], :customer_id)
df = combine(gd, :amount => sum);
Q = quantile(df.amount_sum, [0.25, 0.50, 0.75]);
df.pct_group = encode.(df.amount_sum);
df2 = sort(df, :customer_id)
first(df2, 10)
Row |
customer_id |
amount_sum |
pct_group |
|
String15 |
Int64 |
Int64 |
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 |
3-element Vector{Float64}:
548.5
1478.0
3651.0
# 別解
using StatsBase
gd = groupby(df_receipt[:, [:amount, :customer_id]], :customer_id)
df = combine(gd, :amount => sum);
Q = quantile(df.amount_sum, [0.25, 0.50, 0.75]);
df2 = df |>
@mutate(pct_group = _.amount_sum .< Q[1] ? 1 :
(_.amount_sum .< Q[2] ? 2 :
(_.amount_sum .< Q[3] ? 3 : 4))) |>
@orderby(_.customer_id) |>
DataFrame
first(df2, 10)
Row |
customer_id |
amount_sum |
pct_group |
|
String15 |
Int64 |
Int64 |
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 = df_customer[!, [:customer_id, :birth_day, :age]]
df.era = @. min((df.age ÷ 10)*10, 60)
first(df, 10)
Row |
customer_id |
birth_day |
age |
era |
|
String15 |
Date |
Int64 |
Int64 |
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 |
# 別解
df_customer[!, [:customer_id, :birth_day, :age]] |>
@mutate(era = min((_.age ÷ 10)*10, 60)) |>
@take(10) |>
DataFrame
Row |
customer_id |
birth_day |
age |
era |
|
String15 |
Date |
Int64 |
Int64 |
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 = df_customer[!, [:customer_id, :gender_cd, :birth_day, :age]]
df.era = @. min((df.age ÷ 10)*10, 60)
df.gender_era = @. string(df.gender_cd) * string(df.era)
first(df, 10)
Row |
customer_id |
gender_cd |
birth_day |
age |
era |
gender_era |
|
String15 |
String |
Date |
Int64 |
Int64 |
String |
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 |
# 別解
df_customer[!, [:customer_id, :gender_cd, :birth_day, :age]] |>
@mutate(era = min((_.age ÷ 10)*10, 60)) |>
@mutate(gender_era = string(_.gender_cd) * string(_.era)) |>
@take(10) |>
DataFrame
Row |
customer_id |
gender_cd |
birth_day |
age |
era |
gender_era |
|
String15 |
String |
Date |
Int64 |
Int64 |
String |
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])
first(df, 10)
Row |
customer_id |
gender_cd0 |
gender_cd1 |
gender_cd9 |
|
String15 |
Int64 |
Int64 |
Int64 |
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 = df_customer[!, [:customer_id]]
df.gender_cd0 = @. (df_customer.gender_cd == "0") + 0
df.gender_cd1 = @. (df_customer.gender_cd == "1") + 0
df.gender_cd9 = @. (df_customer.gender_cd == "9") + 0
first(df, 10)
Row |
customer_id |
gender_cd0 |
gender_cd1 |
gender_cd9 |
|
String15 |
Int64 |
Int64 |
Int64 |
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_customer[!, [:customer_id, :gender_cd]] |>
@mutate(gender_cd0 = (_.gender_cd == "0") + 0,
gender_cd1 = (_.gender_cd == "1") + 0,
gender_cd9 = (_.gender_cd == "9") + 0)|>
@select(-:gender_cd) |>
@take(10) |>
DataFrame
Row |
customer_id |
gender_cd0 |
gender_cd1 |
gender_cd9 |
|
String15 |
Int64 |
Int64 |
Int64 |
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()内で使えません。
gd = groupby(filter(:customer_id => x -> !occursin(r"^Z", x), df_receipt), :customer_id)
df = combine(gd, :amount => sum => :sum_amount)
df.standardized_amount = (df.sum_amount .- mean(df.sum_amount)) ./ std(df.sum_amount)
df2 = sort(df, :customer_id)
first(df2, 10)
Row |
customer_id |
sum_amount |
standardized_amount |
|
String15 |
Int64 |
Float64 |
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 |
# 別解
df2 = df_receipt[!, [:customer_id, :amount]] |>
@filter(!occursin(r"^Z", _.customer_id)) |>
DataFrame;
gd = groupby(df2, :customer_id)
df3 = combine(gd, :amount => sum => :sum_amount) |>
@orderby(_.customer_id) |>
DataFrame
using StatsBase
mean_amount = mean(df3.sum_amount)
std_amount = std(df3.sum_amount);
df3 |>
@mutate(standardized_amount = (_.sum_amount - mean_amount) / std_amount) |>
@take(10) |>
DataFrame
Row |
customer_id |
sum_amount |
standardized_amount |
|
Any |
Any |
Any |
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 |
df2 を作ってからは,以下のように freqtables() を使うほうが簡単でわかりやすい。
using FreqTables
a = freqtable(df2.customer_id, weights=df2.amount)
(mean_amount, std_amount) = (mean(a), std(a))
DataFrame(customer_id=names(a)[1], sum_amount=a) |>
@mutate(standardized_amount = (_.sum_amount - mean_amount) / std_amount) |>
@take(10) |>
DataFrame
Row |
customer_id |
sum_amount |
standardized_amount |
|
Any |
Any |
Any |
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"から始まるのものは非会員を表すため、除外して計算すること。
gd = groupby(filter(:customer_id => x -> !occursin(r"^Z", x), df_receipt), :customer_id)
df = combine(gd, :amount => sum => :sum_amount)
df.standardized_amount = (df.sum_amount .- minimum(df.sum_amount)) ./ (maximum(df.sum_amount) - minimum(df.sum_amount))
df2 = sort(df, :customer_id)
first(df2, 10)
Row |
customer_id |
sum_amount |
standardized_amount |
|
String15 |
Int64 |
Float64 |
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 |
# 別解
df2 = df_receipt[!, [:customer_id, :amount]] |>
@filter(!occursin(r"^Z", _.customer_id)) |>
DataFrame;
using FreqTables
a = freqtable(df2.customer_id, weights=df2.amount)
(min_amount, max_amount) = (minimum(a), maximum(a))
DataFrame(customer_id=names(a)[1], sum_amount=a) |>
@mutate(scaled_amount = (_.sum_amount - min_amount) / (max_amount - min_amount)) |>
@take(10) |>
DataFrame
Row |
customer_id |
sum_amount |
scaled_amount |
|
Any |
Any |
Any |
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"から始まるのものは非会員を表すため、除外して計算すること。
gd = groupby(filter(:customer_id => x -> !occursin(r"^Z", x), df_receipt), :customer_id)
df = combine(gd, :amount => sum => :sum_amount)
df.log_amount = log10.(df.sum_amount)
df2 = sort(df, :customer_id)
first(df2, 10)
Row |
customer_id |
sum_amount |
log_amount |
|
String15 |
Int64 |
Float64 |
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 |
# 別解
df2 = df_receipt[!, [:customer_id, :amount]] |>
@filter(!occursin(r"^Z", _.customer_id)) |>
DataFrame;
using FreqTables
a = freqtable(df2.customer_id, weights=df2.amount)
(min_amount, max_amount) = (minimum(a), maximum(a))
DataFrame(customer_id=names(a)[1], sum_amount=a) |>
@mutate(log_amount = log10(_.sum_amount)) |>
@take(10) |>
DataFrame
Row |
customer_id |
sum_amount |
log_amount |
|
String15 |
Int64 |
Float64 |
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"から始まるのものは非会員を表すため、除外して計算すること。
gd = groupby(filter(:customer_id => x -> !occursin(r"^Z", x), df_receipt), :customer_id)
df = combine(gd, :amount => sum => :sum_amount)
df.log_amount = log.(df.sum_amount)
df2 = sort(df, :customer_id)
first(df2, 10)
Row |
customer_id |
sum_amount |
log_amount |
|
String15 |
Int64 |
Float64 |
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 |
# 別解
df2 = df_receipt[!, [:customer_id, :amount]] |>
@filter(!occursin(r"^Z", _.customer_id)) |>
DataFrame;
using FreqTables
a = freqtable(df2.customer_id, weights=df2.amount)
(min_amount, max_amount) = (minimum(a), maximum(a))
DataFrame(customer_id=names(a)[1], sum_amount=a) |>
@mutate(log_amount = log(_.sum_amount)) |>
@take(10) |>
DataFrame
Row |
customer_id |
sum_amount |
log_amount |
|
String15 |
Int64 |
Float64 |
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 = copy(df_product) # copy() しないと,元のデータフレームが編集される
df.unit_profit = df.unit_price - df.unit_cost
first(df, 10)
Row |
product_cd |
category_major_cd |
category_medium_cd |
category_small_cd |
unit_price |
unit_cost |
unit_profit |
|
String15 |
String |
String |
String |
Int64? |
Int64? |
Int64? |
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 |
# 別解
df_product |>
@mutate(unit_profit = _.unit_price - _.unit_cost) |>
@take(10) |>
DataFrame
Row |
product_cd |
category_major_cd |
category_medium_cd |
category_small_cd |
unit_price |
unit_cost |
unit_profit |
|
String15 |
String |
String |
String |
Int64? |
Int64? |
Int64? |
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))
# 別解
df = df_product |>
@mutate(unit_profit_rate = 1 - _.unit_cost / _.unit_price) |>
DataFrame;
mean(skipmissing(df.unit_profit_rate))
# 別解2
df = df_product |>
@mutate(unit_profit_rate = 1 - _.unit_cost / _.unit_price) |>
@dropna(:unit_profit_rate) |>
DataFrame;
mean(df.unit_profit_rate)
J-065: 商品データ(df_product)の各商品について、利益率が30%となる新たな単価を求めよ。ただし、1円未満は切り捨てること。そして結果を10件表示させ、利益率がおよそ30%付近であることを確認せよ。ただし、単価(unit_price)と原価(unit_cost)には欠損が生じていることに注意せよ。
df = dropmissing(df_product[!, [:product_cd, :unit_price, :unit_cost]])
df.new_price = @. trunc(Int, df.unit_cost / 0.7)
df.new_profit_rate = @. 1 - df.unit_cost / df.new_price
first(df, 10)
Row |
product_cd |
unit_price |
unit_cost |
new_price |
new_profit_rate |
|
String15 |
Int64 |
Int64 |
Int64 |
Float64 |
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 |
# 別解
df_product[!, [:product_cd, :unit_price, :unit_cost]] |>
@dropna() |>
@mutate(new_price = trunc(Int, _.unit_cost / 0.7)) |>
@mutate(new_profit_rate = 1 - _.unit_cost / _.new_price) |>
@take(10) |>
DataFrame
Row |
product_cd |
unit_price |
unit_cost |
new_price |
new_profit_rate |
|
String15 |
Int64 |
Int64 |
Int64 |
Float64 |
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 = dropmissing(df_product[!, [:product_cd, :unit_price, :unit_cost]])
df.new_price = @. round(Int, df.unit_cost / 0.7)
df.new_profit_rate = @. 1 - df.unit_cost / df.new_price
first(df, 10)
Row |
product_cd |
unit_price |
unit_cost |
new_price |
new_profit_rate |
|
String15 |
Int64 |
Int64 |
Int64 |
Float64 |
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 |
# 別解
df_product[!, [:product_cd, :unit_price, :unit_cost]] |>
@dropna() |>
@mutate(new_price = round(Int, _.unit_cost / 0.7)) |>
@mutate(new_profit_rate = 1 - _.unit_cost / _.new_price) |>
@take(10) |>
DataFrame
Row |
product_cd |
unit_price |
unit_cost |
new_price |
new_profit_rate |
|
String15 |
Int64 |
Int64 |
Int64 |
Float64 |
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 = dropmissing(df_product[!, [:product_cd, :unit_price, :unit_cost]])
df.new_price = @. ceil(Int, df.unit_cost / 0.7)
df.new_profit_rate = @. 1 - df.unit_cost / df.new_price
first(df, 10)
Row |
product_cd |
unit_price |
unit_cost |
new_price |
new_profit_rate |
|
String15 |
Int64 |
Int64 |
Int64 |
Float64 |
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 |
df_product[!, [:product_cd, :unit_price, :unit_cost]] |>
@dropna() |>
@mutate(new_price = ceil(Int, _.unit_cost / 0.7)) |>
@mutate(new_profit_rate = 1 - _.unit_cost / _.new_price) |>
@take(10) |>
DataFrame
Row |
product_cd |
unit_price |
unit_cost |
new_price |
new_profit_rate |
|
String15 |
Int64 |
Int64 |
Int64 |
Float64 |
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 = dropmissing(df_product[!, [:product_cd, :unit_price]])
df.tax_price = @. trunc(Int, df.unit_price * 1.1)
first(df, 10)
Row |
product_cd |
unit_price |
tax_price |
|
String15 |
Int64 |
Int64 |
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 |
# 別解
df_product[!, [:product_cd, :unit_price]] |>
@dropna() |>
@mutate(tax_price = trunc(Int, _.unit_price * 1.1)) |>
@take(10) |>
DataFrame
Row |
product_cd |
unit_price |
tax_price |
|
String15 |
Int64 |
Int64 |
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, makeunique=true)
df1 = combine(groupby(df, :customer_id), :amount => sum => :sum_all)
filter!(:category_major_cd => x -> x == "07", df)
df2 = combine(groupby(df, :customer_id), :amount => sum => :sum_07)
df3 = innerjoin(df1, df2, on=:customer_id)
df3.sales_rate = df3.sum_07 ./ df3.sum_all
sort!(df3, :customer_id)
first(df3, 10)
Row |
customer_id |
sum_all |
sum_07 |
sales_rate |
|
String15 |
Int64 |
Int64 |
Float64 |
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 |
# 別解
df1 = df_receipt |>
@select(:customer_id, :product_cd, :amount) |> DataFrame;
df2 = df_product |>
@select(:category_major_cd, :product_cd) |> DataFrame;
df3 = df1 |>
@join(df2, _.product_cd, _.product_cd, {_.customer_id, _.amount, __.category_major_cd}) |>
DataFrame;
df4 = df3 |>
@groupby(_.customer_id) |>
@map({customer_id = key(_), sum_all = sum(_.amount)}) |>
DataFrame;
df5 = df3 |>
@filter(_.category_major_cd == "07") |>
@groupby(_.customer_id) |>
@map({customer_id = key(_), sum_07 = sum(_.amount)}) |>
DataFrame;
df4 |>
@join(df5, _.customer_id, _.customer_id, {_.customer_id, _.sum_all, __.sum_07}) |>
@mutate(sales_rate = _.sum_07 / _.sum_all) |>
@orderby(_.customer_id) |>
@take(10) |> DataFrame
Row |
customer_id |
sum_all |
sum_07 |
sales_rate |
|
String15 |
Int64 |
Int64 |
Float64 |
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 = innerjoin(df_receipt[!, [:customer_id, :sales_ymd]],
df_customer[!, [:customer_id, :application_date]],
on=:customer_id);
df.elapsed_days = @. Dates.value(date(df.sales_ymd) - date(parse(Int, df.application_date)))
first(df, 10)
Row |
customer_id |
sales_ymd |
application_date |
elapsed_days |
|
String15 |
Int64 |
String |
Int64 |
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 |
# 別解
using Dates
date(d) = @. Date(d ÷ 10000, (d % 10000) ÷ 100, d % 100)
df_receipt |>
@join(df_customer, _.customer_id, _.customer_id, {_.customer_id, _.sales_ymd, __.application_date}) |>
@mutate(elapsed_days = Dates.value(date(_.sales_ymd) - date(parse(Int, _.application_date)))) |>
@take(10) |> DataFrame
Row |
customer_id |
sales_ymd |
application_date |
elapsed_days |
|
String15 |
Int64 |
String |
Int64 |
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 = innerjoin(df_receipt[!, [:customer_id, :sales_ymd]],
df_customer[!, [:customer_id, :application_date]],
on=:customer_id);
df.elapsed_months = date3.(df.application_date, df.sales_ymd)
first(df, 10)
Row |
customer_id |
sales_ymd |
application_date |
elapsed_months |
|
String15 |
Int64 |
String |
Int64 |
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 |
# 別解
df_receipt |>
@join(df_customer, _.customer_id, _.customer_id, {_.customer_id, _.sales_ymd, __.application_date}) |>
@mutate(elapsed_months = date3( _.application_date, _.sales_ymd)) |>
@take(10) |>
DataFrame
Row |
customer_id |
sales_ymd |
application_date |
elapsed_months |
|
String15 |
Int64 |
String |
Int64 |
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 = innerjoin(df_receipt[!, [:customer_id, :sales_ymd]],
df_customer[!, [:customer_id, :application_date]],
on=:customer_id)
df.elapsed_years = year2(parse.(Int, df.application_date), df.sales_ymd)
first(df, 10)
Row |
customer_id |
sales_ymd |
application_date |
elapsed_years |
|
String15 |
Int64 |
String |
Int64 |
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 |
# 別解
year2(ymd, ymd2) = (ymd2 - ymd) ÷ 10000
df_receipt |>
@join(df_customer, _.customer_id, _.customer_id, {_.customer_id, _.sales_ymd, __.application_date}) |>
@mutate(elapsed_years = year2(parse(Int, _.application_date), _.sales_ymd)) |>
@take(10) |>
DataFrame
Row |
customer_id |
sales_ymd |
application_date |
elapsed_years |
|
String15 |
Int64 |
String |
Int64 |
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 = innerjoin(df_receipt[!, [:customer_id, :sales_ymd]],
df_customer[!, [:customer_id, :application_date]],
on=:customer_id)
df.elapsed_epoch = convert.(Int64, Dates.value.(datetime.(df.sales_ymd) - datetime.(parse.(Int, df.application_date)))/1000)
first(df, 10)
Row |
customer_id |
sales_ymd |
application_date |
elapsed_epoch |
|
String15 |
Int64 |
String |
Int64 |
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 |
# 別解
datetime(d) = DateTime(d ÷ 10000, (d % 10000) ÷ 100, d % 100, 0, 0, 0)
df_receipt |>
@join(df_customer, _.customer_id, _.customer_id, {_.customer_id, _.sales_ymd, __.application_date}) |>
@mutate(elapsed_epoch = convert(Int64, Dates.value(datetime(_.sales_ymd) .- datetime(parse(Int, _.application_date)))/1000)) |>
@take(10) |>
DataFrame
Row |
customer_id |
sales_ymd |
application_date |
elapsed_epoch |
|
String15 |
Int64 |
String |
Int64 |
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 = copy(df_receipt) # または,df = df_receipt[!, [:sales_ymd]]
df.monday = firstdayofweek.(date.(df.sales_ymd))
df.elapsed_days = Dates.value.(date.(df.sales_ymd) - df.monday)
df = select(df, [:sales_ymd, :elapsed_days, :monday])
first(df, 10)
Row |
sales_ymd |
elapsed_days |
monday |
|
Int64 |
Int64 |
Date |
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 |
# 別解
using Dates
date(d) = Date(d ÷ 10000, (d % 10000) ÷ 100, d % 100)
df_receipt |>
#@select(:sales_ymd) |>
@mutate(monday = firstdayofweek(date(_.sales_ymd))) |>
@mutate(elapsed_days = Dates.value(date(_.sales_ymd) - _.monday)) |>
@select(:sales_ymd, :elapsed_days, :monday) |>
@take(10) |>
DataFrame
Row |
sales_ymd |
elapsed_days |
monday |
|
Int64 |
Int64 |
Date |
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), :]
first(df, 10)
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
1 |
CS001313000265 |
竹村 遥 |
1 |
女性 |
1984-04-13 |
34 |
144-0035 |
東京都大田区南蒲田********** |
S13001 |
20160624 |
0-00000000-0 |
2 |
CS001415000572 |
田口 ヒカル |
1 |
女性 |
1977-07-31 |
41 |
144-0056 |
東京都大田区西六郷********** |
S13001 |
20170413 |
8-20100925-7 |
3 |
CS013313000160 |
大塚 遥 |
9 |
不明 |
1980-09-28 |
38 |
275-0022 |
千葉県習志野市香澄********** |
S12013 |
20150117 |
0-00000000-0 |
4 |
CS017412000008 |
ほしの 菜摘 |
1 |
女性 |
1971-12-18 |
47 |
166-0004 |
東京都杉並区阿佐谷南********** |
S13017 |
20150907 |
3-20080225-3 |
5 |
CS022403000040 |
佐川 憲史 |
0 |
男性 |
1969-09-25 |
49 |
240-0113 |
神奈川県三浦郡葉山町長柄********** |
S14022 |
20150804 |
0-00000000-0 |
6 |
CS001713000040 |
村山 遥 |
1 |
女性 |
1939-12-10 |
79 |
144-0045 |
東京都大田区南六郷********** |
S13001 |
20150323 |
0-00000000-0 |
7 |
CS023602000043 |
戸田 和之 |
0 |
男性 |
1949-01-31 |
70 |
212-0054 |
神奈川県川崎市幸区小倉********** |
S14023 |
20170114 |
0-00000000-0 |
8 |
CS003615000329 |
おかやま 貴美子 |
1 |
女性 |
1956-10-15 |
62 |
201-0001 |
東京都狛江市西野川********** |
S13003 |
20170405 |
0-00000000-0 |
9 |
CS038615000053 |
門脇 優 |
1 |
女性 |
1951-01-03 |
68 |
279-0041 |
千葉県浦安市堀江********** |
S13038 |
20150522 |
4-20090601-5 |
10 |
CS039413000205 |
野田 季衣 |
1 |
女性 |
1975-02-18 |
44 |
167-0032 |
東京都杉並区天沼********** |
S13039 |
20150412 |
1-20090216-4 |
以下の方法は,各行に [0,1) の一様乱数を与え,その値が希望する抽出率の数値未満の行を抽出するというものである。実際に抽出される件数が若干の幅を持つが,実用上の問題はないであろう。
# 別解
using StatsBase
df = df_customer |>
@mutate(uniformrandom=rand(1)[1]) |>
@filter(_.uniformrandom < 0.01) |>
@select(-:uniformrandom) |> # 乱数列は用済みなので削除
DataFrame
println("df_customer の件数 = $(nrow(df_customer)), 抽出された件数 = $(nrow(df)), 抽出率 = $(100nrow(df)/nrow(df_customer)) %")
first(df, 10)
df_customer の件数 = 21971, 抽出された件数 = 216, 抽出率 = 0.9831141049565336 %
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
1 |
CS011215000048 |
芦田 沙耶 |
1 |
女性 |
1992-02-01 |
27 |
223-0062 |
神奈川県横浜市港北区日吉本町********** |
S14011 |
20150228 |
C-20100421-9 |
2 |
CS031415000106 |
宇野 由美子 |
1 |
女性 |
1970-02-26 |
49 |
151-0053 |
東京都渋谷区代々木********** |
S13031 |
20150201 |
F-20100511-E |
3 |
CS029313000221 |
北条 ひかり |
1 |
女性 |
1987-06-19 |
31 |
279-0011 |
千葉県浦安市美浜********** |
S12029 |
20180810 |
0-00000000-0 |
4 |
CS013613000043 |
大森 瞳 |
1 |
女性 |
1956-04-28 |
62 |
261-0025 |
千葉県千葉市美浜区浜田********** |
S12013 |
20150222 |
0-00000000-0 |
5 |
CS006803000002 |
堀 獅童 |
0 |
男性 |
1930-01-21 |
89 |
224-0057 |
神奈川県横浜市都筑区川和町********** |
S14006 |
20150927 |
0-00000000-0 |
6 |
CS031514000047 |
原口 礼子 |
1 |
女性 |
1963-07-26 |
55 |
151-0064 |
東京都渋谷区上原********** |
S13031 |
20150927 |
8-20090607-6 |
7 |
CS025713000029 |
大塚 怜奈 |
1 |
女性 |
1942-07-31 |
76 |
242-0015 |
神奈川県大和市下和田********** |
S14025 |
20151005 |
0-00000000-0 |
8 |
CS037704000007 |
吹越 菊生 |
0 |
男性 |
1943-01-11 |
76 |
136-0076 |
東京都江東区南砂********** |
S13037 |
20150329 |
0-00000000-0 |
9 |
CS002215000165 |
田村 美幸 |
1 |
女性 |
1991-01-16 |
28 |
185-0014 |
東京都国分寺市東恋ケ窪********** |
S13002 |
20170728 |
5-20100122-1 |
10 |
CS007415000047 |
土屋 瞬 |
1 |
女性 |
1973-06-25 |
45 |
285-0855 |
千葉県佐倉市井野********** |
S12007 |
20141122 |
0-00000000-0 |
層化抽出
J-076: 顧客データ(df_customer)から性別コード(gender_cd)の割合に基づきランダムに10%のデータを層化抽出し、性別コードごとに件数を集計せよ。
combine(groupby(df_customer, :gender_cd), nrow => :customer_num)
Row |
gender_cd |
customer_num |
|
String |
Int64 |
1 |
1 |
17918 |
2 |
9 |
1072 |
3 |
0 |
2981 |
function sampling(df)
n = nrow(df)
return df[sample(1:n, floor(Int, n*0.01), 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 |
179 |
2 |
9 |
10 |
3 |
0 |
29 |
データフレームをグループ化し,それぞれのデータフレームに対して一定の処理を行い,再度一つのデータフレームにまとめるという作業は以下のようにすれば簡単になる。
# 別解
gd = groupby(df_customer, :gender_cd) # グループ化
df = [sampling(df) for df in gd] # 処理(関数内で行う)
df2 = vcat(df...) # 再度一つのデータフレームにまとめる
first(df2, 10)
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
1 |
CS019415000255 |
寺西 綾 |
1 |
女性 |
1975-09-24 |
43 |
173-0036 |
東京都板橋区向原********** |
S13019 |
20150515 |
D-20100409-E |
2 |
CS022412000091 |
溝口 早紀 |
1 |
女性 |
1972-03-29 |
47 |
240-0112 |
神奈川県三浦郡葉山町堀内********** |
S14022 |
20150531 |
0-00000000-0 |
3 |
CS033513000001 |
斉藤 美帆 |
1 |
女性 |
1964-06-18 |
54 |
246-0037 |
神奈川県横浜市瀬谷区橋戸********** |
S14033 |
20150918 |
9-20090809-6 |
4 |
CS004515000228 |
吉村 南朋 |
1 |
女性 |
1961-05-15 |
57 |
167-0022 |
東京都杉並区下井草********** |
S13004 |
20150214 |
0-00000000-0 |
5 |
CS035212000033 |
上村 あさみ |
1 |
女性 |
1993-09-25 |
25 |
157-0068 |
東京都世田谷区宇奈根********** |
S13035 |
20150415 |
5-20100905-6 |
6 |
CS001312000231 |
西脇 京子 |
1 |
女性 |
1985-10-18 |
33 |
210-0021 |
神奈川県川崎市川崎区元木********** |
S13001 |
20160324 |
0-00000000-0 |
7 |
CS022715000051 |
黒谷 景子 |
1 |
女性 |
1941-07-16 |
77 |
249-0005 |
神奈川県逗子市桜山********** |
S14022 |
20150608 |
0-00000000-0 |
8 |
CS024312000022 |
三輪 瞳 |
1 |
女性 |
1981-02-13 |
38 |
216-0015 |
神奈川県川崎市宮前区菅生********** |
S14024 |
20150924 |
0-00000000-0 |
9 |
CS001211000024 |
島津 一恵 |
1 |
女性 |
1992-02-06 |
27 |
212-0058 |
神奈川県川崎市幸区鹿島田********** |
S13001 |
20160421 |
0-00000000-0 |
10 |
CS027315000113 |
武藤 美佐 |
1 |
女性 |
1987-05-12 |
31 |
251-0016 |
神奈川県藤沢市弥勒寺********** |
S14027 |
20150626 |
0-00000000-0 |
外れ値
J-077: レシート明細データ(df_receipt)の売上金額を顧客単位に合計し、合計した売上金額の外れ値を抽出せよ。なお、外れ値は売上金額合計を対数化したうえで平均と標準偏差を計算し、その平均から3σを超えて離れたものとする(自然対数と常用対数のどちらでも可)。結果は10件表示せよ。
gd = groupby(df_receipt, :customer_id)
df = combine(gd, :amount => sum => :sum_amount, :amount => (x -> log(sum(x))) => :log_sum_amount);
using StatsBase
m = mean(df.log_sum_amount)
s = std(df.log_sum_amount)
df2 = df[abs.(df.log_sum_amount .- m) ./ s .> 3, :]
first(df2, 10)
Row |
customer_id |
sum_amount |
log_sum_amount |
|
String15 |
Int64 |
Float64 |
1 |
ZZ000000000000 |
12395003 |
16.3328 |
# 別解
df = df_receipt |>
@groupby(_.customer_id) |>
@map({customer_id=key(_), sum_amount=sum(_.amount), log_sum_amount=log(sum(_.amount))}) |>
DataFrame
using StatsBase
m = mean(df.log_sum_amount)
s = std(df.log_sum_amount)
df2 = df |>
@filter(abs(_.log_sum_amount - m) / s > 3) |>
@take(10) |>
DataFrame
Row |
customer_id |
sum_amount |
log_sum_amount |
|
String15 |
Int64 |
Float64 |
1 |
ZZ000000000000 |
12395003 |
16.3328 |
J-078: レシート明細データ(df_receipt)の売上金額(amount)を顧客単位に合計し、合計した売上金額の外れ値を抽出せよ。ただし、顧客IDが"Z"から始まるのものは非会員を表すため、除外して計算すること。なお、ここでは外れ値を第1四分位と第3四分位の差であるIQRを用いて、「第1四分位数-1.5×IQR」を下回るもの、または「第3四分位数+1.5×IQR」を超えるものとする。結果は10件表示せよ。
gd = groupby(filter(:customer_id => x -> !occursin(r"^Z", x), df_receipt), :customer_id)
df = combine(gd, :amount => sum => :sum_amount)
using StatsBase
(qt1, qt3) = quantile(df.sum_amount, [0.25, 0.75])
IQR = qt3 - qt1
df2 = df[df.sum_amount .< qt1 - 1.5*IQR .|| df.sum_amount .> qt3 + 1.5*IQR, :]
sort!(df2, :customer_id)
first(df2, 10)
Row |
customer_id |
sum_amount |
|
String15 |
Int64 |
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 |
# 別解
df = df_receipt[!, [:customer_id, :amount]] |>
@filter(!occursin(r"^Z", _.customer_id)) |>
@groupby(_.customer_id) |>
@map({customer_id=key(_), sum_amount=sum(_.amount)}) |>
DataFrame
using StatsBase
(qt1, qt3) = quantile(df2.sum_amount, [0.25, 0.75])
IQR = qt3 - qt1
df |>
@filter(_.sum_amount < qt1 - 1.5*IQR || _.sum_amount > qt3 + 1.5*IQR) |>
@orderby(_.customer_id) |>
@take(10) |>
DataFrame
Row |
customer_id |
sum_amount |
|
String15 |
Int64 |
1 |
CS001113000004 |
1298 |
2 |
CS001114000005 |
626 |
3 |
CS001115000010 |
3044 |
4 |
CS001205000004 |
1988 |
5 |
CS001205000006 |
3337 |
6 |
CS001211000025 |
456 |
7 |
CS001212000027 |
448 |
8 |
CS001212000031 |
296 |
9 |
CS001212000046 |
228 |
10 |
CS001212000070 |
456 |
欠損値の補完
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")
df = copy(df_product)
println(df[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
println("nrow = $(nrow(df))")
df.unit_price = coalesce.(df.unit_price, price_mean)
df.unit_cost = coalesce.(df.unit_cost, cost_mean)
println(df[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
println("nrow = $(nrow(df))")
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 │ P040802007 04 0408 040802 [90m missing [0m[90m missing [0m
3 │ P050103021 05 0501 050103 [90m missing [0m[90m missing [0m
4 │ P050405009 05 0504 050405 [90m missing [0m[90m missing [0m
5 │ P060802026 06 0608 060802 [90m missing [0m[90m missing [0m
6 │ P070202092 07 0702 070202 [90m missing [0m[90m missing [0m
7 │ P080504027 08 0805 080504 [90m missing [0m[90m missing [0m
8 │ P090204185 09 0902 090204 [90m missing [0m[90m missing [0m
nrow = 10030
[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
# 別解
using StatsBase
price_mean = round(Int, mean(skipmissing(df_product.unit_price)))
cost_mean = round(Int, mean(skipmissing(df_product.unit_cost)))
println(df_product[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
println("nrow = $(nrow(df))")
df = df_product |>
# @replacena(:unit_price => price_mean, :unit_cost => cost_mean) |> エラーになる。変数名は指定できない
@replacena(:unit_price => 9999999999, :unit_cost => 9999999999) |>
@mutate(unit_price = _.unit_price == 9999999999 ? price_mean : _.unit_price,
unit_cost = _.unit_cost == 9999999999 ? cost_mean : _.unit_cost) |>
DataFrame
println("nrow = $(nrow(df))")
println(df[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
[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 [90m missing [0m[90m missing [0m
3 │ P050103021 05 0501 050103 [90m missing [0m[90m missing [0m
4 │ P050405009 05 0504 050405 [90m missing [0m[90m missing [0m
5 │ P060802026 06 0608 060802 [90m missing [0m[90m missing [0m
6 │ P070202092 07 0702 070202 [90m missing [0m[90m missing [0m
7 │ P080504027 08 0805 080504 [90m missing [0m[90m missing [0m
8 │ P090204185 09 0902 090204 [90m missing [0m[90m missing [0m
nrow = 10030
nrow = 10030
[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 Any [0m[90m Any [0m[90m Any [0m[90m Any [0m[90m Any [0m[90m Any [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
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")
df = copy(df_product)
println(df[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
println("nrow = $(nrow(df))")
df.unit_price = coalesce.(df.unit_price, price_median)
df.unit_cost = coalesce.(df.unit_cost, cost_median)
println(df[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
println("nrow = $(nrow(df))")
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 │ P040802007 04 0408 040802 [90m missing [0m[90m missing [0m
3 │ P050103021 05 0501 050103 [90m missing [0m[90m missing [0m
4 │ P050405009 05 0504 050405 [90m missing [0m[90m missing [0m
5 │ P060802026 06 0608 060802 [90m missing [0m[90m missing [0m
6 │ P070202092 07 0702 070202 [90m missing [0m[90m missing [0m
7 │ P080504027 08 0805 080504 [90m missing [0m[90m missing [0m
8 │ P090204185 09 0902 090204 [90m missing [0m[90m missing [0m
nrow = 10030
[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
# 別解
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("nrow = $(nrow(df))")
println(df_product[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
df = df_product |>
# @replacena(:unit_price => price_median, :unit_cost => cost_median) |> エラーになる。変数名は指定できない
@replacena(:unit_price => 9999999999, :unit_cost => 9999999999) |>
@mutate(unit_price = _.unit_price == 9999999999 ? price_median : _.unit_price,
unit_cost = _.unit_cost == 9999999999 ? cost_median : _.unit_cost) |>
DataFrame
println("nrow = $(nrow(df))")
println(df[[159, 160, 197, 497, 1532, 2013, 6297, 7076], :])
price_median = 252, cost_median = 189
nrow = 10030
[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 [90m missing [0m[90m missing [0m
3 │ P050103021 05 0501 050103 [90m missing [0m[90m missing [0m
4 │ P050405009 05 0504 050405 [90m missing [0m[90m missing [0m
5 │ P060802026 06 0608 060802 [90m missing [0m[90m missing [0m
6 │ P070202092 07 0702 070202 [90m missing [0m[90m missing [0m
7 │ P080504027 08 0805 080504 [90m missing [0m[90m missing [0m
8 │ P090204185 09 0902 090204 [90m missing [0m[90m missing [0m
nrow = 10030
[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 Any [0m[90m Any [0m[90m Any [0m[90m Any [0m[90m Any [0m[90m Any [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
J-083: 単価(unit_price)と原価(unit_cost)の欠損値について、各商品のカテゴリ小区分コード(category_small_cd)ごとに算出した中央値で補完した新たな商品データを作成せよ。なお、中央値については1円未満を丸めること(四捨五入または偶数への丸めで良い)。補完実施後、各項目について欠損が生じていないことも確認すること。
using StatsBase
gd = groupby(df_product, :category_small_cd)
df = combine(gd, :unit_price => (x -> round(Int, median(skipmissing(x)))) => :unit_price_median,
:unit_cost => (x -> round(Int, median(skipmissing(x)))) => :unit_cost_median);
df2 = innerjoin(df_product, df, on=:category_small_cd);
# これは動かない
# results = df2 |>
# @mutate(unit_price2 = ifelse(ismissing(_.unit_price), _.unit_price_median, _.unit_price)) |>
# DataFrame;
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件表示せよ。また、作成したデータに欠損が存在しないことを確認せよ。
gd2019 = groupby(df_receipt[df_receipt.sales_ymd .÷ 10000 .== 2019, [:customer_id, :amount]], :customer_id)
df2019 = combine(gd2019, :amount => sum => :amount_2019);
gdall = groupby(df_receipt[!, [:customer_id, :amount]], :customer_id)
dfall = combine(gdall, :amount => sum => :amount_all);
df = leftjoin(df2019, dfall, on=:customer_id) |>
@replacena(0) |>
@mutate(amount_rate = _.amount_2019 / _.amount_all) |>
@filter(_.amount_rate > 0) |>
@orderby(_.customer_id) |>
DataFrame
first(df, 10)
Row |
customer_id |
amount_2019 |
amount_all |
amount_rate |
|
String15 |
Int64 |
Int64 |
Float64 |
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
gd = groupby(df_geocode[!, [:postal_cd, :longitude, :latitude]], :postal_cd)
df = combine(gd, :longitude => mean => :m_longitude, :latitude => mean => :m_latitude);
df_customer2 = innerjoin(df_customer, df, on=:postal_cd)
first(df_customer2, 10)
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
m_longitude |
m_latitude |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
Float64 |
Float64 |
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 = result |>
@mutate(distance = calc_distance(_.m_latitude, _.m_longitude, _.latitude, _.longitude)) |>
@rename(:address => :customer_address, :address_1 => :store_address) |>
@select(:customer_id, :customer_address, :store_address, :distance) |>
@orderby(_.customer_id) |>
DataFrame
first(result_df, 10)
Row |
customer_id |
customer_address |
store_address |
distance |
|
String15 |
String |
String |
Float64 |
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)の番号が小さいものを残すこととする。
gd = groupby(df_receipt, :customer_id)
df = leftjoin(df_customer, combine(gd, :amount => sum => :sum_amount), on=:customer_id);
gd = groupby(df, [: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
dfx = dfx |>
@orderby_descending(_.sum_amount) |>
@thenby(_.customer_id) |>
@take(1) |>
DataFrame
#println(dfx)
end
append!(df_customer_u, dfx)
end
println("df_customer の行数 = ", nrow(df_customer))
println("df_customer_u の行数 = ", nrow(df_customer_u))
println("差 = ", count)
first(df_customer_u, 5)
df_customer の行数 = 21971
df_customer_u の行数 = 21941
差 = 30
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
sum_amount |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
Int64? |
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 |
J-088: 087で作成したデータを元に、顧客データに統合名寄IDを付与したデータを作成せよ。ただし、統合名寄IDは以下の仕様で付与するものとする。
- 重複していない顧客:顧客ID(customer_id)を設定
- 重複している顧客:前設問で抽出したレコードの顧客IDを設定
顧客IDのユニーク件数と、統合名寄IDのユニーク件数の差も確認すること。
df_customer_n = innerjoin(df_customer, df_customer_u[!, [:customer_id, :customer_name, :postal_cd]], on=[:customer_name, :postal_cd], makeunique=true) |>
@rename(:customer_id_1 => :integration_id) |>
DataFrame;
println("件数の差 = $(length(unique(df_customer_n.customer_id)) - length(unique(df_customer_n.integration_id)))")
first(df_customer_n, 10)
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
integration_id |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
String15 |
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の割合でランダムにデータを分割せよ。
gd = groupby(df_receipt, :customer_id)
df_sales_customer = combine(gd, :amount => sum => :sum_amount);
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))
first(df_customer_train, 5)
(0.7999036840837949, 0.20009631591620516)
Row |
customer_id |
customer_name |
gender_cd |
gender |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
sum_amount |
|
String15 |
String31 |
String |
String7 |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
Int64 |
1 |
CS027411000001 |
長田 遥 |
1 |
女性 |
1973-09-14 |
45 |
251-0861 |
神奈川県藤沢市大庭********** |
S14027 |
20150720 |
A-20100214-A |
2382 |
2 |
CS023615000111 |
松井 幸子 |
1 |
女性 |
1956-06-23 |
62 |
212-0016 |
神奈川県川崎市幸区南幸町********** |
S14023 |
20150313 |
8-20091213-6 |
1504 |
3 |
CS040214000008 |
佐々木 由美子 |
1 |
女性 |
1994-05-30 |
24 |
194-0001 |
東京都町田市つくし野********** |
S14040 |
20150811 |
F-20100901-F |
13523 |
4 |
CS038615000134 |
杉山 美智子 |
1 |
女性 |
1949-04-03 |
69 |
279-0043 |
千葉県浦安市富士見********** |
S13038 |
20150723 |
5-20100705-4 |
608 |
5 |
CS011615000108 |
岡本 めぐみ |
9 |
不明 |
1950-03-06 |
69 |
223-0058 |
神奈川県横浜市港北区新吉田東********** |
S14011 |
20141112 |
6-20081209-3 |
898 |
J-090: レシート明細データ(df_receipt)は2017年1月1日〜2019年10月31日までのデータを有している。売上金額(amount)を月次で集計し、学習用に12ヶ月、テスト用に6ヶ月の時系列モデル構築用データを3セット作成せよ。
temp = copy(df_receipt)
temp.sales_ymd .÷= 100
gd = groupby(temp, :sales_ymd)
df = combine(gd, :amount => sum => :sum_amount) |>
@rename(:sales_ymd => :sales_ym) |>
DataFrame
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(train)
println(test)
[1m12×2 DataFrame[0m
[1m Row [0m│[1m sales_ym [0m[1m sum_amount [0m
│[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────
1 │ 201705 884010
2 │ 201706 894242
3 │ 201707 959205
4 │ 201708 954836
5 │ 201709 902037
6 │ 201710 905739
7 │ 201711 932157
8 │ 201712 939654
9 │ 201801 944509
10 │ 201802 864128
11 │ 201803 946588
12 │ 201804 937099
[1m6×2 DataFrame[0m
[1m Row [0m│[1m sales_ym [0m[1m sum_amount [0m
│[90m Int64 [0m[90m Int64 [0m
─────┼──────────────────────
1 │ 201702 764413
2 │ 201703 962945
3 │ 201704 847566
4 │ 201705 884010
5 │ 201706 894242
6 │ 201707 959205
J-091: 顧客データ(df_customer)の各顧客に対し、売上実績がある顧客数と売上実績がない顧客数が1:1となるようにアンダーサンプリングで抽出せよ。
gd = groupby(df_receipt, :customer_id)
df = combine(gd, :amount => sum => :sum_amount)
df2 = leftjoin(df_customer, df, on=:customer_id) |>
@replacena(0) |>
@mutate(flag = _.sum_amount > 0) |>
DataFrame
gd2 = groupby(df2, :flag)
(n1, n2) = (nrow(gd2[1]), nrow(gd2[2]))
using StatsBase
index = sample(1:n1, n2, replace=false) # 非復元抽出
df_amount_0 = gd2[2];
df_amount_1 = gd2[1][index, :]
nrow(df_amount_0), nrow(df_amount_1)
第三正規形,非正規化
J-092: 顧客データ(df_customer)の性別について、第三正規形へと正規化せよ。
df_customer_std = df_customer |>
@select(-:gender) |>
@take(3) |>
DataFrame
Row |
customer_id |
customer_name |
gender_cd |
birth_day |
age |
postal_cd |
address |
application_store_cd |
application_date |
status_cd |
|
String15 |
String31 |
String |
Date |
Int64 |
String15 |
String |
String7 |
String |
String15 |
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 = df_customer |>
@select(:gender_cd, :gender) |>
@unique() |>
@take(3) |>
DataFrame
Row |
gender_cd |
gender |
|
String |
String7 |
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);
first(df_product_full, 3)
Row |
product_cd |
category_major_cd |
category_medium_cd |
category_small_cd |
unit_price |
unit_cost |
category_major_name |
category_medium_name |
category_small_name |
|
String15 |
String |
String |
String |
Int64? |
Int64? |
String |
String |
String |
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 |
ファイル出力先のパスは以下のようにすること
CSV.write("-094.csv", df_product_full)
これ以降の問題は重要なものではないのでパスする
J-095: 093で作成したカテゴリ名付き商品データを以下の仕様でファイル出力せよ。
ファイル形式 |
ヘッダ有無 |
文字エンコーディング |
CSV(カンマ区切り) |
有り |
CP932 |
ファイル出力先のパスは以下のようにすること。
J-096: 093で作成したカテゴリ名付き商品データを以下の仕様でファイル出力せよ。
ファイル形式 |
ヘッダ有無 |
文字エンコーディング |
CSV(カンマ区切り) |
無し |
UTF-8 |
ファイル出力先のパスは以下のようにすること。
J-097: 094で作成した以下形式のファイルを読み込み、データを3件を表示させて正しく取り込まれていることを確認せよ。
ファイル形式 |
ヘッダ有無 |
文字エンコーディング |
CSV(カンマ区切り) |
有り |
UTF-8 |
J-098: 096で作成した以下形式のファイルを読み込み、データを3件を表示させて正しく取り込まれていることを確認せよ。
ファイル形式 |
ヘッダ有無 |
文字エンコーディング |
CSV(カンマ区切り) |
ヘッダ無し |
UTF-8 |
J-099: 093で作成したカテゴリ名付き商品データを以下の仕様でファイル出力せよ。
ファイル形式 |
ヘッダ有無 |
文字エンコーディング |
TSV(タブ区切り) |
有り |
UTF-8 |
ファイル出力先のパスは以下のようにすること
J-100: 099で作成した以下形式のファイルを読み込み、データを3件を表示させて正しく取り込まれていることを確認せよ。
ファイル形式 |
ヘッダ有無 |
文字エンコーディング |
TSV(タブ区切り) |
有り |
UTF-8 |
~~# これで100本終わりです。おつかれさまでした!