#!/usr/bin/env python # coding: utf-8 # In[1]: import pandas as pd # In[2]: # http://archive.ics.uci.edu/ml/datasets/Online+Retail# のデータを利用 data_dtype = {'InvoiceNo':'str', 'StockCode': 'str', 'Description': 'str', 'Quantity': 'int', 'InvoiceDate': 'datetime64', 'UnitPrice': 'float', 'CustomerID': 'str', 'Country': 'str'} df = pd.read_excel("./Online Retail.xlsx", dtype = data_dtype, keep_default_na=False) # In[3]: # 541909 entriesと表示されて、エクセルで開いた時のレコード数と一致するか確認する # エクセルでは列名を含むので、541910行ある # nullという欠損データとして扱われるデータがないことも確認する。 # 欠損がある場合は削除や調査による穴埋め、統計処理により代入などの追加処理が必要になる df.info() # In[4]: # 先頭5行を表示 df.head() # In[5]: # 数値データの集計 # 購入量 Quantityにマイナスが含まれている。ログデータを見ると返品時の処理と推測される # UnitPriceがマイナスの場合については判明せず。業務の場合は取引先にヒアリングを実施 df.describe() # In[6]: # 会員に限定して分析 df = df.loc[df["CustomerID"] != "", :] # In[7]: df.info() # In[8]: # 2011年10月末までを来店の集計期間にする train_df = df.loc[df["InvoiceDate"] < "2011-11-01",] # In[9]: import datetime def transform(data_df): days = max(data_df.loc[:, "InvoiceDate"]) - min(data_df.loc[:, "InvoiceDate"]) # Recency recency = (datetime.datetime(2011, 11, 1) - data_df.groupby("CustomerID")["InvoiceDate"].max()).apply(lambda x: x.days) recency.name = "recency" # Frequency frequency = data_df.groupby("CustomerID")["InvoiceNo"].nunique() / days.days frequency.name = "frequency" # Monetary data_process_df = data_df.copy() data_process_df.loc[:, "total_price"] = data_process_df.loc[:, "Quantity"] * data_process_df.loc[:, "UnitPrice"] monetary = data_process_df.groupby("CustomerID")["total_price"].sum() monetary.name = "monetary" return pd.merge(recency, frequency, left_index=True, right_index=True).merge(monetary, left_index=True, right_index=True) # In[10]: def is_visit(data_df, visitors): data_prcess_df = data_df.copy() data_prcess_df.loc[:, "is_visit"] = data_prcess_df.loc[:, "CustomerID"].apply(lambda x: x in visitors) return data_prcess_df.groupby("CustomerID")["is_visit"].max() # In[11]: # RFM分析 df_rfm = transform(train_df) df_rfm # In[12]: # 11月に購入実績があるかの判定フラグをたてる # 11月に購入実績のあるCustomerIDを取得 nov_customers = df.loc[(df["InvoiceDate"] >= "2011-11-01") & (df["InvoiceDate"] < "2011-12-01"), "CustomerID"].unique() # 10月末までのCustomerで11月に購入実績があるかを判定 visit_df = is_visit(train_df, nov_customers) # RFM分析の結果と結合する all_df = pd.merge(df_rfm, visit_df, left_index=True, right_index=True).reset_index() all_df