1. 项目背景
通过分析销售数据来了解在线销售业务的消费情况,分析用户消费数据来分析用户的消费行为,为用户推荐相匹配的商品。
2. 数据概况
2.1. 加载数据
data = pd.read_csv("./data/某电商电子产品销售数据分析.csv")
data.head()
2.2. 数据说明
列名 | 类型 |
---|---|
下单时间 | datatime |
订单编号 | str |
产品编号 | str |
类别编号 | str |
类别 | str |
品牌 | str |
价格 | float65 |
用户编号 | str |
年龄 | int64 |
性别 | str |
省份 | str |
3. 数据清洗与整理
3.1. 数据类型转换
data['下单时间'] = pd.to_datetime(data['下单时间'])
data[['订单编号','产品编号','类别编号','用户编号']] = data[['订单编号','产品编号','类别编号','用户编号']].astype(str)
data['年龄'] = data['年龄'].astype(int)
3.2. 空值和重复值
数据集中有空值,无重复值
# 类别为空的数据,使用类别编码填充
data['类别'] = data['类别'].fillna(data['类别编号'])
# 品牌为空的数据,填充 unknoun
data['品牌'] = data['品牌'].fillna('unknown')
3.3. 删除无用列
# 第一二列是无用列
data.drop(data.columns[[0,1]], axis=1, inplace=True)
3.4. 新增列
data['month'] = data['下单时间'].dt.month
data['hour'] = data['下单时间'].dt.hour
data['weekday'] = data['下单时间'].dt.weekday
data['weekend'] = ((data['weekday'] == 5) | (data['weekday'] == 6)).astype(int)
4. 探索性分析
4.1. 销售情况
4.1.1. 月度
经分析,数据集中包含1307条 1970 年数据,其他为2022年数据(占比99.66%)
for year in data['下单时间'].dt.year.unique():
cnt = data[data['下单时间'].dt.year==year].shape[0]
print(f'{year}年数据有:{cnt}, 占数据集比例:{format(cnt/data.shape[0], '.2%')}')
按月统计
绘制图形
第二季度开始,订单量开始起量,人均消费也随之提升,4月份销量略有回落后,5月份极速爬升,7-9月份是消费高峰期,消费人数和消费额双高,而人均消费金额从4月份开始逐步爬升。
接下来再按看看每个月各个年龄的消费人数
- 观测各条曲线 7、8这两个月,25岁-30岁这个年龄段的人相较于其他月份,较为活跃
- 8月份40岁-45岁年龄段的人平稳增长
4.1.2. 区域
df_privince = data2022.groupby('省份')[['订单编号','用户编号','价格']].agg({'订单编号':'count','价格':'sum','用户编号':'nunique'}).rename(columns={'订单编号':'销售数量','用户编号':'购买人数','价格':'销售额'}).sort_values('销售额',ascending=False)
df_privince
广东省、上海、北京三个地区是店铺主要的收入来源,无论是是用户数、销售额和订单数的占比之和都超过了50%。
4.1.3. 性别
消费者性别比例,男女占比1:1,相差不大。
4.1.3. 一天内的销售情况
统计一天24小时内的消费数据,发现早上7-11点是用户的购买高峰,但是整体上看似乎与我们的消费习惯不太一致,一般来说晚20-21点是一个消费高峰,但这里呈现出来却是一天的谷底。
这里我随机取某一天(6-18)的样本数据看一些,整个消费情况的分布大致相同。
4.1.5. 工作日与周末
wkend_data = data2022.groupby(['weekend','hour'])['订单编号'].count().reset_index()
plt.figure(figsize=(10,6))
sns.pointplot(x='hour', y='订单编号', hue='weekend', data=wkend_data, ci=None)
plt.xlabel('小时'), plt.ylabel('订单量')
plt.title('工作日和周末订单量分析')
plt.legend(title='1-周末,0-工作日')
plt.grid(linestyle='--', alpha=0.5)
plt.show()
周末的订单量波峰明显比工作日平缓,说明工作日人们的购物行为较高。人们更热衷于在7-11点购物。
4.2. 热销分析
4.2.1. 热销类别
店铺销量最好的品类是smartphone和notebook,这两类商品占销售额的48.8%。
4.2.2. 热销产品
以下是按销量TOP10的商品,其中有8个是smartphone,与热销类品TOP1的结果相符。
可视化
4.2.3. 热销品牌
以下是店铺销售所有商品的品牌销量的TOP10
4.3. 用户分析
4.3.1. 用户消费次数与消费金额的关系
4.3.2. 新老用户比例
rnt = data2022.groupby(['用户编号']).agg({'下单时间':['min','max']})
rnt_new_user = rnt[rnt['下单时间']['min']==rnt['下单时间']['max']]
rnt_old_user = rnt[rnt['下单时间']['min']!=rnt['下单时间']['max']]
new_percent = round(rnt_new_user.shape[0]/rnt.shape[0],2)
old_percent = round(rnt_old_user.shape[0]/rnt.shape[0],2)
print(new_percent, old_percent)
dic_on = {'新用户':new_percent,'老用户':old_percent}
df_on = pd.DataFrame(dic_on, index=[0])
sizes = df_on.values.flatten() # 将 DataFrame 的值转换为一维数组
labels = df_on.columns.tolist() # 将列名转换为列表
plt.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90)
plt.title('新老用户比')
plt.legend()
plt.show()
df_on
这里的新老用户的判断依据采用下单时间的最大值与最小值是否相等,当min和max相同,即是新用户。可见店铺的新用户占比46%,还是挺高的。
4.3.3. RFM分层
from datetime import timedelta
data_rfm = data2022.copy()
current_date = data_rfm['下单时间'].max() + timedelta(days=1)
# 计算每个用户最近消费时间
df_rfm = data_rfm.groupby('用户编号').agg({'下单时间': lambda x: (current_date - x.max()).days, '订单编号':'count', '价格':'sum'})\
.rename(columns={'下单时间':'Recency','订单编号':'Frequency','价格':'Monetary'})
# 分箱
r=range(5,0,-1) # 值越小越好 [4,3,2,1]
f=range(1,6) # 值越大越好 [1,2,3,4]
m=range(1,6)
# 使用cut函数分箱,将rfm 划分成5个区间
r_quartiles = pd.cut(df_rfm['Recency'], bins=5,labels=r)
f_quartiles = pd.cut(df_rfm['Frequency'], bins=5,labels=f)
m_quartiles = pd.cut(df_rfm['Monetary'], bins=5,labels=m)
# 构造 R/F/M 列
df_rfm=df_rfm.assign(R=r_quartiles.values)
df_rfm=df_rfm.assign(F=f_quartiles.values)
df_rfm=df_rfm.assign(M=m_quartiles.values)
此时的R/F/M值,均有5值划分,现在将这些数值与均值比较,简化分类结果,以[0 1]来划分。
# RFM分别计算score的平均值,>mean,=1,否则=0
r_mean = np.mean(df_rfm['R'].to_list())
f_mean = np.mean(df_rfm['F'].to_list())
m_mean = np.mean(df_rfm['M'].to_list())
df_rfm['R'] = df_rfm['R'].apply(lambda x: '1' if x>=r_mean else '0')
df_rfm['F'] = df_rfm['F'].apply(lambda x: '1' if x>=f_mean else '0')
df_rfm['M'] = df_rfm['M'].apply(lambda x: '1' if x>=m_mean else '0')
df_rfm['RFM'] = df_rfm['R']+df_rfm['F']+df_rfm['M']
# rfm分类后的标签映射
def rfm_label(x):
if x == '111':
return '重要价值客户'
elif x == '101':
return '重要发展客户'
elif x == '011':
return '重要保持客户'
elif x == '001':
return '重要挽留客户'
elif x == '110':
return '一般价值客户'
elif x == '100':
return '一般发展客户'
elif x == '010':
return '一般保持客户'
elif x == '000':
return '一般挽留客户'
df_rfm['RFM_label'] = df_rfm['RFM'].apply(lambda x : rfm_label(x))
rfm_cnt = df_rfm.groupby('RFM_label').agg({'RFM_label':'count'}).rename(columns={'RFM_label':'数量'}).sort_values(by='数量', ascending=False)
从图中可以看出,绝大部分的用户属于一般发展用户与一般挽留用户。而对于一般发展用户,根据前述分析,这部分用户多为新用户,是具有推广价值的用户群体,可以考虑通过一些营销手段(比如试用、评测等)提高此类用户兴趣,以此来挖掘新用户需求。而一般挽留客户是即将流失的一次性客户,不必花费太多服务资源。
因此,可以看出用户流失较多,但是可发展的用户同样是非常多的,新用户留存是平台店铺亟需解决的问题。想要提高收入,对一般发展用户入手是成本少,效率高的选择,提高其消费客单价或消费频次,将这部分客户转化为一般价值客户或重要发展客户,是较为理想的。
5. 总结
综上分析,得出如下结论:
1、7-9月份是消费高峰期,正值暑假期间。而每天的消费高峰期则集中在7-11点之间。建议,通过一些预约优惠券,进一步促进18点-21点间的消费晚高峰的消费。
2、广东、上海、北京是主要的销售区域,占据了店铺销售额的半壁江山,其他地区的销售表现相对均衡,但与前三个地区差距明显。建议对湖南、天津、江苏等地区推行区域性优惠政策,提升这些地区的销量。
3、smartphone是销量和销售额占绝对优势的品类,其次是notebook类,这两类品类贡献了48.8%的销售额。
4、从品牌商来看,Samsung是销量之冠,销量相当于排名第2-4的apply、ava、lg和xiaomi之和,9个月销量达 60761。
5、从用户分析来看,店铺新老用户比例5:5分,绝大部分的用户属于一般发展用户与一般挽留用户,符合新用户比较高的特性。建议进行新用户促活留存的营销活动,通过客户兴趣分析,推荐更高客单价的产品以及满减券提高用户订单客单价;或者使用不定期赠送折扣券和满减券,提升用户的消费次数,从而将新用户转换为价值客户或重要发展客户。