【Python】Kaggle可视化:黑色星期五画像分析

公众号:尤而小屋
作者:Peter
编辑:Peter

本文还是kaggle上一份黑色星期五消费数据的分析,主要是针对用户和商品信息的画像分析。建模的方案参考文章:

kaggle实战:星期五黑了,随机森林输了!

本文重点是可视化,使用的图形:柱状图、饼图、散点图、小提琴图、桑基图、树状图、漏斗图、多子图等,全部是Plotly库绘制。

关键词:用户画像、可视化、plotly、Pandas

81c30e3a7ad7736db9240318cf99ebca.png

导入库

import pandas as pd
import numpy as np

import matplotlib.pyplot as plt
import seaborn as sns 
import matplotlib.patches as mpatches
import matplotlib
# 中文显示问题
plt.rcParams["font.sans-serif"]=["SimHei"] #设置字体
plt.rcParams["axes.unicode_minus"]=False #正常显示负号

import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
from plotly.offline import init_notebook_mode, iplot

# 忽略notebook中的警告
import warnings
warnings.filterwarnings("ignore")

数据基本信息

导入数据

探索数据的基本信息

In [2]:

df = pd.read_csv("train.csv")
df
f9ece435ad76574cfca4ff2986909019.png

基本信息

In [3]:

# 1、数据大小
df.shape

Out[3]:

(550068, 12)

In [4]:

# 2、字段类型
df.dtypes

Out[4]:

User_ID                         int64
Product_ID                     object
Gender                         object
Age                            object
Occupation                      int64
City_Category                  object
Stay_In_Current_City_Years     object
Marital_Status                  int64
Product_Category_1              int64
Product_Category_2            float64
Product_Category_3            float64
Purchase                        int64
dtype: object

下面是具体的字段含义为:

  • User_ID:用户编码

  • Product_ID:商品编码

  • Gender:性别(M为男性,F为女性)

  • Age:年龄(0-17,18-25,26-35,36-45,46-50,51-55,55+,7种)

  • Occupation:职业(用数字代表具体职业,一共20种职业)

  • City_Category:城市分类(分为三类城市:ABC)

  • Stay_in_Current_City_Years:在目前城市的居住的年数(0,1,2,3,4+,5种)

  • Marital_Status:婚姻状态(0为未婚,1为已婚)

  • Product_Category_1:产品分类为1(服饰,20种,用1-20表示)

  • Product_Category_2:产品分类为2(电子产品)

  • Product_Category_3:产品分类为3(家具用品)

  • Purchase:购买金额(单位为美元)

In [5]:

# 3、缺失值情况
df.isnull().sum()

Out[5]:

User_ID                            0
Product_ID                         0
Gender                             0
Age                                0
Occupation                         0
City_Category                      0
Stay_In_Current_City_Years         0
Marital_Status                     0
Product_Category_1                 0
Product_Category_2            173638   # 存在缺失值
Product_Category_3            383247
Purchase                           0
dtype: int64

In [6]:

# 4、数据信息
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 550068 entries, 0 to 550067
Data columns (total 12 columns):
 #   Column                      Non-Null Count   Dtype  
---  ------                      --------------   -----  
 0   User_ID                     550068 non-null  int64  
 1   Product_ID                  550068 non-null  object 
 2   Gender                      550068 non-null  object 
 3   Age                         550068 non-null  object 
 4   Occupation                  550068 non-null  int64  
 5   City_Category               550068 non-null  object 
 6   Stay_In_Current_City_Years  550068 non-null  object 
 7   Marital_Status              550068 non-null  int64  
 8   Product_Category_1          550068 non-null  int64  
 9   Product_Category_2          376430 non-null  float64
 10  Product_Category_3          166821 non-null  float64
 11  Purchase                    550068 non-null  int64  
dtypes: float64(2), int64(5), object(5)
memory usage: 50.4+ MB

缺失值可视化

In [7]:

import missingno
df.isna().sum() / df.shape[0]

Out[7]:

