前のページでは予め行列形式に集計された評価値データを読み込んで協調フィルタリングを行いました.しかしながら,実際は集計されていない生の評価値データから行列形式に変換する必要があります.ここでは,「商品データ」「顧客データ」「評価データ」の3つのデータを読み込んで順に行列形式に集計する方法を確認します.
まず,必要なライブラリをインポートします.
import pandas as pd
import numpy as np
商品のCSVデータを GitHub のリポジトリからデータフレームに読み込みます.
url_items = "https://github.com/rinsaka/sample-data-sets/blob/master/collaborative_filtering_items.csv?raw=true"
df_items = pd.read_csv(url_items)
print(df_items)
id item 0 0 A 1 1 B 2 2 C 3 3 D 4 4 E
顧客のCSVデータを読み込みます.
url_customers = "https://github.com/rinsaka/sample-data-sets/blob/master/collaborative_filtering_customers.csv?raw=true"
df_customers = pd.read_csv(url_customers )
print(df_customers)
id name 0 0 Eto 1 1 Sato 2 2 Kato 3 3 Muto 4 4 Kito 5 5 Goto 6 6 Bito 7 7 Saito 8 8 Naito 9 9 Koto
次に,評価のCSVデータを読み込みます.例えば先頭行は,顧客ID = 8 の Naito さんが,商品ID = 3 の商品「D」について「2」という評価を行ったことを意味しています.
url_ratings = "https://github.com/rinsaka/sample-data-sets/blob/master/collaborative_filtering_ratings.csv?raw=true"
df_ratings = pd.read_csv(url_ratings)
print(df_ratings)
customer item rating
0 8 3 2
1 1 1 2
2 6 1 3
3 9 2 2
4 6 0 3
5 2 2 4
6 1 2 4
7 4 2 3
8 3 2 2
9 8 0 5
10 0 0 5
11 2 1 3
12 4 0 4
13 5 4 3
14 7 2 5
15 8 4 1
16 5 3 2
17 6 4 1
18 0 1 4
19 1 3 2
20 5 0 2
21 7 1 4
22 0 2 3
23 5 1 5
24 3 1 3
25 8 1 5
26 3 4 2
27 8 2 4
28 9 3 2
29 1 4 3
30 6 2 2
31 2 0 2
32 3 0 2
33 9 4 2
34 7 4 5
35 7 0 4
36 9 0 3
37 4 3 4
38 4 1 3
3つのテーブル(表のこと)を順に結合していきます.まず,「評価」と「商品」のテーブルを結合します.なお,テーブルの結合に関する詳細はここやここで確認してください.
tbl_1 = pd.merge(
df_ratings, df_items,
left_on = 'item',
right_on = 'id',
)
print(tbl_1)
customer item_x rating id item_y
0 8 3 2 3 D
1 5 3 2 3 D
2 1 3 2 3 D
...(中略)...
36 1 4 3 4 E
37 9 4 2 4 E
38 7 4 5 4 E
列名「item_y」を「item」に変更します.
tbl_1 = tbl_1.rename(columns={'item_y': 'item'})
print(tbl_1)
customer item_x rating id item
0 8 3 2 3 D
1 5 3 2 3 D
2 1 3 2 3 D
・・・(省略)
必要な列だけ残し,さらに順序も変更します.
tbl_1 = tbl_1.loc[:,['customer','item','rating']]
print(tbl_1)
customer item rating 0 8 D 2 1 5 D 2 2 1 D 2 ...(省略)...
今出来上がったテーブルと「顧客」テーブルを結合します.
tbl_2 = pd.merge(
tbl_1, df_customers,
left_on = 'customer',
right_on = 'id',
)
print(tbl_2)
customer item_x rating id_x item id_y name 0 8 3 2 3 D 8 Naito 1 8 1 5 1 B 8 Naito 2 8 2 4 2 C 8 Naito 3 8 0 5 0 A 8 Naito 4 8 4 1 4 E 8 Naito 5 5 3 2 3 D 5 Goto 6 5 1 5 1 B 5 Goto ・・・(中略)... 34 7 4 5 4 E 7 Saito 35 3 1 3 1 B 3 Muto 36 3 2 2 2 C 3 Muto 37 3 0 2 0 A 3 Muto 38 3 4 2 4 E 3 Muto
同様の方法で列名を変更した上で,列を選択し順序も変更します.
# 表示系列名の変更
tbl_2 = tbl_2.rename(columns={'id_y': 'id'})
# 列の選択と順序の変更
tbl_2 = tbl_2.loc[:,['id', 'name','item','rating']]
print(tbl_2)
id name item rating 0 8 Naito D 2 1 8 Naito B 5 2 8 Naito C 4 3 8 Naito A 5 4 8 Naito E 1 5 5 Goto D 2 6 5 Goto B 5 7 5 Goto A 2 8 5 Goto E 3 9 1 Sato D 2 10 1 Sato B 2 11 1 Sato C 4 12 1 Sato E 3 13 9 Koto D 2 14 9 Koto C 2 15 9 Koto A 3 16 9 Koto E 2 17 4 Kito D 4 18 4 Kito B 3 19 4 Kito C 3 20 4 Kito A 4 21 6 Bito B 3 22 6 Bito C 2 23 6 Bito A 3 24 6 Bito E 1 25 2 Kato B 3 26 2 Kato C 4 27 2 Kato A 2 28 0 Eto B 4 29 0 Eto C 3 30 0 Eto A 5 31 7 Saito B 4 32 7 Saito C 5 33 7 Saito A 4 34 7 Saito E 5 35 3 Muto B 3 36 3 Muto C 2 37 3 Muto A 2 38 3 Muto E 2
評価の生データをピボットテーブルを利用して行列形式にまとめます.まず,念の為に顧客と商品ごとの評価数を確認します.つまり,同一顧客が同じ商品に複数回評価していないかを確認しておきます.この結果,1.0 より大きなデータがない,つまり,同じ商品を複数回評価しているデータはないことがわかりました.
df = tbl_2.pivot_table('rating', index=['id', 'name'], columns='item', aggfunc='count')
print(df)
item A B C D E id name 0 Eto 1.0 1.0 1.0 NaN NaN 1 Sato NaN 1.0 1.0 1.0 1.0 2 Kato 1.0 1.0 1.0 NaN NaN 3 Muto 1.0 1.0 1.0 NaN 1.0 4 Kito 1.0 1.0 1.0 1.0 NaN 5 Goto 1.0 1.0 NaN 1.0 1.0 6 Bito 1.0 1.0 1.0 NaN 1.0 7 Saito 1.0 1.0 1.0 NaN 1.0 8 Naito 1.0 1.0 1.0 1.0 1.0 9 Koto 1.0 NaN 1.0 1.0 1.0
重複した評価がないことが確認できたので,合計を計算すると簡単に集計できます.
df = tbl_2.pivot_table('rating', index=['id', 'name'], columns='item', aggfunc='sum')
print(df)
item A B C D E id name 0 Eto 5.0 4.0 3.0 NaN NaN 1 Sato NaN 2.0 4.0 2.0 3.0 2 Kato 2.0 3.0 4.0 NaN NaN 3 Muto 2.0 3.0 2.0 NaN 2.0 4 Kito 4.0 3.0 3.0 4.0 NaN 5 Goto 2.0 5.0 NaN 2.0 3.0 6 Bito 3.0 3.0 2.0 NaN 1.0 7 Saito 4.0 4.0 5.0 NaN 5.0 8 Naito 5.0 5.0 4.0 2.0 1.0 9 Koto 3.0 NaN 2.0 2.0 2.0
これで行列形式のデータフレームが完成したので,NumPy 配列に格納し,レイティング行列 y
を生成します.
y = df.values
print(y)
[[ 5. 4. 3. nan nan] [nan 2. 4. 2. 3.] [ 2. 3. 4. nan nan] [ 2. 3. 2. nan 2.] [ 4. 3. 3. 4. nan] [ 2. 5. nan 2. 3.] [ 3. 3. 2. nan 1.] [ 4. 4. 5. nan 5.] [ 5. 5. 4. 2. 1.] [ 3. nan 2. 2. 2.]]
これは前のページの行列 y
と全く同じ形式です.ここまでできれば,類似度の計算やスコアの計算は前のページと同じ方法で可能です.