【解説】データサイエンス100本ノック【問85〜86回答】

【解説】データサイエンス100本ノック【問85〜86回答】

当ページのリンクには広告が含まれています。



目次


データサイエンス100本ノックの始め方は、以下の記事を参考にしていただければと思います。


>>データサイエンス100本ノックの始め方を確認する


第85問目:軽度緯度変換用データフレームの紐付け

P-085: 顧客データフレーム(df_customer)の全顧客に対し、郵便番号(postal_cd)を用いて経度緯度変換用データフレーム(df_geocode)を紐付け、新たなdf_customer_1を作成せよ。ただし、複数紐づく場合は経度(longitude)、緯度(latitude)それぞれ平均を算出すること。

本問は、「df_customerの全顧客に対して、郵便番号(postal_cd)を用いて経度緯度変換用データフレーム(df_geocode)を紐付ける」ということですが、シンプルに内部結合を行えばOKです。

内部結合は、mergeメソッドを使えばOKです。

mergeメソッドの復習は以下の記事を参照ください。

【解説】内部結合の方法を学ぶ | データサイエンス100本ノック【問36〜問37 回答】 - omathin blog

まずは、df_customerとdf_geocodeの構造を確認します。

1
df_customer.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	customer_id	customer_name	gender_cd	gender	birth_day	age	postal_cd	address	application_store_cd	application_date	status_cd
0 CS021313000114 大野 あや子 1 女性 1981-04-29 37 259-1113 神奈川県伊勢原市粟窪********** S14021 20150905 0-00000000-0
1 CS037613000071 六角 雅彦 9 不明 1952-04-01 66 136-0076 東京都江東区南砂********** S13037 20150414 0-00000000-0
2 CS031415000172 宇多田 貴美子 1 女性 1976-10-04 42 151-0053 東京都渋谷区代々木********** S13031 20150529 D-20100325-C
3 CS028811000001 堀井 かおり 1 女性 1933-03-27 86 245-0016 神奈川県横浜市泉区和泉町********** S14028 20160115 0-00000000-0
4 CS001215000145 田崎 美紀 1 女性 1995-03-29 24 144-0055 東京都大田区仲六郷********** S13001 20170605 6-20090929-2
5 CS020401000016 宮下 達士 0 男性 1974-09-15 44 174-0065 東京都板橋区若木********** S13020 20150225 0-00000000-0
6 CS015414000103 奥野 陽子 1 女性 1977-08-09 41 136-0073 東京都江東区北砂********** S13015 20150722 B-20100609-B
7 CS029403000008 釈 人志 0 男性 1973-08-17 45 279-0003 千葉県浦安市海楽********** S12029 20150515 0-00000000-0
8 CS015804000004 松谷 米蔵 0 男性 1931-05-02 87 136-0073 東京都江東区北砂********** S13015 20150607 0-00000000-0
9 CS033513000180 安斎 遥 1 女性 1962-07-11 56 241-0823 神奈川県横浜市旭区善部町********** S14033 20150728 6-20080506-5
1
df_geocode.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
12

postal_cd prefecture city town street address full_address longitude latitude
0 060-0000 北海道 札幌市中央区 None None None 北海道札幌市中央区 141.34103 43.05513
1 064-0941 北海道 札幌市中央区 旭ケ丘 None None 北海道札幌市中央区旭ケ丘 141.31972 43.04223
2 060-0042 北海道 札幌市中央区 大通西 None 1丁目 北海道札幌市中央区大通西1丁目 141.35637 43.06102
3 060-0042 北海道 札幌市中央区 大通西 None 2丁目 北海道札幌市中央区大通西2丁目 141.35445 43.06080
4 060-0042 北海道 札幌市中央区 大通西 None 3丁目 北海道札幌市中央区大通西3丁目 141.35275 43.06086
5 060-0042 北海道 札幌市中央区 大通西 None 4丁目 北海道札幌市中央区大通西4丁目 141.35126 43.06039
6 060-0042 北海道 札幌市中央区 大通西 None 5丁目 北海道札幌市中央区大通西5丁目 141.34975 43.06017
7 060-0042 北海道 札幌市中央区 大通西 None 6丁目 北海道札幌市中央区大通西6丁目 141.34821 43.05992
8 060-0042 北海道 札幌市中央区 大通西 None 7丁目 北海道札幌市中央区大通西7丁目 141.34663 43.05974
9 060-0042 北海道 札幌市中央区 大通西 None 8丁目 北海道札幌市中央区大通西8丁目 141.34506 43.05957