User_ID                       0.000000
Product_ID                    0.000000
Gender                        0.000000
Age                           0.000000
Occupation                    0.000000
City_Category                 0.000000
Stay_In_Current_City_Years    0.000000
Marital_Status                0.000000
Product_Category_1            0.000000
Product_Category_2            0.315666  # 缺失值字段
Product_Category_3            0.696727
Purchase                      0.000000
dtype: float64

In [8]:

可以看到有两个字段存在缺失值

# 矩阵图:查看缺失值的分布

missingno.matrix(df)
plt.show()
b35c835f9ad143354b0d1cfd5b9fb844.png
# 条形图
missingno.bar(df, color="blue")
plt.show()

从下面的图像中也能够观察到只有两个字段存在缺失值

bff441e36d1fb7427ad8ff26729436dc.png

小结1:在我们的数据中包含object、float64和int64共3种数据类型

其中Product_Category_2字段有约31%的缺失占比,Product_Category_3有69%的缺失值占比。

总信息

寻找3个总体的数据信息:

  • 总消费人数

  • 总消费商品种类

  • 总消费金额

In [10]:

# 总消费人数

df["User_ID"].nunique()

Out[10]:

5891

In [11]:

# 总消费商品种类

df["Product_ID"].nunique()

Out[11]:

3631

In [12]:

# 总消费金额
sum(df["Purchase"])

Out[12]:

5095812742

商品类别

In [13]:

# 总消费商品种类

df["Product_Category_1"].nunique()

Out[13]:

20

In [14]:

df["Product_Category_2"].nunique()

Out[14]:

17

画像1:消费金额Top10

In [15]:

不同用户的消费金额对比

df1 = df.groupby("User_ID")["Purchase"].sum().reset_index()

df2 = df1.sort_values("Purchase", ascending=False)
df2["User_ID"] = df2["User_ID"].apply(lambda x: "id_"+str(x))
7fa65f3b024c5da9b11c4a91fc9a4a57.png
fig = px.bar(df2[:10],   # 选择前10人
             x="User_ID",
             y="Purchase",
             text="Purchase")

fig.show()
f4954b5d17cc18975274834c7a3cfd78.png

可以看到最高的一位用户花费了1千多万!

画像2:高频消费前10

In [19]:

df3 = df.groupby("User_ID").size().reset_index()

# Number表示购买次数
df3.columns = ["User_ID", "Number"]  

# 降序排列
df4 = df3.sort_values("Number", ascending=False)
df4.head(10)
0000dfc270f55107b1e5b9b469556315.png
df4["User_ID"] = df4["User_ID"].apply(lambda x: "id_"+str(x))

fig = px.bar(df4[:10],   # 选择前10人
             x="User_ID",
             y="Number",
             text="Number",
             color="Number"
            )

fig.show()
be5cb31ea831987147c437b0462e4e78.png

画像3:人均消费金额Top10

In [23]:

df5 = pd.merge(df2, df4)
# 人均消费金额

df5["Average"] = df5["Purchase"] / df5["Number"]
df5["Average"] = df5["Average"].apply(lambda x: round(x,2))
df5.head()
ab6f41f1848087cab20f2b053ad493bc.png
fig = px.scatter(df5, 
                 x="User_ID", 
                 y="Average",
                 color="Average")

fig.show()
b34e88aaf6aa0e983339e9c09ce5cd5d.png
px.violin(df5["Average"])
8585701880b2af9d1fd98d708e434f78.png

从散点分布图和小提琴图中能够看到,大部分用户的平均消费金额在8k到10k之间

画像4:男女消费对比

In [28]:

df6 = df.groupby("Gender").agg({"User_ID":"nunique", "Purchase":"sum"}).reset_index()
df6

Out[28]:


GenderUser_IDPurchase
0F16661186232642
1M42253909580100
86a13a0c9dc2c06e84af02fcef2c925c.png 7ce354af78a23eae8fccb9ecd0a6fe9b.png

总结:男士才是消费主力军!

画像5:不同年龄的消费人数和金额

In [30]:

df7 = df.groupby("Age").agg({"User_ID":"nunique", "Purchase":"sum"}).reset_index()
df7

Out[30]:


AgeUser_IDPurchase
00-17218134913183
118-251069913848675
226-3520532031770578
336-4511671026569884
446-50531420843403
551-55481367099644
655+372200767375

