项目三 _____(超市电商数据分析项目)
引言
随着电子商务的快速发展,超市电商作为零售行业的重要组成部分,扮演着愈发重要的角色。超市电商平台每天产生大量的数据,包括用户购买记录、浏览行为、促销活动效果等,这些数据蕴含着宝贵的信息和商业洞察。本文旨在通过对超市电商数据的深入分析,揭示潜在的消费趋势、用户偏好以及销售策略的优化方向。
本实践将基于实际超市电商数据集,运用数据挖掘和统计分析方法,探索用户购买行为模式、热门商品推荐机制以及促销活动效果评估等方面。通过深入挖掘数据背后的规律和趋势,旨在为超市电商平台提供数据驱动的决策支持,提升用户体验,优化营销策略,实现商业增长。
本实践将首先介绍超市电商数据的来源和特点,然后阐述分析方法和技术工具的选择,最后展望研究的预期成果和对超市电商行业的实际意义。
数据源概况
数据源概况
| Row ID:行编号;| Postal Code:邮编;| Market:商店所属区域;|
| Order ID:订单ID;| Region:商店所属州;| Product ID:产品ID;|
| Order Date:订单日期;| Category:产品类别;| Country:客户所在国家;|
| Ship Date:发货日期;| Product Name:产品名称;| Sales:销售额;|
| Ship Mode:发货模式;| Quantity:销售量;| Discount:折扣;|
| Customer ID:客户ID;| Profit:利润;| Shipping Cost:发货成本;|
| Customer Name:客户姓名;| Order Priority:订单优先级;|
| Segment:客户类别;| City:客户所在城市;| State:客户城市所在州;|
| Country:客户所在国家;|
读取、清洗数据
使用pandas的read_csv读取数据后,查看各列数据的空值情
况,发现Postal Code字段(邮编字段)有空值,而且这一
列不重要,所以首先删除掉Postal Code列;
data = pd.read_csv(‘market.csv’,encoding=‘ISO-8859-1’)
data.isnull().sum()
data.drop(‘Postal Code’,axis=1,inplace=True)
使用DataFrame对象的describe()方法,没有发现异常数
据,所以,不必处理;
data.describe()
将Order Date订单日期字段的数据修改为datetime类型;
temp = pd.to_datetime(data[‘Order Date’], format=‘%m/%d/%Y’,errors=‘coerce’).fillna(pd.to_datetime(data[‘Order Date’], format=‘%d-%m-%Y’,errors=‘coerce’))
data[‘Order Date’] = temp.dt.date
为了后续分析方便,从订单日期中分别提取年、月、季度数
据,并添加三个列用来存取年、月、季度信息,分别
为:’Order-year’,’Order-month’,’quarter’ 。
data[‘Order-year’] = temp.dt.year
data[‘Order-month’] = temp.dt.month
data[‘Order-quarter’] = temp.dt.quarter
将处理后的数据导入到一个CSV文件中。
data.to_csv(‘market_cleaned.csv’, index=False)
数据分析及结果解释
问题一 __ 利润分析
先根据年和月进行分组,再分别提取各年份(2011-2014
年)的数据,分析各年份对应月的利润情况。
profit_analysis = df.groupby([‘Order-year’, ‘Order-month’])[‘Profit’].sum().unstack()
绘制利润分析的热力图
sns.heatmap(profit_analysis, annot=True, fmt=“.2f”, cmap=“YlGnBu”)
分组:使用groupby()方法按照指定的列进行分组。
grouped = df.groupby(‘列名’)
聚合运算:对分组后的数据进行聚合运算,如求和、平均值等。
result = grouped.sum()
多个Series对象合并成一个DataFrame
df_concatenated = pd.concat([s1, s2], axis=1)
问题二 __ 客单价分析
客单价指商场每一个顾客平均购买商品的金额,客单价反映顾客的购买水平;
计算公式为:客单价=销售额÷成交顾客数
通过计算并展示每年的客单价数据,可以反映每年的顾客购买水平。
计算每年的唯一顾客数量
annual_customers = data_cleaned.groupby(‘Year’)[‘Customer ID’].nunique().reset_index()
计算客单价
annual_data[‘Average Spending per Customer’] = annual_data[‘Total Sales’] / annual_data[‘Unique Customers’]
绘制客单价的柱状图
ax3.bar(annual_data[‘Year’], annual_data[‘Average Spending per Customer’], color=‘blue’, alpha=0.6, label=‘客单价’)
ax3.set_xlabel(‘年份/年’)
ax3.set_ylabel(‘销售额/元’)
ax3.legend(loc=‘upper left’)
我们可以看出:客单价逐年上升,说明顾客的购买水平是逐年增加的。
去除重复行:使用drop_duplicates()方法来去除DataFrame中的重复行。
df_no_duplicates = df.drop_duplicates()
问题三 __ 每年销售额与销售额的增长率分析
通过年份分组,计算每年的销售额总和,
销售额增长率 = (本年销售额-上年销售额) / 上年销售额 * 100%
计算每年的总销售额
annual_sales = data_cleaned.groupby(‘Year’)[‘Sales’].sum().reset_index()
计算销售额增长率
annual_sales[‘Growth Rate’] = annual_sales[‘Total Sales’].pct_change() * 100
绘制总销售额的柱状图
ax1.bar(annual_data[‘Year’], annual_data[‘Total Sales’], color=‘blue’, alpha=0.6, label=‘总销售额’)
ax1.set_xlabel(‘年份/年’)
ax1.set_ylabel(‘销售额/元’, color=‘blue’)
ax1.tick_params(axis=‘y’, labelcolor=‘blue’)
ax1.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, _: f’{int(x/1e6)}'))
绘制销售额增长率的折线图
ax2 = ax1.twinx()
ax2.plot(annual_data[‘Year’], annual_data[‘Growth Rate’], color=‘red’, marker=‘*’, label=‘增长率’)
ax2.set_ylabel(‘增长率 (%)’, color=‘red’)
ax2.tick_params(axis=‘y’, labelcolor=‘red’)
我们可以看出:该超市在2011-2014年销售额在稳步上升,说明企业市场占有能力在不断提高; 2012-2014年的增长率在增长后趋于平稳,说明企业经营在逐步稳定。
将条形图与折线图在一幅图上展示:通过设置不同的y轴。
创建子图
fig, ax1 = plt.subplots()
ax1.bar(categories, values_bar, color=‘b’, label=‘Bar Chart’)
创建第二个y轴
ax2 = ax1.twinx()
ax2.plot(categories, values_line, color=‘r’, marker=‘o’, label=‘Line Chart’)
问题四 __ 分析各个地区分店的销售额
查看不同区域分店的总销售额占比
使用了groupby()对‘Market’进行分组,并计算每个分组中’Sales’列的总和。
df=df.groupby(‘Market’)[‘Sales’].sum()
绘制饼图,展示了不同市场销售总额的占比情况。
plt.pie(df,labels=df.index,autopct=‘%1.1f%%’)
我们可以从该饼图可以看出:APAC、BJ两个地区的销售额比例很高,总计占51.6%,Canada的销售总额占比最小,只有0.5%,可以增加对该地区的营销。
分别对各个区域每年销售额分析
按照’Market’和’Order-year’两列进行分组
yearly =df.groupby([‘Market’,‘Order-year’])[‘Sales’].sum()
提取到不同年份的数据
y1 = yearly[yearly[‘Order-year’]==2011]
y2 = yearly[yearly[‘Order-year’]==2012]
y3 = yearly[yearly[‘Order-year’]==2013]
y4 = yearly[yearly[‘Order-year’]==2014]
绘制了四年的年销售数据的柱状图
plt.bar(x-0.4,y1[‘Sales’],0.2,label=‘2011’)
plt.bar(x-0.2,y2[‘Sales’],0.2,label=‘2012’)
plt.bar(x,y3[‘Sales’],0.2,label=‘2013’)
plt.bar(x+0.2,y4[‘Sales’],0.2,label=‘2014’)
我们可以由上面的条形图看出,各个地区2011-2014年的销售总额均是增长趋势, 其中APAC地区和EU地区的增长速度较快,市场前景较好,下一年可以适当 加大运营成本。
分别对各个区域的不同类型产品销售额分析
按照’Market’和’Category’两列进行分组
yearly =df.groupby([‘Market’,‘Order-year’])[‘Sales’].sum()
提取到不同类型的数据
p1 = prod[prod[‘Category’]‘Furniture’]
p2 = prod[prod[‘Category’]‘Office Supplies’]
p3 = prod[prod[‘Category’]==‘Technology’]
绘制了三种的类型数据的柱状图
plt.bar(x-0.2,p1[‘Sales’],0.2,label=‘Furniture’)
plt.bar(x,p2[‘Sales’],0.2,label=‘Office Supplies’)
plt.bar(x+0.2,p3[‘Sales’],0.2,label=‘Technology’)
由上图可看出,除了Canada地区以外,各大地区销售额都比较高的是电子产品,可以适当加大对各地区(除Canada地区)该种类的投入,以便扩大优势。
透视表的创建:
pivot_table = df.pivot_table(index=’ ‘, columns=’ ‘, values=’ ', aggfunc=‘sum’)
透视表的作用:
透视表可以对数据进行重塑和重新排列,使得数据更易于分析和理解。
问题五 __ 销量分析与销售淡旺季分析
销量分析
通过表格展示,2011-2014年各月份的详细销量数据
根据年和月进行分组,分析每年的月销量情况
quantity = df.groupby([‘Order-year’, ‘Order-month’])[‘Quantity’].sum().unstack()
绘制销量分析的热力图
sns.heatmap(quantity, annot=True, fmt=“.2f”, cmap=“YlGnBu”)
提取符合特定条件的行:Pandas 中的条件筛选功能。
filtered_df = df[df[‘Year’] == 2011]
问题六 __ 淡旺季分析(通过销售额分析)
通过年月销售额的变化趋势分析淡旺季
年和月进行分组,分析每年的月销售额情况
sale_analysis = df.groupby([‘year’, ‘month’)[‘Sales’].sum().unstack()
创建一个折线图
years = sale_analysis.index
for year in years:
data_year = sale_analysis.loc[year]
plt.plot(data_year.index, data_year.values, label=str(year))
由上面的折线图可以看出,该超市2011-2014年每一年的销售额同比上一年都是上升趋势,而且该超市的旺季是下半年;在上半年的销售额中发现6月份的销售额较高,可以在6月份开始加大一些运营成本;尤其需要注意,下半年的7月份和10月份销售额会有明显下降,可以针对这两个月份举行一些营销活动,以期提高销售额。
通过透视表绘制折线图:创建透视表 pivot_table,然后使用 plot() 绘制折线图。
创建透视表
pivot_table = df.pivot_table(index=’ ‘, columns=’ ‘, values=’ ',aggfunc=‘sum’)
绘制折线图
pivot_table.plot(kind=‘line’)
问题七 __ 分析新老客户数
新老客户的定义:将只要消费过的客户定义为老客户,否则就是新客户。
根据Customer ID列数据进行重复行的删除, 保证数据集中所有的客户ID都是唯一的,根据此数据再通过年、月进行分组,通过透视表分析新老客户数。
创建透视表
pivot_table = pd.pivot_table( customers_with_purchases,values=‘Customer ID’,
index=‘Order-Month’,columns=‘Order-Year’,aggfunc=‘count’,fill_value=0)
由于上述透视表的人数和远远小于总的记录数,说明超市对保持老客户较为有效 也间接说明了超市的运营状况较为稳定;还可以发现,2011-2014年每年的新增客户数呈逐年减少的趋势,新客户获取率比较低,因此,可以进行主动推广营销,从而增加新客户数;
定义新老客户:
新客户:在特定时间段(比如一个月或一年)内第一次购买的客户。
老客户:在之前的时间段内已经购买过商品或服务的客户。
计算新老客户数:
首先,需要识别客户的购买行为,可以通过订单记录或者客户信息来判断客户是否是新客户还是老客户。根据定义,统计每个时间段内新客户和老客户的数量。
分析新老客户比例:
计算新客户和老客户的比例,了解新客户对总客户数的贡献比例。这可以帮助企业评估客户获取的效果,以及对客户保留的影响。
问题八 __ 用户数据分析
客户类型占比分析
绘制饼图查看不同客户的类型占比,其中,'Segment’字段代表客户类别。
计算不同客户类型的数量
customer_counts = df[‘Segment’].value_counts()
绘制饼图
plt.pie(customer_counts,labels=customer_counts.index,autopct=‘%1.2f%%’)
我们可以看出:Consumer类型的消费者的客户占比最多,达51.7%,Home Office占比最小,可加强对该类型的客户进行营销宣传。
各年不同类型消费者数量分析
按照客户种类和年份分组,并计算每组的用户数量
grouped = df.groupby([‘Segment’, ‘year’])[‘Customer ID’].count().unstack()
绘制条形图
for i, year in enumerate(grouped.columns):
ax.bar(index + i * bar_width, grouped[year], width=bar_width, label=year)
由图分析出,每种类型的客户数量在逐年增长,说明客户的结构类型趋于良好。
问题九 __ 不同类型的客户每年的销售额分析
按照客户种类和年份分组,并计算每组的销售额之和
grouped = df.groupby([‘Segment’, ‘Order-year’])[‘Sales’].sum().unstack()
绘制条形图
for i, year in enumerate(grouped.columns):
ax.bar(index + i * bar_width, grouped[year], width=bar_width, label=year)
由上面可知,各类型的消费者的销售额在逐步上升,其中以普通消费者的销售额最多, 可能是因为普通消费者最多的缘故。
对分组数据进行聚合的方法:
-
sum():对分组数据进行求和操作,适用于数值型数据。
-
mean():计算分组数据的平均值,对于数值型数据有意义。
-
count():计算分组中的非缺失值的数量,适用于统计每个分组的样本数量。
-
min()和max():分别计算分组数据的最小值和最大值,适用于数值型数据。
-
median():计算分组数据的中位数,对于数值型数据有意义。
-
std()和var():分别计算分组数据的标准差和方差,用于衡量数据离散程度。
-
agg():可以使用自定义函数对分组数据进行聚合操作。
-
apply():允许对每个分组应用自定义函数,更加灵活。
-
pivot_table():可以根据一个或多个键对数据进行聚合,类似透视表功能。
-
transform():根据分组对数据进行转换,可以用于分组平均值的组内均值。
问题十 __ 用户价值度RFM模型分析
RFM是一个经典的客户分群模型,含义如下:
R——Recency:客户最近一次消费时间
F——Frequency:客户消费的频次
M——Monetary:消费金额
客户价值类型:
重要价值客户:RFM3个值都很高,是平台重点维护的客户。
重要保持客户:最近一次消费时间较远,消费金额和消费频次比较高。
重要发展客户:最近有消费,且整体消费金额高,但是购买不频繁。
重要挽留客户:消费金额较高,消费频次偏低,而且已经很久没有消费行为了。
一般价值客户:多次频繁购买,但是购买的商品价格都较低。
一般保持客户:频繁浏览,但是很久没有成交了。
一般发展客户:有近期购买行为,但购买商品利润低而且不活跃。
一般挽留客户:RFM3个值都低,已经是流失的客户。
根据客户对贡献度排序是:重要价值客户 > 重要保持客户 > 重要发展客户 > 重要挽留客户 > 一般价值客户 > 一般保持客户 > 一般发展客户 > 一般挽留客户。
以2014年的消费数据为例(其他年份类似):
提取出2014年的订单数据后,分别添加F、M、R三个维度的数据列,然后再分别对三个维度划定评级,添加三个列,并将每条记录的三个维度的评分进行0、1标记(大于平均分记为1,小于平均分的记为0),最后对每个客户进行价值类型标记;对不同价值的客户类型进行占比分析。
计算RFM值
current_date = data_2014[‘Order Date’].max() + pd.Timedelta(days=1)
R值(最近一次消费时间)
recency = data_2014.groupby(‘Customer ID’)[‘Order Date’].apply(lambda x: (current_date - x.max()).days).reset_index()
recency.columns = [‘Customer ID’, ‘Recency’]
F值(消费频次)
frequency = data_2014.groupby(‘Customer ID’)[‘Order ID’].count().reset_index()
frequency.columns = [‘Customer ID’, ‘Frequency’]
M值(消费金额)
monetary = data_2014.groupby(‘Customer ID’)[‘Sales’].sum().reset_index()
monetary.columns = [‘Customer ID’, ‘Monetary’]
RFM值评级(大于平均值记为1,小于等于平均值记为0)
rfm[‘R_Score’] = (rfm[‘Recency’] <= rfm[‘Recency’].mean()).astype(int)
rfm[‘F_Score’] = (rfm[‘Frequency’] > rfm[‘Frequency’].mean()).astype(int)
rfm[‘M_Score’] = (rfm[‘Monetary’] > rfm[‘Monetary’].mean()).astype(int)
客户价值类型标记
def rfm_segment(row):
if row[‘R_Score’] == 1 and row[‘F_Score’] == 1 and row[‘M_Score’] == 1:
return ‘重要价值客户’
elif row[‘R_Score’] == 0 and row[‘F_Score’] == 1 and row[‘M_Score’] == 1:
return ‘重要保持客户’
elif row[‘R_Score’] == 1 and row[‘F_Score’] == 0 and row[‘M_Score’] == 1:
return ‘重要发展客户’
elif row[‘R_Score’] == 0 and row[‘F_Score’] == 0 and row[‘M_Score’] == 1:
return ‘重要挽留客户’
elif row[‘R_Score’] == 1 and row[‘F_Score’] == 1 and row[‘M_Score’] == 0:
return ‘一般价值客户’
elif row[‘R_Score’] == 0 and row[‘F_Score’] == 1 and row[‘M_Score’] == 0:
return ‘一般保持客户’
elif row[‘R_Score’] == 1 and row[‘F_Score’] == 0 and row[‘M_Score’] == 0:
return ‘一般发展客户’
elif row[‘R_Score’] == 0 and row[‘F_Score’] == 0 and row[‘M_Score’] == 0:
return ‘一般挽留客户’
else:
return ‘未知’
绘制客户类型占比分析图
segment_counts.plot.pie(autopct=‘%1.1f%%’, startangle=90)
由上面的分析可知:对于该超市来说,重要价值客户和重要保持客户的总和已经超过35%;但是一般发展客户的比例也很高,这种客户很可能是刚注册的客户或者接近流失的客户,针对刚注册的用户可以采取各种新人优惠福利,提高新客户了解平台的动力,针对接近流失的客户应该追溯客户过去不满的原因,对平台进一步完善。
分组对象的apply()方法的使用:
在每个分组上应用一个函数,然后将每个组的结果合并成一个新的数据结构。
grouped = df.groupby(‘key’)
result = grouped.apply(func)
问题十一 __ 客户群体与产品种类的关系分析
通过客户群体类别(Segment字段)与产品类别(Category字段)分组,对销售额数据进行分析。
对 df 按照 Category 和 Segment 进行分组,对组内的 Sales 列进行求和操作。
grouped_data = df.groupby([‘Category’,‘Segment’])[‘Sales’].sum().reset_index()
创建 catplot
cat_plot = sns.catplot(x=‘Segment’, y=‘Sales’, hue=‘Category’, kind=‘bar’)
通过上图展示的结果可以看出,不同客户群体对各种产品的消费额次序由高到低是: 科技产品(Technology)> 家具产品(Furniture)>办公用品产品(Office Supplies)。因此,可以2加大对科技产品的推广;在三种客户类型中,个人消费者(Consumer)对各种产品的消费都是最高的,因此,可以保持对个人消费者群体的策略;而居家办公群体(HomeOffice)在三种产品的销售额较低,以针对该用户群体进行更好的营销推广。
通过多个字段分组并进行聚合运算、重置索引:
agg() 方法对 列进行求和操作。使用 reset_index() 方法重新设置索引。
问题十二 __ 发货时间与发货成本分析
提取发货日期字段(Ship Date字段)的年、月信息,并整理发货年、发货月的销售总额,分析发货成本,并预测进货成本。
对df 按照 Ship-year 和 Ship-month 列分组,然后对组内的 Sales 列求和操作。
sales = df.groupby([‘Ship-year’, ‘Ship-month’])[‘Sales’].sum()
对df 按照 Ship-year 和 Ship-month 列分组,组内 Shipping Cost 列进行求和。
shipping = df.groupby([‘Ship-year’, ‘Ship-month’])[‘Shipping Cost’].sum()
创建一个折线图
for year in years:
data_year = merged_data[merged_data[‘Ship-year’] == year]
plt.plot(data_year[‘Ship-month’], data_year[‘Shipping Cost’], label=str(year))
创建透视表
pivot_table = pd.pivot_table( merged_data,values=‘Shipping Cost’,
index=‘Ship-month’, columns=‘Ship-year’,fill_value=0)
由上面的透视表和折线图可以看出,2011-2014年的发货成本逐年上升,而且每年的各个月份的发货成本也呈上升趋势;但是,2015年出现了新的情况!2015年只有7个月的统计数据,但是这7个月的发货成本逐月降低,而且远远小于前4年的发货成本,这很可能是由于2015年物流业的飞速发展使得发货成本大大降低,所以,之后的进货成本也极有可能大大降低!
透视表的好处:是一种数据汇总工具,可以帮助用户更好地理解和分析数据。
代码展示
原数据集及代码详情见码云:
码云地址:https://gitee.com/wswswsw222/project-three
项目总结
在超市电商数据分析项目中,数据收集、清洗和预处理是首要步骤。随后,通过数据探索性分析和建模分析,可以深入了解销售趋势、客户偏好等关键信息。透视表和分组聚合等技术可以帮助对销售数据进行多维度的分析,例如按时间、产品类别、客户等维度进行汇总和分析,从而发现潜在的销售机会和业务趋势。数据可视化则有助于向利益相关者传达数据洞察和发现。最终,通过数据分析,可以提出产品推荐策略、促销活动等建议,帮助超市电商更好地服务客户并提升业绩。数据分析报告的撰写和结果解释也是项目中不可或缺的一环,它有助于向管理层和团队成员传达数据分析的结论和建议,为业务决策提供支持。