df_customerとdf_geocodeを内部結合していきます。共通するカラムは、postal_cdを指定します。

1
2
df_customer_1 = pd.merge(df_customer[['customer_id', 'postal_cd']], df_geocode[['postal_cd', 'longitude', 'latitude']], how='inner', on='postal_cd')
df_customer_1
出力
1
2
3
4
5
6
7
8
9
10
11
12
13
	customer_id	postal_cd	longitude	latitude
0 CS021313000114 259-1113 139.31779 35.41358
1 CS021303000023 259-1113 139.31779 35.41358
2 CS021303000007 259-1113 139.31779 35.41358
3 CS021313000183 259-1113 139.31779 35.41358
4 CS021314000098 259-1113 139.31779 35.41358
... ... ... ... ...
22085 CS021612000057 259-1134 139.30992 35.38544
22086 CS035401000016 155-0033 139.66281 35.65271
22087 CS003612000043 182-0033 139.53539 35.66020
22088 CS007612000095 276-0043 140.10959 35.73419
22089 CS021411000017 243-0121 139.26601 35.44896
22090 rows × 4 columns

df_customer_1というデータフレームが作成できました。

ここでcustomer_idに対して複数の緯度経度が紐付いてしまったデータに関しては緯度経度それぞれの平均を算出しなければなりません。

つまりcustomer_idごとに緯度経度それぞれの平均を取れば良いと言い換えられるので、gtoupbyとaggを用いれば良いと考えられます。

groupbyとaggの使い方は以下の記事を参考にしてください。

【解説】手を動かしながら平均値と中央値の抽出方法を学ぶ | データサイエンス100本ノック【問27〜問28 回答】 - omathin blog

1
2
df_customer_1 = df_customer_1.groupby('customer_id').agg({'longitude':'mean', 'latitude':'mean'}).reset_index()
df_customer_1.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	customer_id	longitude	latitude
0 CS001105000001 139.70238 35.54137
1 CS001112000009 139.70386 35.58670
2 CS001112000019 139.74687 35.57153
3 CS001112000021 139.70238 35.54137
4 CS001112000023 139.74687 35.57153
5 CS001112000024 139.70238 35.54137
6 CS001112000029 139.70238 35.54137
7 CS001112000030 139.70238 35.54137
8 CS001113000004 139.70238 35.54137
9 CS001113000010 139.70238 35.54137

緯度、軽度の平均をとった値なので、カラムの名前そm_longitude, m_latitudeに変換します。

カラム名の変換はrenameメソッドを用います。

renameメソッドの詳しい使い方は以下の記事を参考にしてください。

【解説】データサイエンス100本ノック【第1問〜第10問】 - omathin blog

1
2
df_customer_1.rename(columns={'longitude':'m_longitude', 'latitude':'m_latitude'}, inplace=True)
df_customer_1.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
customer_id	m_longitude	m_latitude
0 CS001105000001 139.70238 35.54137
1 CS001112000009 139.70386 35.58670
2 CS001112000019 139.74687 35.57153
3 CS001112000021 139.70238 35.54137
4 CS001112000023 139.74687 35.57153
5 CS001112000024 139.70238 35.54137
6 CS001112000029 139.70238 35.54137
7 CS001112000030 139.70238 35.54137
8 CS001113000004 139.70238 35.54137
9 CS001113000010 139.70238 35.54137

最後にdf_customerとdf_customer_1を内部結合を行い完了です。

