本文来源
KathyZhu - 天猫双十一美妆销售数据分析 - kesci.com
点击以上链接,不用配置环境,直接在线运行
本文数据集链接:Tmall_makeup - 采集了2016年双十一化妆品的销量信息
import pandas as pd
import numpy as np
data = pd.read_csv('beautymakeup in T-mall.csv')
data.head()
data.shape
out[]:(27598, 7)
# 查看各字段信息
data.info()
data['店名'].value_counts()
# 对重复数据做删除处理
data = data.drop_duplicates(inplace=False)
data.shape
out:(27512, 7)
# 此处虽然删除了重复值,但索引未变,因此应用以下方法进行重置索引
data.reset_index(inplace=True,drop=True)
# 查看缺失值
data.isnull().any()
有两列数据存在缺失值:sale_count, comment_count
# 查看数据结构
data.describe()
# 查看sale_count列的众数
mode_01 = data.sale_count.mode()
mode_01
out:
0 0.0
dtype: float64
# 查看comment_count列的众数
mode_02 = data.comment_count.mode()
mode_02
out:
0 0.0
dtype: float64
此处两列的众数均为0,且由标签数据含义可知销售量和评论数有可能存在为0的情况,因此使用0来填充缺失值
data = data.fillna(0)
data.isnull().sum()
import jieba
# jieba.load_userdict('addwords.txt')
title_cut = []
for i in data.title:
j = jieba.lcut(i)
title_cut.append(j)
data['item_name_cut'] = title_cut
data[['title','item_name_cut']].head()
# 给商品添加分类
sub_type = [] #子类别
main_type = [] #主类别
basic_config_data = """护肤品 套装 套装
护肤品 乳液类 乳液 美白乳 润肤乳 凝乳 柔肤液' 亮肤乳 菁华乳 修护乳
护肤品 眼部护理 眼霜 眼部精华 眼膜
护肤品 面膜类 面膜
护肤品 清洁类 洗面 洁面 清洁 卸妆 洁颜 洗颜 去角质 磨砂
护肤品 化妆水 化妆水 爽肤水 柔肤水 补水露 凝露 柔肤液 精粹水 亮肤水 润肤水 保湿水 菁华水 保湿喷雾 舒缓喷雾
护肤品 面霜类 面霜 日霜 晚霜 柔肤霜 滋润霜 保湿霜 凝霜 日间霜 晚间霜 乳霜 修护霜 亮肤霜 底霜 菁华霜
护肤品 精华类 精华液 精华水 精华露 精华素
护肤品 防晒类 防晒霜 防晒喷雾
化妆品 口红类 唇釉 口红 唇彩
化妆品 底妆类 散粉 蜜粉 粉底液 定妆粉 气垫 粉饼 BB CC 遮瑕 粉霜 粉底膏 粉底霜
化妆品 眼部彩妆 眉粉 染眉膏 眼线 眼影 睫毛膏
化妆品 修容类 鼻影 修容粉 高光 腮红
其他 其他 其他"""
category_config_map = {}
for config_line in basic_config_data.split('\n'):
basic_cateogry_list = config_line.strip().strip('\n').strip('\t').split('\t')
main_category = basic_cateogry_list[0]
sub_category = basic_cateogry_list[1]
unit_category_list = basic_cateogry_list[2:-1]
for unit_category in unit_category_list:
if unit_category and unit_category.strip().strip('\t'):
category_config_map[unit_category] = (main_category,sub_category)
category_config_map
for i in range(len(data)):
exist = False
for temp in data.item_name_cut[i]:
if temp in category_config_map:
sub_type.append(category_config_map.get(temp)[1])
main_type.append(category_config_map.get(temp)[0])
exist = True
break
if not exist:
sub_type.append('其他')
main_type.append('其他')
print(len(sub_type),len(main_type),len(data))
out:
27512 27512 27512
data['sub_type'] = sub_type
data['main_type'] = main_type
data['sub_type'].value_counts()
data['main_type'].value_counts()
gender = []
for i in range(len(data)):
if '男' in data.item_name_cut[i]:
gender.append('是')
elif '男士' in data.item_name_cut[i]:
gender.append('是')
elif '男生' in data.item_name_cut[i]:
gender.append('是')
else:
gender.append('否')
# 将“是否男士专用”新增为一列
data['是否男士专用'] = gender
data['是否男士专用'].value_counts()
新增销售额为一列
# 销售额=销售量*价格
data['销售额'] = data.sale_count*data.price
新增购买日期为一列
# 转换时间格式
data['update_time'] = pd.to_datetime(data['update_time'])
data['update_time']
# 将时间设置为新的index
data = data.set_index('update_time')
# 新增时间“天”为一列
data['day'] = data.index.day
# 删除中文分词的一列
del data['item_name_cut']
data.head()
data.info()
# 保存清理好的数据为Excel格式
data.to_excel('clean_beautymakeup.xls',sheet_name='clean_data')
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
data.columns
plt.rcParams['font.sans-serif']=['SimHei'] #指定默认字体
plt.rcParams['axes.unicode_minus']=False #解决负号'-'显示为方块的问题
plt.figure(figsize=(8,6))
# 计算各店铺的商品数量
data['店名'].value_counts().sort_values(ascending=False).plot.bar(width=0.8,alpha=0.6,color='b')
plt.title('各品牌SKU数',fontsize=18)
plt.ylabel('商品数量',fontsize=14)
plt.show()
fig,axes = plt.subplots(1,2,figsize=(12,10))
ax1 = data.groupby('店名').sale_count.sum().sort_values(ascending=True).plot(kind='barh',ax=axes[0],width=0.6)
ax1.set_title('品牌总销售量',fontsize=12)
ax1.set_xlabel('总销售量')
ax2 = data.groupby('店名')['销售额'].sum().sort_values(ascending=True).plot(kind='barh',ax=axes[1],width=0.6)
ax2.set_title('品牌总销售额',fontsize=12)
ax2.set_xlabel('总销售额')
plt.subplots_adjust(wspace=0.4)
plt.show()
相宜本草的销售量和销售额都是最高的。销量第二至第五,分别为美宝莲、悦诗风吟、妮维雅、欧莱雅;销售额第二至第五,分别为欧莱雅、佰草集、美宝莲、悦诗风吟。 宝莲、悦诗风吟、欧莱雅都在销量、销售额前五中。
fig,axes = plt.subplots(1,2,figsize=(12,5))
data1 = data.groupby('main_type')['sale_count'].sum()
ax1 = data1.plot(kind='pie',ax=axes[0],autopct='%.1f%%', # 设置百分比的格式,这里保留一位小数
pctdistance=0.8, # 设置百分比标签与圆心的距离
labels= data1.index,
labeldistance = 1.05, # 设置标签与圆心的距离
startangle = 60, # 设置饼图的初始角度
radius = 1.1, # 设置饼图的半径
counterclock = False, # 是否逆时针,这里设置为顺时针方向
wedgeprops = {'linewidth': 1.2, 'edgecolor':'k'},# 设置饼图内外边界的属性值
textprops = {'fontsize':10, 'color':'k'}, # 设置文本标签的属性值
)
ax1.set_title('主类别销售量占比',fontsize=12)
data2 = data.groupby('sub_type')['sale_count'].sum()
ax2 = data2.plot(kind='pie',ax=axes[1],autopct='%.1f%%',
pctdistance=0.8,
labels= data2.index,
labeldistance = 1.05,
startangle = 230,
radius = 1.1,
counterclock = False,
wedgeprops = {'linewidth': 1.2, 'edgecolor':'k'},
textprops = {'fontsize':10, 'color':'k'},
)
ax2.set_title('子类别销售量占比',fontsize=12)
plt.subplots_adjust(wspace=0.4)
plt.show()
plt.figure(figsize=(14,6))
sns.barplot(x='店名',y='sale_count',hue='main_type',data=data,saturation=0.75,ci=0)
plt.title('各品牌各总类的总销量')
plt.ylabel('销量')
plt.text(0,78000,'注:此处也可使用堆叠图,对比效果更直观',
verticalalignment='top', horizontalalignment='left',color='gray', fontsize=10)
plt.show()
plt.figure(figsize = (14,6))
sns.barplot( x = '店名',
y = '销售额',hue = 'main_type',data =data,saturation = 0.75,ci=0,)
plt.title('各品牌各总类的总销售额')
plt.ylabel('销售额')
plt.show()
各品牌的化妆品、护肤品销量、销售情况均不一样,这与品牌的定位有关, 有的品牌主打化妆品,化妆品会表现好很多,如蜜丝佛陀等。主打护肤品的品牌,护肤品的销量销售额会表现好很多,如欧莱雅、佰草集等。 有的品牌如美宝莲、兰蔻、悦诗风吟,化妆品和护肤品的销售、销售额都还不错。
plt.figure(figsize = (16,6))
sns.barplot( x = '店名',
y = 'sale_count',hue = 'sub_type',data =data,saturation = 0.75,ci=0)
plt.title('各品牌各子类的总销量')
plt.ylabel('销量')
plt.show()
plt.figure(figsize = (14,6))
sns.barplot( x = '店名',
y = '销售额',hue = 'sub_type',data =data,saturation = 0.75,ci=0)
plt.title('各品牌各子类的总销售额')
plt.ylabel('销售额')
plt.show()
plt.figure(figsize = (12,6))
data.groupby('店名').comment_count.mean().sort_values(ascending=False).plot(kind='bar',width=0.8)
plt.title('各品牌商品的平均评论数')
plt.ylabel('评论数')
plt.show()
plt.figure(figsize=(12,10))
x = data.groupby('店名')['sale_count'].mean()
y = data.groupby('店名')['comment_count'].mean()
s = data.groupby('店名')['price'].mean()
txt = data.groupby('店名').id.count().index
sns.scatterplot(x,y,size=s,hue=s,sizes=(100,1500),data=data)
for i in range(len(txt)):
plt.annotate(txt[i],xy=(x[i],y[i]))
plt.ylabel('热度')
plt.xlabel('销量')
plt.legend(loc='upper left')
plt.show()
由上图所示:越靠上的品牌热度越高,越靠右的品牌销量越高,颜色越深圈越大价格越高
#查看价格的箱型图
plt.figure(figsize=(14,6))
sns.boxplot(x='店名',y='price',data=data)
plt.ylim(0,3000)#如果不限制,就不容易看清箱型,所以把Y轴刻度缩小为0-3000
plt.show()
data.groupby('店名').price.sum()
avg_price=data.groupby('店名').price.sum()/data.groupby('店名').price.count()
avg_price
fig = plt.figure(figsize=(12,6))
avg_price.sort_values(ascending=False).plot(kind='bar',width=0.8,alpha=0.6,color='b',label='各品牌平均价格')
y = data['price'].mean()
plt.axhline(y,0,5,color='r',label='全品牌平均价格')
plt.ylabel('各品牌平均价格')
plt.title('各品牌产品的平均价格',fontsize=24)
plt.legend(loc='best')
plt.show()
plt.figure(figsize=(12,10))
x = data.groupby('店名')['sale_count'].mean()
y = data.groupby('店名')['销售额'].mean()
s = avg_price
txt = data.groupby('店名').id.count().index
sns.scatterplot(x,y,size=s,sizes=(100,1500),marker='v',alpha=0.5,color='b',data=data)
for i in range(len(txt)):
plt.annotate(txt[i],xy=(x[i],y[i]),xytext = (x[i]+0.2, y[i]+0.2)) #在散点后面增加品牌信息的标签
plt.ylabel('销售额')
plt.xlabel('销量')
plt.legend(loc='upper left')
plt.show()
由上图所示,越靠上代表销售额越高,越靠左代表销量越高,图形越大代表平均价格越高
gender_data=data[data['是否男士专用']=='是']
gender_data_1=gender_data[(gender_data.main_type =='护肤品')| (gender_data.main_type=='化妆品')]
plt.figure(figsize = (12,6))
sns.barplot(x='店名',y='sale_count',hue='main_type',data =gender_data_1,saturation=0.75,ci=0,)
plt.show()
f,[ax1,ax2]=plt.subplots(1,2,figsize=(12,6))
gender_data.groupby('店名').sale_count.sum().sort_values(ascending=True).plot(kind='barh',width=0.8,ax=ax1)
ax1.set_title('男士护肤品销量排名')
gender_data.groupby('店名').销售额.sum().sort_values(ascending=True).plot(kind='barh',width=0.8,ax=ax2)
ax2.set_title('男士护肤品销售额排名')
plt.subplots_adjust(wspace=0.4)
plt.show()
from matplotlib.pyplot import MultipleLocator
plt.figure(figsize = (12,6))
day_sale=data.groupby('day')['sale_count'].sum()
day_sale.plot()
plt.grid(linestyle="-.",color="gray",axis="x",alpha=0.5)
x_major_locator=MultipleLocator(1) #把x轴的刻度间隔设置为1,并存在变量里
ax=plt.gca() #ax为两条坐标轴的实例
ax.xaxis.set_major_locator(x_major_locator)
#把x轴的主刻度设置为1的倍数
plt.xlabel('日期(11月)')
plt.ylabel('销量')
plt.show()