kaggle电商零售数据分析案例 项目背景数据清洗退货情况分析客户RFM分析
项目背景
这个数据集是kaggle上面的一个电商数据集,其中包含2010年12月12日至2011年12月9日之间在英国注册的非商店在线零售的所有交易。该公司主要销售各种独特的礼品之类,其中许多客户该公司是批发商。因此本次数据分析将对客户进行分析,并对客户进行相关分层处理。
数据清洗 import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport osimport warningsimport missingno as msnowarnings.filterwarnings('ignore')data = pd.read_csv('data.csv',encoding = 'utf-8', dtype = {'CustomerID' : str})data.head()
这就是data数据集的前五行。
接下来观看数据概况
我们看到这里面Description和CustomerID字段都有相应的缺失,因此我们选择将这里面的数据进行处理。
首先我们选择将Description字段里面缺失的行删除,另外我们将CustinerID中确实字段填补为U。
data.dropna(axis = 0, subset = ['Description'], inplace = True)data.CustomerID = data.CustomerID.fillna('U')做好以上处理后我们看每个客户的每个订单的购买商品数量
temp = data.groupby(by=['CustomerID', 'InvoiceNo'], as_index=False)['StockCode'].count()temp.rename(columns = {'StockCode': 'product numbers'}) 退货情况分析数据集标签InvioceNo里有一些编号包含’C’,这代表这些订单时退货订单,因此我们需要对这些退货订单进行处理。我们写一个函数,找出退货订单的原订单。这里面会有如下两种情况:
退货订单没有对应的原订单退货订单存在一个或一个以上的原订单。因此我们创建一个quantity_canceled的标签,用来记录每一个订单退货量,方便我们之后计算相应的单笔订单真实消费额。 data_cleaned = data.copy(deep = True)data_cleaned['quantity_canceled'] = 0unpaired_invoice = []paired_invoice = []for index, col in data.iterrows(): if col['Quantity'] > 0 or col['Description'] == 'Discount': continue #提取出和取消订单的商品配对的原订单 df_test = data[(data['CustomerID'] == col['CustomerID']) &(data['StockCode'] == col['StockCode']) &(data['InvoiceDate'] < col['InvoiceDate']) &(data['Quantity']) > 0] if (len(df_test) == 0): unpaired_invoice.append(index) elif (len(df_test) == 1): index_order = df_test.index[0] data_cleaned.loc[index_order, 'quantity_canceled'] = -col['Quantity'] paired_invoice.append(index) elif (len(df_test) > 1): df_test.sort_index(axis=0 ,ascending=False, inplace = True) for ind, val in df_test.iterrows(): if val['Quantity'] < -col['Quantity']: continue data_cleaned.loc[ind, 'quantity_canceled'] = -col['Quantity'] paired_invoice.append(index) break
经过上述代码处理后,我们就得到了两个列表,一个列表叫unpaired_invoice,这个里面记录了没有配对的订单。还有一个列表叫做paired_invoice,表示配对的订单。
我们查看列表长度,发现分别有7106和1994条。
我们接下来先探索相应的退货情况。
#分别提取数量为正的订单和数量为负的订单data_canceled = data[data['Quantity'] <= 0]data_all = data[(data['Quantity'] > 0)]data_canceled['month'] = pd.to_datetime(data_canceled['InvoiceDate']).dt.monthdata_all['month'] = pd.to_datetime(data_all['InvoiceDate']).dt.monthdata_canceled['year'] = pd.to_datetime(data_canceled['InvoiceDate']).dt.yeardata_all['year'] = pd.to_datetime(data_all['InvoiceDate']).dt.yeardata_canceled['price'] = - data_canceled['Quantity'] * data_canceled['UnitPrice']data_all['price'] = data_all['Quantity'] * data_all['UnitPrice']按照年月分别统计退货金额和退货率,tt这个表就是展示分月的退货总金额,pp代表所有订单数量为正的购物总金额,tt / pp 就代表退货率情况。
tt = data_canceled.groupby(['year','month'])['price'].sum().unstack()pp = data_all.groupby(['year','month'])['price'].sum().unstack()plt.figure(figsize = (8,6))plt.title('各月份退货金额',fontsize = 16)plt.bar(tt.loc[2011].index, tt.loc[2011].values)plt.figure(figsize = (8,6))plt.title('各月份退货比例',fontsize = 16)plt.plot((tt / pp).loc[2011].index, (tt / pp).loc[2011].values,)
我们看到在1月份和12月份相应的退货金额和退货比例都是上升的,这里的原因应该是在那个时候西方人可能会过圣诞节之类的节日,出现大批购物的次数变多,同时相应的退货次数也增多了,这和我们的双十一有没有点像啊,购买之后都是会有大批退货。
RFM分析主要包括三个维度,R代表客户最近一次购物消费的时间,F代表客户消费的频率, M代表客户消费总金额。为了进行这一分析,我们首先对数据进行以下处理,删除掉最近之前未配对的quantity为负的订单,由于配对订单已经包含在data_cleaned这一特征里面的quantity_canceled标签中,因此我们对配对的订单也予以删除
data_cleaned.drop(unpaired_invoice, axis = 0, inplace = True)data_cleaned.drop(paired_invoice, axis = 0, inplace =True)为了计算RFM,我们计算total_price,这包含了客户的退货订单,同时取每个客户每笔订单的时间
data_cleaned['TotalPrice'] = data_cleaned['UnitPrice'] * (data_cleaned['Quantity'] - data_cleaned['quantity_canceled'])data_cleaned.sort_values('CustomerID')[:5]invoice_price = data_cleaned.groupby(by = ['CustomerID','InvoiceNo'], as_index = False).agg({'TotalPrice': 'sum','InvoiceDate': 'first'})invoice_price.rename(columns = {'TotalPrice': 'basket_price'}, inplace =True)invoice_price = invoice_price.loc[invoice_price['basket_price'] > 0]invoice_price.head()
接下来我们就可以计算相应的R_value, F_value, M_value了。
接下来我们对R_value,F_value, M_value进行离散化分箱,便于我们对客户分类。
我们这里选取R_value、F_value、M_value的均值作为相应的分割点,分为高低等级。
rfm['R'] = np.where(rfm['R_score'] > 3.57, '高', '低')rfm['F'] = np.where(rfm['F_score'] > 2.03, '高', '低')rfm['M'] = np.where(rfm['M_score'] > 1.89, '高', '低')rfm['value'] = rfm['R'] + rfm['F'] + rfm['M']rfm
最后我们根据value标签对客户进行分类
最后我们用plotly这个包来进行展示分类