1
2
df_customer_1 = pd.merge(df_customer, df_customer_1, how='inner', on='customer_id')
df_customer_1.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	customer_id	customer_name	gender_cd	gender	birth_day	age	postal_cd	address	application_store_cd	application_date	status_cd	m_longitude	m_latitude
0 CS021313000114 大野 あや子 1 女性 1981-04-29 37 259-1113 神奈川県伊勢原市粟窪********** S14021 20150905 0-00000000-0 139.31779 35.41358
1 CS037613000071 六角 雅彦 9 不明 1952-04-01 66 136-0076 東京都江東区南砂********** S13037 20150414 0-00000000-0 139.83502 35.67193
2 CS031415000172 宇多田 貴美子 1 女性 1976-10-04 42 151-0053 東京都渋谷区代々木********** S13031 20150529 D-20100325-C 139.68965 35.67374
3 CS028811000001 堀井 かおり 1 女性 1933-03-27 86 245-0016 神奈川県横浜市泉区和泉町********** S14028 20160115 0-00000000-0 139.48360 35.39125
4 CS001215000145 田崎 美紀 1 女性 1995-03-29 24 144-0055 東京都大田区仲六郷********** S13001 20170605 6-20090929-2 139.70775 35.54084
5 CS020401000016 宮下 達士 0 男性 1974-09-15 44 174-0065 東京都板橋区若木********** S13020 20150225 0-00000000-0 139.67245 35.77073
6 CS015414000103 奥野 陽子 1 女性 1977-08-09 41 136-0073 東京都江東区北砂********** S13015 20150722 B-20100609-B 139.83601 35.67818
7 CS029403000008 釈 人志 0 男性 1973-08-17 45 279-0003 千葉県浦安市海楽********** S12029 20150515 0-00000000-0 139.90469 35.65422
8 CS015804000004 松谷 米蔵 0 男性 1931-05-02 87 136-0073 東京都江東区北砂********** S13015 20150607 0-00000000-0 139.83601 35.67818
9 CS033513000180 安斎 遥 1 女性 1962-07-11 56 241-0823 神奈川県横浜市旭区善部町********** S14033 20150728 6-20080506-5 139.51463 35.45013

第86問目: 軽度緯度の算出

P-086: 前設問で作成した緯度経度つき顧客データフレーム(df_customer_1)に対し、申込み店舗コード(application_store_cd)をキーに店舗データフレーム(df_store)と結合せよ。そして申込み店舗の緯度(latitude)・経度情報(longitude)と顧客の緯度・経度を用いて距離(km)を求め、顧客ID(customer_id)、顧客住所(address)、店舗住所(address)とともに表示せよ。計算式は簡易式で良いものとするが、その他精度の高い方式を利用したライブラリを利用してもかまわない。結果は10件表示すれば良い。

まずは店舗データフレームの構造を確認します。

1
df_store.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	store_cd	store_name	prefecture_cd	prefecture	address	address_kana	tel_no	longitude	latitude	floor_area
0 S12014 千草台店 12 千葉県 千葉県千葉市稲毛区千草台一丁目 チバケンチバシイナゲクチグサダイイッチョウメ 043-123-4003 140.1180 35.63559 1698.0
1 S13002 国分寺店 13 東京都 東京都国分寺市本多二丁目 トウキョウトコクブンジシホンダニチョウメ 042-123-4008 139.4802 35.70566 1735.0
2 S14010 菊名店 14 神奈川県 神奈川県横浜市港北区菊名一丁目 カナガワケンヨコハマシコウホククキクナイッチョウメ 045-123-4032 139.6326 35.50049 1732.0
3 S14033 阿久和店 14 神奈川県 神奈川県横浜市瀬谷区阿久和西一丁目 カナガワケンヨコハマシセヤクアクワニシイッチョウメ 045-123-4043 139.4961 35.45918 1495.0
4 S14036 相模原中央店 14 神奈川県 神奈川県相模原市中央二丁目 カナガワケンサガミハラシチュウオウニチョウメ 042-123-4045 139.3716 35.57327 1679.0
5 S13051 板橋大原店 13 東京都 東京都板橋区大原町 トウキョウトイタバシクオオハラチョウ 03-0123-4029 139.6980 35.76788 1045.0
6 S13015 南砂店 13 東京都 東京都江東区南砂二丁目 トウキョウトコウトウクミナミスナニチョウメ 03-0123-4014 139.8229 35.67066 1337.0
7 S14040 長津田店 14 神奈川県 神奈川県横浜市緑区長津田みなみ台五丁目 カナガワケンヨコハマシミドリクナガツタミナミダイゴチョウメ 045-123-4046 139.4994 35.52398 1548.0
8 S13044 南六郷店 13 東京都 東京都大田区南六郷二丁目 トウキョウトオオタクミナミロクゴウニチョウメ 03-0123-4028 139.7207 35.54604 1379.0
9 S14050 阿久和西店 14 神奈川県 神奈川県横浜市瀬谷区阿久和西一丁目 カナガワケンヨコハマシセヤクアクワニシイッチョウメ 045-123-4053 139.4961 35.45918 1830.0