In [31]:

41e3bd221de7034ee08b51617e8b779d.png 98f8942f2420f861b85bcbe127e74275.png

总结:26到35岁的人群,年轻人,大部分都是工作多年的用户,有家庭和经济基础,成为了消费主力军

画像6:不同性别+年龄的消费人数、金额

In [32]:

df8 = df.groupby(["Gender","Age"]).agg({"User_ID":"nunique", "Purchase":"sum"}).reset_index()
df8
990cb10e1ee1b7654622de1d66f6d8d5.png
fig = px.treemap(
    df8,  # 传入数据
    path=[px.Constant("all"),"Gender","Age"],  
    values="Purchase" # 消费金额
)

fig.update_traces(root_color="lightskyblue")

fig.update_layout(margin=dict(t=30,l=20,r=25,b=30))

fig.show()
2879d23731e0b0d3d785183d81775756.png

画像7:不同城市、年龄消费金额

In [34]:

df9 = df.groupby(["City_Category","Age"]).agg({"User_ID":"nunique", "Purchase":"sum"}).reset_index()
df9.head()
aa9f24c2ba3973d8e4827d6ae298e6bb.png
fig = px.bar(df9,
             x="City_Category",
             y="Purchase",
             color="Age",
             barmode="group",
             text="Purchase"
            )

fig.update_layout(title="不同城市不同年龄段的消费金额")

fig.show()
1f92f3a7c3e6de042ec4636487838c75.png

从3个城市来看,26-35一直都是消费主力

df1d3522423d8bdba0e4fefa02928cfc.png

从上面的柱状图来看,在不同的年龄段,一直保持A < B < C的现象。C城市果真是消费的主要城市

画像8:不同婚姻状态的消费次数和金额

In [37]:

df10 = df.groupby(["Marital_Status"]).agg({"User_ID":"nunique", "Purchase":"sum"}).reset_index()
df10

Out[37]:


Marital_StatusUser_IDPurchase
0034173008927447
1124742086885295

In [38]:

df10["Marital_Status"] = df10["Marital_Status"].map({0:"未婚",1:"已婚"})

In [39]:

fig = px.pie(names=df10["Marital_Status"],
             values=df10["Purchase"]
            )

fig.update_traces(
    textposition='inside',   # 文本显示位置:['inside', 'outside', 'auto', 'none']
    textinfo='percent+label'
)

fig.show()
955efc3e7b86ab8ca37676b7fd594466.png 9a9766513f39390c1b4c03bddb82008a.png

总结:单身自由,就是要买

画像9:城市停留时间

In [41]:

px.violin(df,
          y="Purchase",
          color="Stay_In_Current_City_Years")
6c7f6856dbefbcd1000ec766a20c9646.png
df11 = (df.groupby(["Stay_In_Current_City_Years"])
        .agg({"User_ID":"nunique", "Purchase":"sum"})
        .reset_index())
df12 = df11.sort_values("User_ID",ascending=False)
df12
54699ebece44334331308d6023354dd1.png
stages = df12["Stay_In_Current_City_Years"].tolist()

fig = px.funnel_area(values = df12["User_ID"].tolist(),
                     names = stages
                    )
fig.show()
b430a20a9538c081cb7806480a6e2dbb.png 95aa7a561772f1390f9eb6cac90fcc5f.png

在一个城市停留1-2年内的用户更容易成为消费主力

画像10:销售额Top20商品

In [46]:

df13 = df.groupby(["Product_ID"]).agg({"Purchase":"sum"}).reset_index()
# 改成以万为单位
df13["Purchase"] = df13["Purchase"].apply(lambda x: round(x / 10000,2))

# 销售额降序
df13.sort_values("Purchase", ascending=False, inplace=True)

df13
5e21b22fcc10d3722296260238c9d790.png
fig = px.bar(df13[:10],   # 选择前10人
             x="Product_ID",
             y="Purchase",
             color="Purchase",
             text="Purchase")

fig.update_layout(title="Top20商品销售额对比图(万)")

fig.show()
8cd7a5505fcb4955371d5c16581d9dc1.png

