Eコマースサイトの販売データを利用して商品をABC分析します。
ABC分析をすることで、売れ筋商品、死に筋商品の見極めができ
商品開発や在庫管理をする際のヒントにします。
データはこちらを利用します。

E-Commerce Data
Actual transactions from UK retailer
コードの準備
Anacondaのjupyter notebookでコードを実行しています。
Pythonが動作する環境でしたらお好きな構成で構いません。
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
df = pd.read_csv('/ecommerce-data/data.csv', encoding="shift-jis")
def ABC_segmentation(perc):
'''
3つのクラスを作成する。
次のパーセンテージによって分類する (A-70%, B-95%, C-5%)
正規分布の1シータ、2シータに準じて70%–95%に分ける。グループCは残りの5%とする
'''
if perc > 0 and perc < 0.7:
return 'A'
elif perc >= 0.7 and perc < 0.95:
return 'B'
elif perc >= 0.95:
return 'C'
df.head()
len(df)
df['StockCode'].nunique()
# 計算用にデータフレームを作成します。作成したデータフレームにカラムを追加していきます。
df_sub = df[['StockCode', 'Quantity', 'UnitPrice']].copy()
# Quantityが1以上のものを抽出
df_sub = df_sub.loc[df_sub['Quantity'] > 0]
# 販売レコードごとに商品価格と販売数で金額を算出します。
df_sub['Price'] = df_sub['UnitPrice'] * df_sub['Quantity']
# 商品ごとにグルーピングします。
df_sub = df_sub.groupby('StockCode')['Price'].sum().to_frame()
df_sub = df_sub.reset_index()
# 金額順でソートします。
df_sub = df_sub.sort_values(by=['Price'], ascending=False)
# 商品ごとに累積金額を算出します。
df_sub['RunCumPrice'] = df_sub['Price'].cumsum()
# 合計の列を作成します
df_sub['TotSum'] = df_sub['Price'].sum()
# 累積売上比の列を作成します
df_sub['RunPerc'] = df_sub['RunCumPrice']/df_sub['TotSum']
# ABCセグメントの列Classを作成します
df_sub['Class'] = df_sub['RunPerc'].apply(ABC_segmentation)
df_sub['Price'] = df_sub['Price'].astype(np.int)
df_sub.head()
# 各クラスの合計数
df_sub.Class.value_counts()
# クラスごとの総売上
print ('Sales of Class A :', df_sub[df_sub.Class == 'A']['Price'].sum())
print ('Sales of Class B :', df_sub[df_sub.Class == 'B']['Price'].sum())
print ('Sales of Class C :', df_sub[df_sub.Class == 'C']['Price'].sum())
# クラスごとの総売上の割合
print ('Percent of Sales of Class A :', df_sub[df_sub.Class == 'A']['Price'].sum()/df_sub['Price'].sum())
print ('Percent of Sales of Class B :', df_sub[df_sub.Class == 'B']['Price'].sum()/df_sub['Price'].sum())
print ('Percent of Sales of Class C :', df_sub[df_sub.Class == 'C']['Price'].sum()/df_sub['Price'].sum())
performance = df_sub['Price'].tolist()
y_pos = np.arange(len(performance))
plt.plot(y_pos, performance)
plt.ylabel('Cost')
plt.title('ABC Analysis - Sales per StockCode')
plt.grid(True)
plt.ylim((0,250000))
plt.show()
performance = df_sub['RunPerc'].tolist()
y_pos = np.arange(len(performance))
plt.plot(y_pos, performance)
plt.ylabel('Running Total Percentage')
plt.title('ABC Analysis - Cumulative Sales per StockCode')
plt.grid(True)
plt.show()
df.head()
from abc_analysis import abc_analysis, abc_plot
# Perform an ABC analysis on a numeric vector (without plotting)
dctAnalysis = abc_analysis(df_sub['Price'])
# Plot saved results of an ABC analysis
abc_plot(dctAnalysis)
ライブラリのインポートとcsv読み込み
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
df = pd.read_csv('/ecommerce-data/data.csv', encoding="shift-jis")
商品をABCセグメントに分ける関数を宣言
def ABC_segmentation(perc):
'''
3つのクラスを作成する。
次のパーセンテージによって分類する (A-70%, B-95%, C-5%)
正規分布の1シータ、2シータに準じて70%–95%に分ける。グループCは残りの5%とする
'''
if perc > 0 and perc < 0.7:
return 'A'
elif perc >= 0.7 and perc < 0.95:
return 'B'
elif perc >= 0.95:
return 'C'
データの中身を確認する
df.head()
len(df)
df['StockCode'].nunique()
前処理を行う
# 計算用にデータフレームを作成します。作成したデータフレームにカラムを追加していきます。
df_sub = df[['StockCode', 'Quantity', 'UnitPrice']].copy()
# Quantityが1以上のものを抽出
df_sub = df_sub.loc[df_sub['Quantity'] > 0]
# 販売レコードごとに商品価格と販売数で金額を算出します。
df_sub['Price'] = df_sub['UnitPrice'] * df_sub['Quantity']
# 商品ごとにグルーピングします。
df_sub = df_sub.groupby('StockCode')['Price'].sum().to_frame()
df_sub = df_sub.reset_index()
# 金額順でソートします。
df_sub = df_sub.sort_values(by=['Price'], ascending=False)
# 商品ごとに累積金額を算出します。
df_sub['RunCumPrice'] = df_sub['Price'].cumsum()
# 合計の列を作成します
df_sub['TotSum'] = df_sub['Price'].sum()
# 累積売上比の列を作成します
df_sub['RunPerc'] = df_sub['RunCumPrice']/df_sub['TotSum']
# ABCグループの列を作成します
df_sub['Class'] = df_sub['RunPerc'].apply(ABC_segmentation)
df_sub['Price'] = df_sub['Price'].astype(np.int)
df_sub.head()
結果を確認する
# 各クラスの合計数
df_sub.Class.value_counts()
# クラスごとの総売上
print ('Sales of Class A :', df_sub[df_sub.Class == 'A']['Price'].sum())
print ('Sales of Class B :', df_sub[df_sub.Class == 'B']['Price'].sum())
print ('Sales of Class C :', df_sub[df_sub.Class == 'C']['Price'].sum())
# クラスごとの総売上の割合
print ('Percent of Sales of Class A :', df_sub[df_sub.Class == 'A']['Price'].sum()/df_sub['Price'].sum())
print ('Percent of Sales of Class B :', df_sub[df_sub.Class == 'B']['Price'].sum()/df_sub['Price'].sum())
print ('Percent of Sales of Class C :', df_sub[df_sub.Class == 'C']['Price'].sum()/df_sub['Price'].sum())
performance = df_sub['Price'].tolist()
y_pos = np.arange(len(performance))
plt.plot(y_pos, performance)
plt.ylabel('Cost')
plt.title('ABC Analysis - Sales per StockCode')
plt.grid(True)
plt.ylim((0,250000))
plt.show()
performance = df_sub['RunPerc'].tolist()
y_pos = np.arange(len(performance))
plt.plot(y_pos, performance)
plt.ylabel('Running Total Percentage')
plt.title('ABC Analysis - Cumulative Sales per StockCode')
plt.grid(True)
plt.show()
df.head()
Sales of Class A : 7447895 Sales of Class B : 2662765 Sales of Class C : 531945 Percent of Sales of Class A : 0.6998187943647256 Percent of Sales of Class B : 0.250198612087924 Percent of Sales of Class C : 0.04998259354735048


ABC分析を行う
from abc_analysis import abc_analysis, abc_plot
# Perform an ABC analysis on a numeric vector (without plotting)
dctAnalysis = abc_analysis(df_sub['Price'])
# Plot saved results of an ABC analysis
abc_plot(dctAnalysis)

abc_analysisに対し、データテーブルの価格を引数で渡すと
80%がA群、90%がB群、残り10%がC群に振り分けられました。
前処理で、正規分布のシータごとに分類しましたが、この結果に応じてセグメント関数を
変更しても良いです。
ABC分析は具体的にA群が80%とかB群が90%などルールは存在せず
データを見ながら判断する必要があります。
さいごに
ABC分析は実際に運営している実店舗およびWebサービスであれば適応できる分析手法です。
カフェ、レストランなどの飲食店はもちろんのこと、Eコマースサイトのデータを準備すれば
分析が可能になっています。上記コード例のcsvの部分を変更すれば応用可能です。
必要なデータは、商品コード、商品価格、販売数の3つです。
決済日付や、顧客番号は必要ありません。
運営しているサービスでやってみてはいかがでしょうか