問題文に従い、顧客データフレーム(df_customer_1)に対して、application_store_cdをキーに店舗データフレームを内部結合します。ここで注意ですが、df_storeには、application_store_cdという名前のカラムが存在しません。application_store_cdではなくstore_cdという名前のカラムになっています。
このような場合の対処としては2パタンあります。

  • renameを用いてカラム名を揃える
  • mergeメソッドの引数としてleft_onright_onを用いて左側と右側それぞれにおけるキーカラムを指定する

ここでは、後者の方法で進めたいと思います。

1
2
df_tmp = pd.merge(df_customer_1, df_store, how='inner', left_on='application_store_cd', right_on='store_cd')
df_tmp.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
12
	customer_id	customer_name	gender_cd	gender	birth_day	age	postal_cd	address_x	application_store_cd	application_date	...	store_cd	store_name	prefecture_cd	prefecture	address_y	address_kana	tel_no	longitude	latitude	floor_area
0 CS021313000114 大野 あや子 1 女性 1981-04-29 37 259-1113 神奈川県伊勢原市粟窪********** S14021 20150905 ... S14021 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0
1 CS021313000025 砂川 あさみ 1 女性 1981-10-05 37 259-1131 神奈川県伊勢原市伊勢原********** S14021 20150326 ... S14021 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0
2 CS021411000096 布施 杏 1 女性 1971-10-30 47 259-1114 神奈川県伊勢原市高森********** S14021 20160621 ... S14021 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0
3 CS021415000150 早美 紗季 1 女性 1969-11-26 49 259-1141 神奈川県伊勢原市上粕屋********** S14021 20150601 ... S14021 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0
4 CS021313000046 会田 薫 9 不明 1983-01-19 36 259-1144 神奈川県伊勢原市池端********** S14021 20150722 ... S14021 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0
5 CS021103000002 庄司 染五郎 0 男性 2006-11-24 12 259-1111 神奈川県伊勢原市西富岡********** S14021 20150317 ... S14021 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0
6 CS021214000028 吉井 菜摘 1 女性 1991-07-12 27 259-1132 神奈川県伊勢原市桜台********** S14021 20151007 ... S14021 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0
7 CS021512000095 佐々木 陽子 1 女性 1963-01-22 56 259-1126 神奈川県伊勢原市沼目********** S14021 20150820 ... S14021 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0
8 CS021613000002 内村 貴美子 1 女性 1950-02-18 69 259-1132 神奈川県伊勢原市桜台********** S14021 20151125 ... S14021 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0
9 CS021412000147 三輪 さやか 1 女性 1971-08-23 47 259-1103 神奈川県伊勢原市三ノ宮********** S14021 20150930 ... S14021 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0
10 rows × 23 columns

次に距離の計算を行います。
まずは、2地点間の距離を算出する関数を定義しましょう。
ここでは、問題文に記述されている距離Lを導く式を実装します。

1
2
3
def calc_distance(x1, y1, x2, y2):
distance = 6371 * math.acos(math.sin(math.radians(y1)) * math.sin(math.radians(y2)) + math.cos(math.radians(y1)) * math.cos(math.radians(y2)) * math.cos(math.radians(x1) - math.radians(x2)))
return distance

定義したcalc_distance関数を用いてapplyメソッドとlambda式を用いて距離計算を行います。

1
2
3
df_tmp['distance'] =   df_tmp[['m_longitude', 'm_latitude','longitude', 'latitude']]. \
apply(lambda x: calc_distance(x[0], x[1], x[2], x[3]), axis=1)
df_tmp.head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
12
	customer_id	customer_name	gender_cd	gender	birth_day	age	postal_cd	address_x	application_store_cd	application_date	...	store_name	prefecture_cd	prefecture	address_y	address_kana	tel_no	longitude	latitude	floor_area	distance
