时间:2023-03-15 23:36:01 | 来源:电子商务
时间:2023-03-15 23:36:01 来源:电子商务
一,背景import pandas as pd data= pd.read_csv('./dataset2011-2015.csv',encoding='ISO-8859-1')print('源数据的形状为:',data.shape)print('查看数据的类型:',data.dtypes)print('初步判断数据是否有缺失值:',data. info())print(data.head())使用read_csv读取数据的时候,需要根据csv文件存储时的编码格式,进行读取。csv常见编码格式:UTF-8、GBK 、ISO-8859-1
根据上面的代码结果,我们可以初步了解的数据的基本情况如下:import pandas as pd data= pd.read_csv(r'superstore_dataset2011-2015.csv',encoding='ISO-8859-1')print('每个字段中是否含有空值:/n', data.isna().any())
发现Postal Code字段含有缺失值。而该字段并不在我们的分析范围内,我们可以不处理该字段的缺失值,同时也保留了该字段所在数据其他字段的数据,这样可以确保分析的准确度。data.describe()
出结果指标包括count,mean,std,min,max以及第25百分位,中位数(第50百分位)和第75百分位。通过观察该结果,发现数据集并无异常值存在。data['Order Date'] = pd.to_datetime(data['Order Date'])print(data.dtypes)
上面我们将Order Date(订单日期)列的数据类型成功修改成了datetime类型,因为在通过datetime可以快速的增加数据的维度,例如:年、月、季度等。# 通过dt属性返回的对象中可以获取datetime中的年与日等数据data['Order-year'] = data ['Order Date'].dt.yeardata ['Order-month'] = data ['Order Date'].dt.monthdata ['quarter'] = data ['Order Date'].dt.to_period('Q')result = data [['Order Date','Order-year','Order-month', 'quarter']].head()display(data.head())
七:具体分析目标sales_year = data.groupby(by='Order-year')['Sales'].sum()print(sales_year)
b,根据销售额增长率公式分别算出2012年、2013年和2014年的销售额增长率sales_rate_12 = sales_year[2012] / sales_year[2011] -1sales_rate_13 = sales_year[2013] / sales_year[2012] -1sales_rate_14 = sales_year[2014] / sales_year[2013] -1print(sales_rate_12,sales_rate_13,sales_rate_14)
用百分数的形式结果sales_rate_12 = "%.2f%%" % (sales_rate_12 * 100)sales_rate_13 = "%.2f%%" % (sales_rate_13 * 100)sales_rate_14 = "%.2f%%" % (sales_rate_14 * 100)print(sales_rate_12,sales_rate_13,sales_rate_14)
import matplotlib.pyplot as pltimport matplotlib as mpl# #由于百分比数据不支持绘图,所以重新求占比sales_rate_12 = sales_year[2012] / sales_year[2011] - 1sales_rate_13 = sales_year[2013] / sales_year[2012] - 1sales_rate_14 = sales_year[2014] / sales_year[2013] - 1print(sales_rate_12,sales_rate_13,sales_rate_14)# 设置字体#修改matplotlib 配置文件mpl.rcParams['font.sans-serif'] = ['SimHei']# 设置风格plt.style.use('ggplot')sales_rate = pd.DataFrame({'sales_all':sales_year, 'sales_rate':[0,sales_rate_12,sales_rate_13,sales_rate_14]})y1 = sales_rate['sales_all']y2 = sales_rate['sales_rate']x = [str(value) for value in sales_rate.index.tolist()]# 新建figure对象fig=plt.figure() # 新建子图1ax1=fig.add_subplot(1,1,1)# ax2与ax1共享X轴ax2 = ax1.twinx()ax1.bar(x,y1,color = 'blue')ax2.plot(x,y2,marker='*',color = 'r')ax1.set_xlabel('年份')ax1.set_ylabel('销售额')ax2.set_ylabel('增长率')ax1.set_title('销售额与增长率')plt.show()
结合上面的图表可以发现,2011年-2014年该超市的销售额在稳步上升,说明企业市场占有能力在不断提高,增长率2012年-2014年在增长后趋于平稳,说明企业经营在逐步稳定。同样我们根据销售和增长率,可以初步制定下一年度的销售额指标是:530万左右,当然具体销售额指标的制定还要再结合公司的整体战略规划。sales_area = data.groupby(by='Market')['Sales'].sum()sales_area.plot(kind='pie',autopct="%1.1f%%",title='2011年-2014年的总销售额占比')
从占比图中可以看出APAC地区销售额占比最大为28.4%,而Canada地区的销售额占比最少,并且只有0.5%,说明市场几乎没有打开,可以根据公司的总体战略部署进行取舍,从而根据销售额占比分配下一年的销售额指标sales_area = data.groupby(by=['Market','Order-year'])['Sales'].sum()sales_area# # # 将分组后的多层索引设置成列数据sales_area = sales_area.reset_index(level=[0,1])sales_area# # # 使用数据透视表重新整理数据sales_area = pd.pivot_table(sales_area, index='Market', columns='Order-year', values='Sales')sales_area# # # 绘制图形sales_area.plot(kind = 'bar',title = '2011年-2014年不同地区销售额对比')
从上面的图形中可以看出,各个地区的2011年-2014年销售总额均是增长的趋势,在APAC地区和EU地区的增长速度比较快速,可以看出市场占有能力也在不短增加,企业市场前景比较好,下一年可以适当加大运营成本,其他地区可以根据自身地区消费特点,吸取上面两个地区的运营模式category_sales_area = data.groupby(by=['Market','Category'])['Sales'].sum()category_sales_area# 将分组后的多层索引设置成列数据category_sales_area = category_sales_area.reset_index(level=[0,1])# 使用数据透视表重新整理数据category_sales_area = pd.pivot_table(category_sales_area, index='Market', columns='Category', values='Sales')# 绘制图形category_sales_area.plot(kind = 'bar', title = '不同类型产品在不同地区销售额对比', figsize= (10,8) )
所有产品按照三个大的类型进行了区分,分别是Furniture(家具)、Technology(电子产品)、Office Supplies(办公用品)。通过上图我们大致可以看出,在各大地区销售额都比较高是电子产品,可以根据企业的整体战略部署适当的加大对各地区该品类的投入,以便扩大优势。year_month = data.groupby(by=['Order-year','Order-month'])['Sales'].sum()# 将索引订单年转为一列数据sales_year_month = year_month.reset_index(level=[0,1])# 利用透视表的确定销售额预览表sales_year_month = pd.pivot_table(sales_year_month, index='Order-month', columns='Order-year', values='Sales')# 绘制图形sales_year_month.plot()
通过图表我们基本可以看出,该超市2011年-2014年每一年的销售额同比上一年都是上升趋势,所以很容易发现该超市的旺季是下半年,另外,我们在上半年销售额中发现6月份的销售额也是比较高的,所以可以在6月份开始加大一些运营成本,进而更大一步提高销售额,但是需要注意是下半年的7月份和10月份销售额会有明显的下降,可以针对这些下降的月份多举行一些营销活动。dt = data.drop_duplicates(subset=['Customer ID'])new_consumer = dt.groupby(by=['Order-year','Order-month']).size()new_consumer = new_consumer.reset_index(level=[0,1])sales_year_month = pd.pivot_table(new_consumer, index='Order-month', columns='Order-year', values=0)print(sales_year_month)
根据图表可以看出,从2011年开始到2014年总体看,每一年的新增客户数是逐年减少的趋势,可以看出该网站对保持老用户是有效的,网站的运营状况较为稳定。但是,新客户获取率比较低,可以不定期的进行主动推广营销,从而增加新客户数# 获取2014年数据data_14 = data [data ['Order-year']==2014]# 获取三列数据#rfm 用这三列数据就可以制定rfmdata_14 = data_14[['Customer ID','Order Date','Sales']]data_14.head()
由于RFM模型分别对应着Customer ID、Order Date、Sales这三个字段,所以我们只获取这三个字段的数据。# 排序函数def order_sort(group):# print(group.sort_values(by='Order Date'))[-1:] return group.sort_values(by='Order Date')[-1:]# 将数据按客户ID分组data_14_group = data_14.groupby(by='Customer ID',as_index = False)# 将每个分组对象的数据排序,并取出日期最大的数据data_max_time = data_14_group.apply(order_sort)print(data_max_time.head())
第三步,经过分组之后同样可以快速算出RFM模型中的F(购买次数)和M(销售额总数)。# 为数据添加F列data_max_time['F'] = data_14_group.size().values# print(data_14_group.size())data_max_time['F'] # 为数据添加M列data_max_time['M'] = data_14_group.sum()['Sales'].valuesdata_max_time.head()
第四步,目前已经获取到了2014年每个客户最后一次的时间了,现在需要根据假定同时间计算出最近一次交易时间的间隔。# 确定统计日期stat_date = pd.to_datetime('2014-12-31')# 计算最近一次交易时间的间隔r_data = stat_date - data_max_time['Order Date']# 为数据添加R列data_max_time['R'] = r_data.valuesprint(data_max_time.head())
第五步,经过上面四步分别计算出来RFM各个维度的数值,现在可以根据经验以及业务场景设定分值的给予区间,本项目中给定F的区间为[0,5,10,15,20,50],然后采用5分制的评分规则与上面分值区间一一对应,例如:1-5对应的为1、5-10对应的为2,依次类推。section_list_F = [0,5,10,15,20,50]# 根据区间设置评分grade_F = pd.cut(data_max_time['F'],bins=section_list_F,labels=[1,2,3,4,5])# 添加FS评分列data_max_time['F_S'] = grade_F.valuesdata_max_time.head()
第六步,根据第五步的思路,首先确定M维度的区间[0,500,1000,5000,10000,30000],然后采用5分制的评分规则与上面分值区间一一对应。同理,确定R维度的区间为[-1,32,93,186,277,365],但是R维度所对应的评分顺序应该与F和M的相反。# 设置M维度的评分section_list_M = [0,500,1000,5000,10000,30000]# 根据区间设置评分grade_M = pd.cut(data_max_time['M'],bins=section_list_M,labels=[1,2,3,4,5])# 添加FS评分列data_max_time['M_S'] = grade_M.valuesdata_max_time# 设置R维度的评分import datetimesection_list_R = [datetime.timedelta(days=i) for i in [-1,32,93,186,277,365]]# 根据区间设置评分grade_R = pd.cut(data_max_time['R'],bins=section_list_R,labels=[5,4,3,2,1])# 添加FS评分列data_max_time['R_S'] = grade_R.valuesdata_max_time.head()
第七步,上面给每条数据的RFM都设置了对应的评分,现在需要根据每一个维度,计算出对应的平均分,然后用对应的分数与平均值进行对比,大于平均分的值的标记成1,同理小于平均分的值的标记成0# 设置F维度高低值data_max_time['F_S'] = data_max_time['F_S'].values.astype('int')# 根据评分平均分设置判别高低grade_avg = data_max_time['F_S'].values.sum()/data_max_time['F_S'].count()grade_avg# # 将高对应为1,低设置为0data_F_S = data_max_time['F_S'].where(data_max_time['F_S']>grade_avg,0)data_max_time['F_high-low']=data_F_S.where(data_max_time['F_S']<grade_avg,1).valuesdata_max_time['F_high-low']# # 设置M维度高低值data_max_time['M_S'] = data_max_time['M_S'].values.astype('int')# # 根据评分平均分设置判别高低grade_avg = data_max_time['M_S'].values.sum()/data_max_time['M_S'].count()# # 将高对应为1,低设置为0data_M_S = data_max_time['M_S'].where(data_max_time['M_S']>grade_avg,0)data_max_time['M_high-low']=data_M_S.where(data_max_time['M_S']<grade_avg,1).values# # 设置R维度高低值data_max_time['R_S'] = data_max_time['R_S'].values.astype('int')# 根据评分平均分设置判别高低grade_avg = data_max_time['R_S'].values.sum()/data_max_time['R_S'].count()# 将高对应为1,低设置为0data_R_S = data_max_time['R_S'].where(data_max_time['R_S']<grade_avg,0)data_max_time['R_high-low']=data_R_S.where(data_max_time['R_S']>grade_avg,1).valuesdata_max_time.head()
第八步,现在基本完成对每个数据的RFM高低值的设置,记下来就可以根据RFM的高低值对每个用进行类型标记了# 截取部分列数据data_rfm = data_max_time.loc[:,['Customer ID','R_high-low','F_high-low','M_high-low']]def get_sum_value(series):# print([str(i) for i in series.values.tolist()]) return ''.join([str(i) for i in series.values.tolist()[1:]])# 添加RFM字符串列data_rfm['data_rfm'] = data_rfm.apply(get_sum_value, axis=1)data_rfm['data_rfm']dic = { '111':'重要价值客户', '101':'重要发展客户', '011':'重要保持客户', '001':'重要挽留客户', '110':'一般价值客户', '100':'一般发展客户', '010':'一般保持客户', '000':'一般挽留客户',}# # RFM字符串数据映射成对应类型文字data_rfm['data_rfm'] = data_rfm['data_rfm'].map(dic)print(data_rfm.head())print(data_rfm.tail())
经过以上步骤,已经给所有的用户都设置好RFM的标签,现在让我们来看一下2014年不同类型人群占比。size = data_rfm.groupby(by='data_rfm').size()size = size.to_frame()size['rfm_pct'] = ["%.2f%%" % (i/sum(size.values) * 100) for i in size.values]print(size)
结论依据:关键词:分析,数据,销售