画像11:二八法则

In [49]:

# 销售额

top20 = int(df13["Product_ID"].nunique() * 0.2)
top20

Out[49]:

726

In [50]:

sum(df13[:top20]["Purchase"]) / sum(df13["Purchase"])

Out[50]:

0.7325143993257992

通过计算的结果发现:销售额排名前20的商品其总销售额占据整体的73%,基本上是符合我们听到的二八法则

画像11:商品种类

In [51]:

df14 = df.groupby(["Product_Category_1"]).agg({"Purchase":"sum"}).reset_index()

fig = px.pie(names=df14["Product_Category_1"],
             values=df14["Purchase"],
             hole=0.5
            )

fig.update_traces(
    textposition='inside',   
    textinfo='percent+label'
)

fig.show()
0e64b1a9faffe1cbcb9c5d8565d671c3.png
px.box(df,
       x="Product_Category_1",
       y="Purchase",
       color="Product_Category_1")
06724814dc46fb548e00df98c6e9e757.png

画像12:不同性别不同种类销售额

In [54]:

ff77c26986d0307696fea69dca1f2092.png 759c85e7fd02fd8b267ef95059c799d5.png

第一级

In [56]:

df16 = df15.groupby("Gender")["Purchase"].sum().reset_index()
df16

Out[56]:


GenderPurchase
0F416719106
1M1528099293

In [57]:

df16["Total"] = "总销售额"

In [58]:

df16 = df16[["Total","Gender","Purchase"]]

df16.columns = ["父类","子类","数据"]

df16

Out[58]:


父类子类数据
0总销售额F416719106
1总销售额M1528099293

第二级

In [59]:

df17 = df15.groupby(["Gender","Product_Category_1"])["Purchase"].sum().reset_index()
df17.head()
4274e9a50200845a1eebe8b7b94dd5b0.png

第三级

In [61]:

df18 = df15.groupby(["Product_Category_1","Product_Category_2"])["Purchase"].sum().reset_index()
df18.head()

Out[61]:

ad9b637d8f46872b133276cbb04c3432.png

In [62]:

df18.columns = ["父类","子类","数据"]

第四级

In [63]:

df19 = df15.groupby(["Product_Category_2","Product_Category_3"])["Purchase"].sum().reset_index()
df19.head()

Out[63]:

70766cd448db9cb495def45719033905.png

In [64]:

df19.columns = ["父类","子类","数据"]

数据合并

In [65]:

df20 = pd.concat([df16,df17,df18,df19],axis=0).reset_index(drop=True)
df20.head()

Out[65]:

de58a0b6e2820fb37f59323f4d5a2fc1.png

子类和父类元素个数

In [66]:

labels = list(set(df20["父类"].tolist() + df20["子类"].tolist()))
labels[:5]

Out[66]:

['c1_3', 'c3_14', 'c3_18', 'c2_4', 'c2_12']

元素字典设置

In [67]:

number = list(range(0, len(labels)))

index = dict(list(zip(labels, number)))

配对

In [68]:

df20["父类索引"] = df20["父类"].map(index)
df20["子类索引"] = df20["子类"].map(index)
df20

Out[68]:

be6fef2b45f7c6ffb546c34f7799d108.png

绘图

In [69]:

cc1b780ec528bb3b3a97d5d70195df0a.png c3de3ec20b57b22a9415f5aec036a65c.png

从性别、3个不同的商品类别来看:

  • 男性的消费能力远高于女性

  • 在商品1中,1号品类是一个高需求的物品;在商品2中,2号最高,8号其次

  • 在商品3中,头部需求的物品差距缩小,整体的需求更均衡

  • 从商品种类的关联性来看,c1_1、c2_2、c3_15是最强的

 
 
 
 
 
 
 
 
 
 
往期精彩回顾




适合初学者入门人工智能的路线及资料下载(图文+视频)机器学习入门系列下载中国大学慕课《机器学习》(黄海广主讲)机器学习及深度学习笔记等资料打印《统计学习方法》的代码复现专辑机器学习交流qq群955171419,加入微信群请扫码

203a323285054e79e069c90aa94d2219.png

  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值