0 CS021313000114 大野 あや子 1 女性 1981-04-29 37 259-1113 神奈川県伊勢原市粟窪********** S14021 20150905 ... 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0 1.394409
1 CS021313000025 砂川 あさみ 1 女性 1981-10-05 37 259-1131 神奈川県伊勢原市伊勢原********** S14021 20150326 ... 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0 0.474282
2 CS021411000096 布施 杏 1 女性 1971-10-30 47 259-1114 神奈川県伊勢原市高森********** S14021 20160621 ... 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0 2.480155
3 CS021415000150 早美 紗季 1 女性 1969-11-26 49 259-1141 神奈川県伊勢原市上粕屋********** S14021 20150601 ... 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0 2.734723
4 CS021313000046 会田 薫 9 不明 1983-01-19 36 259-1144 神奈川県伊勢原市池端********** S14021 20150722 ... 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0 1.111911
5 CS021103000002 庄司 染五郎 0 男性 2006-11-24 12 259-1111 神奈川県伊勢原市西富岡********** S14021 20150317 ... 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0 2.384941
6 CS021214000028 吉井 菜摘 1 女性 1991-07-12 27 259-1132 神奈川県伊勢原市桜台********** S14021 20151007 ... 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0 1.399344
7 CS021512000095 佐々木 陽子 1 女性 1963-01-22 56 259-1126 神奈川県伊勢原市沼目********** S14021 20150820 ... 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0 1.993991
8 CS021613000002 内村 貴美子 1 女性 1950-02-18 69 259-1132 神奈川県伊勢原市桜台********** S14021 20151125 ... 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0 1.399344
9 CS021412000147 三輪 さやか 1 女性 1971-08-23 47 259-1103 神奈川県伊勢原市三ノ宮********** S14021 20150930 ... 伊勢原店 14 神奈川県 神奈川県伊勢原市伊勢原四丁目 カナガワケンイセハラシイセハラヨンチョウメ 046-123-4035 139.3129 35.40169 962.0 3.507680
10 rows × 24 columns

最後に顧客ID、顧客獣wy尾、店舗住所、距離を表示して完了です。

1
df_tmp[['customer_id', 'address_x', 'address_y', 'distance']].head(10)
出力
1
2
3
4
5
6
7
8
9
10
11
	customer_id	address_x	address_y	distance
0 CS021313000114 神奈川県伊勢原市粟窪********** 神奈川県伊勢原市伊勢原四丁目 1.394409
1 CS021313000025 神奈川県伊勢原市伊勢原********** 神奈川県伊勢原市伊勢原四丁目 0.474282
2 CS021411000096 神奈川県伊勢原市高森********** 神奈川県伊勢原市伊勢原四丁目 2.480155
3 CS021415000150 神奈川県伊勢原市上粕屋********** 神奈川県伊勢原市伊勢原四丁目 2.734723
4 CS021313000046 神奈川県伊勢原市池端********** 神奈川県伊勢原市伊勢原四丁目 1.111911
5 CS021103000002 神奈川県伊勢原市西富岡********** 神奈川県伊勢原市伊勢原四丁目 2.384941
6 CS021214000028 神奈川県伊勢原市桜台********** 神奈川県伊勢原市伊勢原四丁目 1.399344
7 CS021512000095 神奈川県伊勢原市沼目********** 神奈川県伊勢原市伊勢原四丁目 1.993991
8 CS021613000002 神奈川県伊勢原市桜台********** 神奈川県伊勢原市伊勢原四丁目 1.399344
9 CS021412000147 神奈川県伊勢原市三ノ宮********** 神奈川県伊勢原市伊勢原四丁目 3.507680

まとめ:ジオコードを学びました

本記事で紹介した方法を元にデータサイエンティストとしての知見を深めていただければと思います。

データサイエンティストに必要な知識は、TechAcademyのデータサイエンスコースでの学習がおすすめです。

無料体験可能なのでご確認ください。

コメント