【Python】Kaggle可視化:黑色星期五畫像分析
公眾號:尤而小屋
作者:Peter
編輯:Peter
本文還是kaggle上一份黑色星期五消費(fèi)數(shù)據(jù)的分析,主要是針對用戶和商品信息的畫像分析。建模的方案參考文章:
kaggle實(shí)戰(zhàn):星期五黑了,隨機(jī)森林輸了!
本文重點(diǎn)是可視化,使用的圖形:柱狀圖、餅圖、散點(diǎn)圖、小提琴圖、?;鶊D、樹狀圖、漏斗圖、多子圖等,全部是Plotly庫繪制。
關(guān)鍵詞:用戶畫像、可視化、plotly、Pandas

導(dǎo)入庫
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"]?#設(shè)置字體
plt.rcParams["axes.unicode_minus"]=False?#正常顯示負(fù)號
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")
數(shù)據(jù)基本信息
導(dǎo)入數(shù)據(jù)
探索數(shù)據(jù)的基本信息
In [2]:
df?=?pd.read_csv("train.csv")
df

基本信息
In [3]:
#?1、數(shù)據(jù)大小
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(xiàn)為女性) Age:年齡(0-17,18-25,26-35,36-45,46-50,51-55,55+,7種) Occupation:職業(yè)(用數(shù)字代表具體職業(yè),一共20種職業(yè)) City_Category:城市分類(分為三類城市:ABC) Stay_in_Current_City_Years:在目前城市的居住的年數(shù)(0,1,2,3,4+,5種) Marital_Status:婚姻狀態(tài)(0為未婚,1為已婚) Product_Category_1:產(chǎn)品分類為1(服飾,20種,用1-20表示) Product_Category_2:產(chǎn)品分類為2(電子產(chǎn)品) Product_Category_3:產(chǎn)品分類為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、數(shù)據(jù)信息
df.info()
'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()

#?條形圖
missingno.bar(df,?color="blue")
plt.show()
從下面的圖像中也能夠觀察到只有兩個字段存在缺失值

小結(jié)1:在我們的數(shù)據(jù)中包含object、float64和int64共3種數(shù)據(jù)類型
其中Product_Category_2字段有約31%的缺失占比,Product_Category_3有69%的缺失值占比。
總信息
尋找3個總體的數(shù)據(jù)信息:
總消費(fèi)人數(shù) 總消費(fèi)商品種類 總消費(fèi)金額
In [10]:
#?總消費(fèi)人數(shù)
df["User_ID"].nunique()
Out[10]:
5891
In [11]:
#?總消費(fèi)商品種類
df["Product_ID"].nunique()
Out[11]:
3631
In [12]:
#?總消費(fèi)金額
sum(df["Purchase"])
Out[12]:
5095812742
商品類別
In [13]:
#?總消費(fèi)商品種類
df["Product_Category_1"].nunique()
Out[13]:
20
In [14]:
df["Product_Category_2"].nunique()
Out[14]:
17
畫像1:消費(fèi)金額Top10
In [15]:
不同用戶的消費(fèi)金額對比
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))

fig?=?px.bar(df2[:10],???#?選擇前10人
?????????????x="User_ID",
?????????????y="Purchase",
?????????????text="Purchase")
fig.show()

可以看到最高的一位用戶花費(fèi)了1千多萬!
畫像2:高頻消費(fèi)前10
In [19]:
df3?=?df.groupby("User_ID").size().reset_index()
#?Number表示購買次數(shù)
df3.columns?=?["User_ID",?"Number"]??
#?降序排列
df4?=?df3.sort_values("Number",?ascending=False)
df4.head(10)

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()

畫像3:人均消費(fèi)金額Top10
In [23]:
df5?=?pd.merge(df2,?df4)
#?人均消費(fèi)金額
df5["Average"]?=?df5["Purchase"]?/?df5["Number"]
df5["Average"]?=?df5["Average"].apply(lambda?x:?round(x,2))
df5.head()

fig?=?px.scatter(df5,?
?????????????????x="User_ID",?
?????????????????y="Average",
?????????????????color="Average")
fig.show()

px.violin(df5["Average"])

從散點(diǎn)分布圖和小提琴圖中能夠看到,大部分用戶的平均消費(fèi)金額在8k到10k之間
畫像4:男女消費(fèi)對比
In [28]:
df6?=?df.groupby("Gender").agg({"User_ID":"nunique",?"Purchase":"sum"}).reset_index()
df6
Out[28]:
| Gender | User_ID | Purchase | |
|---|---|---|---|
| 0 | F | 1666 | 1186232642 |
| 1 | M | 4225 | 3909580100 |


總結(jié):男士才是消費(fèi)主力軍!
畫像5:不同年齡的消費(fèi)人數(shù)和金額
In [30]:
df7?=?df.groupby("Age").agg({"User_ID":"nunique",?"Purchase":"sum"}).reset_index()
df7
Out[30]:
| Age | User_ID | Purchase | |
|---|---|---|---|
| 0 | 0-17 | 218 | 134913183 |
| 1 | 18-25 | 1069 | 913848675 |
| 2 | 26-35 | 2053 | 2031770578 |
| 3 | 36-45 | 1167 | 1026569884 |
| 4 | 46-50 | 531 | 420843403 |
| 5 | 51-55 | 481 | 367099644 |
| 6 | 55+ | 372 | 200767375 |
In [31]:


