电商双 11 美妆数据分析学习报告
一、数据读取与初步探索代码
import numpy as np
import pandas as pd
df = pd.read_csv('双十一淘宝美妆数据.csv')
df.head() # 查看数据前五行
df.info() # 查看数据特征信息
df.shape # 查看数据量
df.describe() # 查看各数字类型特征的统计量
功能解析:这部分代码主要用于数据的读取和初步了解。通过pd.read_csv
读取 CSV 格式的数据文件;df.head()
展示数据的前 5 行,帮助快速了解数据结构;df.info()
获取数据的基本信息,包括列名、数据类型、非空值数量等;df.shape
返回数据的行数和列数;df.describe()
则对数值型特征进行统计描述,包括计数、均值、标准差、最值及四分位数等,为后续分析提供基础统计参考。
二、数据清洗代码
- 重复值处理
data = df.drop_duplicates(inplace=False) # 去重 data.reset_index(inplace=True, drop=True) # 重置行索引 data.shape
- 功能解析:
drop_duplicates
方法用于删除数据中的重复行,inplace=False
表示不修改原数据,而是返回一个新的去重后的数据框;reset_index
用于重置行索引,避免去重后索引混乱。通过data.shape
可以查看去重后的数据量,对比去重前的数据量可知删除了 86 条重复数据。data.loc[data['sale_count'].isnull()].head() # 查看sale_count缺失值的前几行 data.loc[data['comment_count'].isnull()].tail() # 查看comment_count缺失值的后几行 data = data.fillna(0) # 用0填补缺失值 data.isnull().any() # 查看是否还有空值
- 功能解析:首先通过
loc
和isnull()
查看sale_count
和comment_count
缺失值的情况,发现缺失值可能意味着销量或评论数为 0,因此使用fillna(0)
用 0 填补缺失值;最后用isnull().any()
检查是否还有空值,确保数据清洗彻底。 三、新特征挖掘代码
import jieba
subtitle = []
for each in data['title']:k = jieba.lcut_for_search(each) # 搜索引擎模式分词subtitle.append(k)
data['subtitle'] = subtitle
data[['title', 'subtitle']].head()
功能解析:利用jieba
库的lcut_for_search
方法对商品标题进行分词,采用搜索引擎模式能更精准地拆分出关键词,将分词结果存储在subtitle
列表中,并新增为数据框的subtitle
列,便于后续对商品特征进行深入分析。
- 商品分类
# 定义分类数据 basic_data = """护肤品\t乳液类\t乳液\t美白乳\t润肤乳\t凝乳\t柔肤液\t亮肤乳\t菁华乳\t修护乳 护肤品\t眼部护理类\t眼霜\t眼部\t眼膜 护肤品\t面膜类\t面膜 护肤品\t清洁类\t洗面\t洁面\t清洁\t卸妆\t洁颜\t洗颜\t去角质\t磨砂 护肤品\t化妆水\t化妆水\t爽肤水\t柔肤水\t补水露\t凝露\t柔肤液\t精粹水\t亮肤水\t润肤水\t保湿水\t菁华水\t保湿喷雾\t舒缓喷雾 护肤品\t面霜类\t面霜\t日霜\t晚霜\t柔肤霜\t滋润霜\t保湿霜\t凝霜\t日间霜\t晚间霜\t乳霜\t修护霜\t亮肤霜\t底霜\t菁华霜 护肤品\t精华类\t精华液\t精华水\t精华露\t精华素\t精华 护肤品\t防晒类\t防晒 护肤品\t补水类\t补水 化妆品\t口红类\t唇釉\t口红\t唇彩\t唇膏 化妆品\t底妆类\t散粉\t蜜粉\t粉底液\t定妆粉 气垫\t粉饼\tBB\tCC\t遮瑕\t粉霜\t粉底膏\t粉底霜 化妆品\t眼部彩妆\t眉粉\t染眉膏\t眼线\t眼影\t睫毛膏\t眉笔 化妆品\t修容类\t鼻影\t修容粉\t高光\t腮红""" # 构建分类字典 dcatg = {} catg = basic_data.split('\n') for i in catg:main_cat = i.strip().split('\t')[0]sub_cat = i.strip().split('\t')[1]o_cat = i.strip().split('\t')[2:len(catg)]for j in o_cat:dcatg[j] = (main_cat, sub_cat) # 给商品添加分类 sub_type = [] # 子类别 main_type = [] # 主类别 for i in range(len(data)):exist = Falsefor j in data['subtitle'][i]:if j in dcatg:sub_type.append(dcatg[j][1])main_type.append(dcatg[j][0])exist = Truebreakif not exist:sub_type.append('其他')main_type.append('其他') data['sub_type'] = sub_type data['main_type'] = main_type data.loc[data['sub_type'] == '其他'].count() # 查看分类为其他的商品数量
功能解析:首先定义了商品分类的基础数据,包括大类、小类及对应的关键词;然后通过构建分类字典
dcatg
,将关键词与对应的大类和小类关联起来;接着遍历每条数据的分词结果,根据分类字典为商品分配主类别和子类别,对于不在分类字典中的商品则归为 “其他” 类;最后统计分类为 “其他” 的商品数量,了解分类覆盖情况。 - 判断是否为男士专用
sex = [] for i in range(len(data)):if '男士' in data['subtitle'][i]:sex.append('是')elif '男生' in data['subtitle'][i]:sex.append('是')elif '男' in data['subtitle'][i] and '女' not in data['subtitle'][i] and '斩男' not in data['subtitle'][i]:sex.append('是')else:sex.append('否') data['是否男士专用'] = sex data.loc[data['是否男士专用'] == '是'].head() data['是否男士专用'].value_counts()
功能解析:通过遍历商品标题的分词结果,判断商品是否为男士专用。若分词中包含 “男士”“男生”,或包含 “男” 且不包含 “女” 和 “斩男”,则标记为 “是”,否则为 “否”;新增 “是否男士专用” 列存储判断结果,并通过
head()
和value_counts()
查看结果情况。 - 计算销售额
data['销售额'] = data.price * data.sale_count data.head()
四、数据分析及可视化代码
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif'] = [u'SimHei'] # 显示中文,设置字体
plt.rcParams['axes.unicode_minus'] = False # 显示符号
plt.figure(figsize=(12, 10))
# 各店铺的商品数量
plt.subplot(2, 2, 1)
plt.tick_params(labelsize=15)
data['店名'].value_counts().sort_values().plot.bar()
plt.title('各品牌商品数', fontsize=20)
plt.ylabel('商品数量', fontsize=15)
plt.xlabel('店名')
# 各店铺的销量
plt.subplot(2, 2, 2)
plt.tick_params(labelsize=15)
data.groupby('店名').sale_count.sum().sort_values().plot.bar()
plt.title('各品牌所有商品的销量', fontsize=20)
plt.ylabel('商品总销量', fontsize=15)
# 各店铺总销售额
plt.subplot(2, 2, 3)
plt.tick_params(labelsize=15)
data.groupby('店名')['销售额'].sum().sort_values().plot.bar()
plt.title('各品牌总销售额', fontsize=20)
plt.ylabel('商品总销售额', fontsize=15)
# 旋转显示
plt.xticks(rotation=45)
# 各品牌的平均每单单价
plt.subplot(2, 2, 4)
plt.tick_params(labelsize=15)
avg_price = data.groupby('店名')['销售额'].sum() / data.groupby('店名').sale_count.sum() # 每个品牌售出的商品的平均单价
avg_price.sort_values().plot.bar()
plt.title('各品牌平均每单单价', fontsize=20)
plt.ylabel('售出商品的平均单价', fontsize=15)
# 自适应调整子图间距
plt.tight_layout()
功能解析:使用matplotlib
库绘制子图,分别展示各店铺的商品数量、总销量、总销售额和平均每单单价。通过groupby
和sum
等方法对数据进行分组聚合计算,再用plot.bar()
绘制条形图,直观呈现各店铺在不同指标上的表现。设置中文字体显示,调整图表尺寸、标题、坐标轴标签等,使图表更易读。
A = avg_price[(avg_price <= 100) & (avg_price > 0)].index
B = avg_price[(avg_price <= 200) & (avg_price > 100)].index
C = avg_price[(avg_price <= 300) & (avg_price > 200)].index
D = avg_price[avg_price > 300].index
# 四类ABCD分别代表0-100,100-200,200-300,300以上平均单价区间的各品牌
sum_sale = data.groupby('店名')['销售额'].sum()
plt.figure(figsize=(16, 8))
plt.tick_params(labelsize=10)
# 各类、各品牌的销售额占比
plt.subplot(1, 2, 1)
sum_sale_byprice = sum_sale[A].sort_values().append(sum_sale[B].sort_values()).append(sum_sale[C].sort_values()).append(sum_sale[D].sort_values())
plt.pie(x=sum_sale_byprice, labels=sum_sale_byprice.index, colors=['grey']*len(A)+['g']*len(B)+['y']*len(C)+['m']*len(D), autopct='%0f%%', pctdistance=0.9)
# 各类的平均每个店销售额
plt.subplot(1, 2, 2)
plt.tick_params(labelsize=15)
plt.bar('均价0-100元', np.mean(sum_sale[A]), color='grey')
plt.bar('均价100-200元', np.mean(sum_sale[B]), color='g')
plt.bar('均价200-300元', np.mean(sum_sale[C]), color='y')
plt.bar('均价300元以上', np.mean(sum_sale[D]), color='m')
plt.title('不同类别的平均每个店销售额', fontsize=20)
plt.ylabel('平均销售额', fontsize=20)
plt.tight_layout()
功能解析:首先将品牌按平均单价划分为 A、B、C、D 四个区间;然后计算各区间品牌的总销售额,用饼图展示各类别品牌的销售额占比,用条形图展示不同价格区间品牌的平均每个店销售额,从而分析价格与销售额的关系。
import seaborn as sns
# 去掉总销量为0的店铺
data1 = data.drop(index=data[data['店名'].isin(data.groupby('店名').sale_count.sum()[data.groupby('店名').sale_count.sum() == 0].index)].index)
# 各店铺中各大类的销售量和销售额
plt.figure(figsize=(16, 12))
plt.subplot(2, 1, 1)
plt.tick_params(labelsize=10)
sns.barplot(x='店名', y='sale_count', hue='main_type', estimator=np.sum, data=data1, ci=0)
plt.title('各店铺中各大类的销售量', fontsize=20)
plt.ylabel('销量', fontsize=15)
plt.subplot(2, 1, 2)
plt.tick_params(labelsize=10)
sns.barplot(x='店名', y='销售额', hue='main_type', estimator=np.sum, data=data1, ci=0)
plt.title('各店铺中各大类的销售额', fontsize=20)
plt.ylabel('销售额', fontsize=15)
plt.tight_layout()# 各店铺中各小类的销售量和销售额
plt.figure(figsize=(16, 12))
plt.subplot(2, 1, 1)
plt.tick_params(labelsize=10)
sns.barplot(x='店名', y='sale_count', hue='sub_type', estimator=np.sum, data=data1, ci=0)
plt.title('各店铺中各小类的销售量', fontsize=20)
plt.ylabel('销量', fontsize=15)
plt.subplot(2, 1, 2)
plt.tick_params(labelsize=10)
sns.barplot(x='店名', y='销售额', hue='sub_type', estimator=np.sum, data=data1, ci=0)
plt.title('各店铺中各小类的销售额', fontsize=20)
plt.ylabel('销售额', fontsize=15)
plt.tight_layout()# 各小类中各店铺的销售量和销售额
plt.figure(figsize=(16, 12))
plt.subplot(2, 1, 1)
plt.tick_params(labelsize=10)
sns.barplot(x='sub_type', y='sale_count', hue='店名', estimator=np.sum, data=data1, ci=0)
plt.title('各小类中各店铺的销售量', fontsize=20)
plt.ylabel('销量', fontsize=15)
plt.subplot(2, 1, 2)
plt.tick_params(labelsize=10)
sns.barplot(x='sub_type', y='销售额', hue='店名', estimator=np.sum, data=data1, ci=0)
plt.title('各小类中各店铺的销售额', fontsize=20)
plt.ylabel('销售额', fontsize=15)
plt.tight_layout()
功能解析:首先去掉总销量为 0 的店铺,简化分析;然后使用seaborn
库的barplot
函数,分别从各店铺中各大类、各店铺中各小类、各小类中各店铺三个角度,绘制销售量和销售额的条形图,通过分组展示,深入分析不同店铺在不同类别商品上的销售表现。