見出し画像

Pythonでグラフ・ネットワーク図を描く

こんにちは。コグラフ株式会社データアナリティクス事業部の塩見です。「このアイテムが好きな人は、こんなアイテムも好き」という関連性を可視化できるグラフ・ネットワーク図。かっこいいと感じる人は多いのではないでしょうか。しかし、実際に描こうとするとデータの準備でつまずくことがあります。アイテム間の関係が明示的に存在するデータは実務では少ないのです。SNSのようにユーザー同士が直接つながる場合もありますが、そのようなデータはめずらしいと思います。ネットワーク作図ライブラリは豊富ですが、描くべきデータがなければ活用できません。

では、どうすればよいのか?答えは簡単です。「ないなら作る!

具体的には、推薦ロジックを作成し、アイテム間の関係を定義します。ユーザーの閲覧履歴や購入履歴をもとに類似アイテムを推定し、それを可視化すれば、自分だけの「かっこいいグラフ・ネットワーク図」が完成します。ここではPythonのpyvisを使い、Google Colaboratoryで実行する方法を紹介します。


行動データの取得

まず、閲覧履歴や購入履歴などの行動データを用意します。行動データは「誰が(ユーザー)」「何を(アイテム)」という情報を記録したものです。以下のようなタブ区切りの log.txt を例に説明します。

user	item
1	A
1	B
2	C
2	A
3	B
3	C

アイテムの共起をカウント

ユーザーがアイテムAとBを選んだ場合、それらは何らかの共通点がある可能性があります。

アイテムAとBはともにユーザー1から選ばれた

このアイテム同士の共起回数をカウントするSQLコードを示します。log.txt の内容が log テーブルに格納されているとし、以下のように直積(クロス結合)を取ることで共起を求めます。

-- code SQL_1
-- アイテム同士の組み合わせをカウントする。
SELECT
  log1.item AS item1
 ,log2.item AS item2
 ,COUNT(*) AS combination_count
FROM log log1 CROSS JOIN log log2
WHERE log1.user = log2.user AND log1.item < log2.item
GROUP BY
  log1.item
 ,log2.item
SQL_1の実行結果

このコードこそが本記事の核心です。これほど簡単なSQLで、行動データからアイテム同士の関係を抽出できるのです。

アイテムの類似度を計算

さらに、アイテム同士のコサイン類似度を計算します。ユーザーがアイテムを選んだ場合を1、選ばなかった場合を0とし、アイテムごとにユーザーの選択をベクトル化します。
例えば、アイテムAとBの選択ベクトルを以下のように表現できます。

$$
\bm{A}=(1, 1, 0)^\mathsf{T}, \bm{B}=(1, 0, 1)^\mathsf{T}
$$

このベクトルの内積を求めると

$$
\bm{A}\cdot\bm{B}=1\cdot1+1\cdot0+0\cdot1=1
$$

コサイン類似度は次の式で定義されます。

$$
cos(\bm{x}, \bm{y})=\dfrac{\bm{x}\cdot\bm{y}}{|\bm{x}||\bm{y}|}
$$

これを求めるためのSQLコードが SQL_2 です。同じ処理をPythonで実装したものが Python_1 になります。

-- code SQL_2
-- アイテム同士のコサイン類似度を求める。
WITH combination AS (
  SELECT
    log1.item AS item1
   ,log2.item AS item2
   ,COUNT(*) AS combination_count
  FROM log log1 CROSS JOIN log log2
  WHERE log1.user = log2.user AND log1.item < log2.item
  GROUP BY
    log1.item
   ,log2.item
)

,summary as (
  SELECT
    item
   ,COUNT(*) AS item_count
  FROM log
  GROUP BY
   item
)

SELECT
  c.item1
 ,c.item2
 ,c.combination_count / sqrt(s1.item_count) / sqrt(s2.item_count) as similarity
FROM combination c
INNER JOIN summary s1
OM c.item1 = s1.item
INNER JOIN summary s2
ON c.item2 = s2.item;
SQL_2の実行結果
# code Pyhton_1
# 類似度を求めるコードPython版
import pandas as pd
import numpy as np

# データの読み込み
log = pd.read_csv('log.txt', sep='\t')

# log同士の共起回数カウント(内積の計算)
combination = (
    log.merge(log, on='user')
    .query('item_x < item_y')
    .groupby(['item_x', 'item_y'])
    .size()
    .reset_index(name='combination_count')
)

# 各アイテムの出現回数
summary = log.groupby('item').size().reset_index(name='item_count')

# 類似度の計算
result = (
    combination
    .merge(summary, left_on='item_x', right_on='item')
    .rename(columns={'item_count': 'item_count_x'})
    .drop(columns=['item'])  # 重複カラムを削除
    .merge(summary, left_on='item_y', right_on='item')
    .rename(columns={'item_count': 'item_count_y'})
    .drop(columns=['item'])  # 重複カラムを削除
)

result['similarity'] = result['combination_count'] / np.sqrt(result['item_count_x']) / np.sqrt(result['item_count_y'])

# 必要なカラムを選択
result = result[['item_x', 'item_y', 'similarity']]

print(result)
result.to_csv('result.csv', index=False)
Pyhton_1の実行結果

可視化

次に、pyvisを使ってネットワーク図を可視化します。Google Colaboratory環境では、以下のコマンドでpyvisをインストールできます。

pyvisのインストールコマンド

pyvisの公式チュートリアル「Example: Visualizing a Game of Thrones character network」を参考に Python_2 を作成しました。

# code Python_2
# pyvisで可視化する
from pyvis.network import Network
import pandas as pd

df = pd.read_csv("result.csv")
sources = df['item_x']
targets = df['item_y']
weights = df['similarity']
edge_data = zip(sources, targets, weights)
net = Network()
for e in edge_data:
    src = e[0]
    dst = e[1]
    w = e[2]
    net.add_node(src, label=str(src))
    net.add_node(dst, label=str(dst))
    net.add_edge(src, dst, value=w)
net.show("items.html", notebook=False)

このコードを実行すると items.html というファイルが生成されます。このファイルをブラウザで開くことで、アイテム同士の関係が可視化されたネットワーク図を確認できます。Google Colaboratory環境では、ファイルをダウンロードしてから開いてください。

items.html

まとめ

この記事では、行動データをもとにアイテム同士の関係を抽出し、ネットワーク図として可視化する手法を紹介しました。データが直接入手できなくても、関係性を定義することで分析の幅が広がります。

さらに、アイテムとユーザーの場所を入れ替えて同じコードを実行すると、ユーザー同士の関係も可視化できます。共通のアイテムを選ぶユーザー同士にどんな共通点があるのか、調べるのも面白いでしょう。

最後に、本記事のもう一つの主張は「SQLの記述力の高さ」です。SQL_1 や SQL_2 のコードを見直してみてください。雑音が少なくて、まるで数式のように読みやすいと思いませんか。単純かつ直感的にデータの関係を抽出できる点がSQLの強みです。

データ分析に興味のある方募集中!

コグラフ株式会社データアナリティクス事業部ではPythonやSQLの研修を行った後、実務に着手します。
研修内容の充実はもちろん、経験者に相談できる環境が備わっています。
このようにコグラフの研修には、実務を想定し着実にスキルアップを目指す環境があります。
興味がある方は、下記リンクよりお問い合わせください。

Xもやってます!

コグラフデータ事業部ではXでも情報を発信しています。
データ分析に興味がある、データアナリストになりたい人など、ぜひフォローお願いします!

いいなと思ったら応援しよう!