總結(jié):26到35歲的人群,年輕人,大部分都是工作多年的用戶,有家庭和經(jīng)濟(jì)基礎(chǔ),成為了消費(fèi)主力軍
畫像6:不同性別+年齡的消費(fèi)人數(shù)、金額
In [32]:
df8?=?df.groupby(["Gender","Age"]).agg({"User_ID":"nunique",?"Purchase":"sum"}).reset_index()
df8

fig?=?px.treemap(
????df8,??#?傳入數(shù)據(jù)
????path=[px.Constant("all"),"Gender","Age"],??
????values="Purchase"?#?消費(fèi)金額
)
fig.update_traces(root_color="lightskyblue")
fig.update_layout(margin=dict(t=30,l=20,r=25,b=30))
fig.show()

畫像7:不同城市、年齡消費(fèi)金額
In [34]:
df9?=?df.groupby(["City_Category","Age"]).agg({"User_ID":"nunique",?"Purchase":"sum"}).reset_index()
df9.head()

fig?=?px.bar(df9,
?????????????x="City_Category",
?????????????y="Purchase",
?????????????color="Age",
?????????????barmode="group",
?????????????text="Purchase"
????????????)
fig.update_layout(title="不同城市不同年齡段的消費(fèi)金額")
fig.show()

從3個城市來看,26-35一直都是消費(fèi)主力

從上面的柱狀圖來看,在不同的年齡段,一直保持A < B < C的現(xiàn)象。C城市果真是消費(fèi)的主要城市
畫像8:不同婚姻狀態(tài)的消費(fèi)次數(shù)和金額
In [37]:
df10?=?df.groupby(["Marital_Status"]).agg({"User_ID":"nunique",?"Purchase":"sum"}).reset_index()
df10
Out[37]:
| Marital_Status | User_ID | Purchase | |
|---|---|---|---|
| 0 | 0 | 3417 | 3008927447 |
| 1 | 1 | 2474 | 2086885295 |
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()


總結(jié):單身自由,就是要買
畫像9:城市停留時間
In [41]:
px.violin(df,
??????????y="Purchase",
??????????color="Stay_In_Current_City_Years")

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

stages?=?df12["Stay_In_Current_City_Years"].tolist()
fig?=?px.funnel_area(values?=?df12["User_ID"].tolist(),
?????????????????????names?=?stages
????????????????????)
fig.show()


在一個城市停留1-2年內(nèi)的用戶更容易成為消費(fèi)主力
畫像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

fig?=?px.bar(df13[:10],???#?選擇前10人
?????????????x="Product_ID",
?????????????y="Purchase",
?????????????color="Purchase",
?????????????text="Purchase")
fig.update_layout(title="Top20商品銷售額對比圖(萬)")
fig.show()

畫像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
通過計(jì)算的結(jié)果發(fā)現(xiàn):銷售額排名前20的商品其總銷售額占據(jù)整體的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()

px.box(df,
???????x="Product_Category_1",
???????y="Purchase",
???????color="Product_Category_1")

畫像12:不同性別不同種類銷售額
In [54]:


第一級
In [56]:
df16?=?df15.groupby("Gender")["Purchase"].sum().reset_index()
df16
Out[56]:
| Gender | Purchase | |
|---|---|---|
| 0 | F | 416719106 |
| 1 | M | 1528099293 |
In [57]:
df16["Total"]?=?"總銷售額"
In [58]:
df16?=?df16[["Total","Gender","Purchase"]]
df16.columns?=?["父類","子類","數(shù)據(jù)"]
df16
Out[58]:
| 父類 | 子類 | 數(shù)據(jù) | |
|---|---|---|---|
| 0 | 總銷售額 | F | 416719106 |
| 1 | 總銷售額 | M | 1528099293 |
第二級
In [59]:
df17?=?df15.groupby(["Gender","Product_Category_1"])["Purchase"].sum().reset_index()
df17.head()

第三級
In [61]:
df18?=?df15.groupby(["Product_Category_1","Product_Category_2"])["Purchase"].sum().reset_index()
df18.head()
Out[61]:

In [62]:
df18.columns?=?["父類","子類","數(shù)據(jù)"]
第四級
In [63]:
df19?=?df15.groupby(["Product_Category_2","Product_Category_3"])["Purchase"].sum().reset_index()
df19.head()
Out[63]:

In [64]:
df19.columns?=?["父類","子類","數(shù)據(jù)"]
數(shù)據(jù)合并
In [65]:
df20?=?pd.concat([df16,df17,df18,df19],axis=0).reset_index(drop=True)
df20.head()
Out[65]:

子類和父類元素個數(shù)
In [66]:
labels?=?list(set(df20["父類"].tolist()?+?df20["子類"].tolist()))
labels[:5]
Out[66]:
['c1_3',?'c3_14',?'c3_18',?'c2_4',?'c2_12']
元素字典設(shè)置
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]:

繪圖
In [69]:


從性別、3個不同的商品類別來看:
男性的消費(fèi)能力遠(yuǎn)高于女性 在商品1中,1號品類是一個高需求的物品;在商品2中,2號最高,8號其次 在商品3中,頭部需求的物品差距縮小,整體的需求更均衡 從商品種類的關(guān)聯(lián)性來看,c1_1、c2_2、c3_15是最強(qiáng)的
往期精彩回顧
