黑色星期五销售数据分析
1. 提出问题
数据分析不是为了分析而分析,而是要通过数据分析来达到某种目的。对黑色星期五销售数据进行分析,是希望通过数据分析来更好地了解客户购买行为。
针对数据提供的信息,主要从这几个方面去分析:
- 年龄
- 性别
- 城市
- 居住城市年数
- 职业
- 婚姻状况
- 商品和类别
前面6个是分析用户画像,最后一个是从商品的角度分析。
2. 数据理解
2.1 数据来源
数据集来自kaggle平台的黑色星期五销售数据Black-Friday,该数据集是零售商店中进行交易的样本。
2.2 字段说明
该数据集总共包含12个字段,如下:
序号 | 字段名 | 数据类型 | 字段描述 | 备注 |
---|---|---|---|---|
1 | User_ID | String | 用户ID | |
1 | Product_ID | String | 商品ID | |
3 | Gender | String | 性别 | F:女,M:男 |
4 | Age | String | 年龄 | 7个年龄段 |
5 | Occupation | String | 职业 | 用0-20表示 |
6 | City_Category | String | 城市类别 | A,B,C |
7 | Stay_In_Current_City_Years | Integer | 居住城市年数 | 0,1, 2, 3, 4+ |
8 | Marital_Status | Integer | 婚姻状况 | 0:已婚,1:未婚 |
9 | Product_Category_1 | Integer | 产品类别1 |
2.3 数据探索
数据读取
df = pd.read_csv('BlackFriday.csv')
查看行数和列数
df.shape
输出:(537577, 12),537577行,12列
查看索引、数据类型和内存信息
df.info()
Product_Category_2和Product_Category_2是存在空值的。
查看简要的统计信息
df.describe()
查看10行数据
df.head(10)
3. 数据处理
列名重命名
为了方便看,可以先对列名进行重命名成中文。
df = df.rename(columns={'User_ID': '用户ID', 'Product_ID': '商品ID', 'Gender': '性别', 'Age': '年龄', 'Occupation': '行业', 'City_Category': '城市类别', 'Stay_In_Current_City_Years': '居住城市年数', 'Marital_Status': '婚姻状况', 'Product_Category_1': '产品类别1', 'Product_Category_2': '产品类别2', 'Product_Category_3': '产品类别3', 'Purchase': '采购额'})
缺失值处理
(df.shape[0]- df.dropna(how='any').shape[0])/df.shape[0]
产品类别2和产品类别3是有缺失数据的,缺失是比例占69%,数据量太大,不能删除,而且产品类别不好填充。但是因为在分析的过程中这两个字段不进行分析,所以这里不管缺失值。
df_dd = df.drop_duplicates(subset=['用户ID'])[['用户ID', '性别', '年龄', '职业', '城市类别', '居住城市年数', '婚姻状况']].sort_values(by='用户ID')
df_dd['采购额'] = df.groupby('用户ID')['采购额'].sum().sort_index().values
4. 数据分析
4.1 性别
explode = (0.1,0)
fig1, ax1 = plt.subplots(figsize=(10,7))
patches, texts, autotexts = ax1.pie(df_dd['性别'].value_counts(), explode=explode,labels=['男','女'], autopct='%1.1f%%',
shadow=True, startangle=90, colors=sns.color_palette("Blues_d", 2))
ax1.axis('equal')
plt.tight_layout()
plt.legend()
for t in texts:
t.set_size('xx-large')
for at in autotexts:
at.set_size('xx-large')
plt.legend(fontsize='16')
plt.show()
s_gender = df_dd.groupby('性别')['采购额'].sum().sort_values()
plt.figure(figsize=(12, 6))
plt.subplot(1, 1, 1)
sc = sns.color_palette("Blues_d", 2)
sns.barplot(s_gender.index, s_gender.values, palette=sc)
plt.xlabel('', fontsize=16)
plt.ylabel('', fontsize=16)
plt.xticks(np.arange(2), ('女', '男'))
plt.title('', fontsize=18)
plt.show()
从消费人数与消费金额两个维度来看,男性都远远超过女性,这个结论与国内男性、女性的消费存在很大的差异,有点出乎意料。
4.2 婚姻状况
explode = (0.1, 0)
fig1, ax1 = plt.subplots(figsize=(10,7))
patches, texts, autotexts = ax1.pie(df_dd['婚姻状况'].value_counts(), explode=explode, labels=['已婚','未婚'], autopct='%1.1f%%',
shadow=True, startangle=90, colors=sns.color_palette("Blues_d", 2))
ax1.axis('equal')
plt.tight_layout()
plt.legend(fontsize=18)
for t in texts:
t.set_size('xx-large')
for at in autotexts:
at.set_size('xx-large')
plt.legend(fontsize='16')
plt.show()
从图中看,购买人群中已婚的要多于未婚的,结婚的生活需要购买的需要多一点,可能家庭消费比较多。在进行营销的时候,要偏向于已婚人群。
fig1, ax1 = plt.subplots(figsize=(12,7))
sc = sns.color_palette("Blues", 2)
sns.countplot(df_dd['婚姻状况'],hue=df['性别'], palette=sc)
plt.xticks(np.arange(2), ('已婚', '未婚'))
plt.xlabel('', fontsize=16)
plt.ylabel('', fontsize=16)
plt.legend(fontsize=16)
plt.show()
可以再从性别的维度看,无论是已婚还是未婚,都是男性大于女性,不会受到婚姻状况的影响。因为不知道当地的情况,无法下定结论就是女性没有购买力。可以进一步调查,如果只是女性的市场没有打开,尝试提高女性购买的欲望,可能会有收获。
4.3 年龄
fig1, ax1 = plt.subplots(figsize=(12,7))
sc = sns.color_palette("Blues", 2)
sns.countplot(df_dd['年龄'],hue=df['性别'], order=['0-17', '18-25', '26-35', '36-45', '46-50', '51-55', '55+'], palette=sc)
plt.xlabel('', fontsize=16)
plt.ylabel('', fontsize=16)
plt.legend(fontsize=16)
plt.show()
从年龄看,无论是男性,还是女性,消费人数都是集中18-45岁。其中26-35这个年龄段最多,这个年龄段的人消费能力大。
s_gender = df_dd.groupby('年龄')['采购额'].sum()
plt.figure(figsize=(10, 6))
plt.subplot(1, 1, 1)
sc = sns.color_palette("Blues_r", 8)
sns.barplot(s_gender.index, s_gender.values, order=['0-17', '18-25', '26-35', '36-45', '46-50', '51-55', '55+'], palette=sc)
plt.xlabel('', fontsize=16)
plt.ylabel('', fontsize=16)
plt.grid(axis='x')
plt.title('', fontsize=18)
plt.grid(axis='x')
plt.show()
消费金额的分布是跟购买人数的分布式一致的,都是集中在18-45岁,这个年龄区间的人购买力比较大。
4.4 城市
explode = (0.1, 0, 0)
fig1, ax1 = plt.subplots(figsize=(10,7))
patches, texts, autotexts = ax1.pie(df_dd['城市类别'].value_counts(), explode=explode,labels=df['城市类别'].unique(), autopct='%1.1f%%',
shadow=True, startangle=90, colors=sns.color_palette("Blues_r", 3))
ax1.axis('equal')
plt.tight_layout()
for t in texts:
t.set_size('xx-large')
for at in autotexts:
at.set_size('xx-large')
plt.legend(fontsize='16')
plt.show()
从购买的人数看,C城市人最多,A城市人最少。
explode = (0.1, 0, 0)
fig1, ax1 = plt.subplots(figsize=(10,7))
patches, texts, autotexts = ax1.pie(df_dd.groupby('城市类别')['采购额'].sum(), explode=explode,labels=df['城市类别'].unique(), autopct='%1.1f%%',
shadow=True, startangle=90, colors=sns.color_palette("Blues_r", 3))
ax1.axis('equal')
plt.tight_layout()
plt.legend()
for t in texts:
t.set_size('xx-large')
for at in autotexts:
at.set_size('xx-large')
plt.legend(fontsize='16')
plt.show()
从消费总额看,A城市是最低的,C城市虽然购买人数超过一半,但是消费总额却三分之一都不到。
可以看出,B城市的人购买力是最大的,购买的人数虽少,但是每个人的购买金额要大于其他两个城市的人。其次是A城市,购买力最低的是C城市,虽然C城市购买的人数要多于其他两个城市,但是消费总额却低于其他两个城市,可以看出A城市的购买力比较低。
hue_order=['0-17', '18-25', '26-35', '36-45', '46-50', '51-55', '55+']
order=['A', 'B', 'C']
fig1, ax1 = plt.subplots(figsize=(12,7))
sc = sns.color_palette("Blues_d", 7)
sns.countplot(df_dd['城市类别'],hue=df['年龄'], order=order, hue_order=hue_order, palette=sc)
plt.xlabel('', fontsize=16)
plt.ylabel('', fontsize=16)
plt.legend(fontsize=16)
plt.show()
从3个城市的年龄段分布看,A城市在各个年龄段的人数都是最少的,C城市高龄人数比较多。
4.5 居住城市年数
labels=['1年','2年','3年','4年以上','游客']
explode = (0.1, 0.1,0,0,0)
fig1, ax1 = plt.subplots(figsize=(10,7))
patches, texts, autotexts = ax1.pie(df_dd['居住城市年数'].value_counts(),explode=explode, labels=labels, autopct='%1.1f%%',
shadow=True, startangle=90, colors=sns.color_palette("Blues_d"))
sc = sns.color_palette("hls", 5)
sns.set_palette(sc)
ax1.axis('equal')
plt.tight_layout()
plt.legend(fontsize=16)
for t in texts:
t.set_size('xx-large')
for at in autotexts:
at.set_size('xx-large')
plt.show()
labels=['1年','2年','3年','4年以上','游客']
explode = (0.1, 0.1,0,0,0)
fig1, ax1 = plt.subplots(figsize=(10,7))
patches, texts, autotexts = ax1.pie(df_dd.groupby('居住城市年数')['采购额'].sum(), explode=explode, labels=labels, autopct='%1.1f%%',
shadow=True, startangle=90, colors=sns.color_palette("Blues_d"))
sc = sns.color_palette("hls", 5)
sns.set_palette(sc)
ax1.axis('equal')
plt.tight_layout()
plt.legend(fontsize=16)
for t in texts:
t.set_size('xx-large')
for at in autotexts:
at.set_size('xx-large')
plt.show()
从购买人数看,居住在城市第一年的购买人数是最多的,从消费总额看,第二年的人购买消费总额是最高的,但是购买人数是比第一年的人少。随着居住年数的增加,购买的人数是递减的。
居住在城市第二年的人消费人数和消费金额都是最高的,其他都比较低,对于居住2年的可以进行适当营销,提高留存。
4.6 职业
fig1, ax1 = plt.subplots(figsize=(12,7))
x = df_dd['职业'].value_counts().sort_values().index
y = df_dd['职业'].value_counts().sort_values().values
sns.barplot(x, y, order=x, palette="Blues_d")
plt.xlabel('', fontsize=16)
plt.ylabel('', fontsize=16)
plt.show()
fig1, ax1 = plt.subplots(figsize=(12,7))
x = df_dd.groupby('职业')['采购额'].sum().sort_values().index
y = df_dd.groupby('职业')['采购额'].sum().sort_values().sort_values().values
sns.barplot(x, y, order=x, palette="Blues_d")
plt.xlabel('', fontsize=16)
plt.ylabel('', fontsize=16)
plt.show()
各职业的消费人数和消费总额排名大致一样,前三名都是4、0、7,购买人数多,消费总额高。根据购买人数的因素,应该把更多的商品针对购买职业人数多的职业。因为无法知道具体职业是什么,无从知道更多信息。
5. 结论
- 男性的消费人数和消费总额都远超女性,跟中国的男女购买情况有所差异。
- 已婚的购买人数比未婚的多。
- 都是集中在18-45岁,这个年龄区间的人购买力比较大
- B城市的购买力最大,购买人数最多的并不一定是购买力最大的。
- 购买人数随着居住城市年数的增加而减少,但是居住两年的人消费总额是最高的。
- 各职业的消费总额跟购买人数相关,职业人数差异还是比较大的。