首先 每個人都會有一段特別懷念而又難忘的時光吧,我到現在依然記得大學時光的美好。讓我們一起來懷念一下時光吧。今天這個故事從一張校園卡開始,相信很多小伙伴們都用過校園卡,它是一種其個人身份認證、校園消費、數據共用等多功能於一體的校園信息集成與管理系統。在它裡面存儲著大量的數據,包含:學生消費、宿舍門禁 ...
首先
每個人都會有一段特別懷念而又難忘的時光吧,我到現在依然記得大學時光的美好。讓我們一起來懷念一下時光吧。
今天這個故事從一張校園卡開始,相信很多小伙伴們都用過校園卡,它是一種其個人身份認證、校園消費、數據共用等多功能於一體的校園信息集成與管理系統。在它裡面存儲著大量的數據,包含:學生消費、宿舍門禁、圖書館進出等。
這篇文章使用的是南京某高校學生一卡通在2019年4月1-20號的消費明細數據,從統計可視化分析、關聯規則分析,發現學生一卡通的使用情況和學生當中的情侶、基友、閨蜜、渣男和單身狗等有趣信息。
使用的數據集地址如下:https://github.com/Nicole456/Analysis-of-students-consumption-behavior-on-campus
導入數據
#####Python學習交流群:906715085### import pandas as pd import numpy as np import datetime import plotly_express as px import plotly.graph_objects as go
1、數據1:每個學生的校園卡基本信息
2、數據2:校園卡每次消費和充值的明細數據
3、數據3:門禁明細數據
數據大小
In [8]: print("df1: ", df1.shape) print("df2: ", df2.shape) print("df3: ", df3.shape) df1: (4341, 5) df2: (519367, 14) df3: (43156, 6)
缺失值
# 每列缺失值 df1.isnull().sum() #每列的缺失值占比 df2.apply(lambda x : sum(x.isnull())/len(x), axis=0)
人數對比
不同性別人數
不同專業人數
In [16]: df5 = df1["Major"].value_counts().reset_index() df5.columns = ["Major","Number"] df5.head()
不同專業不同性別人數
In [18]: df6 = df1.groupby(["Major","Sex"])["CardNo"].count().reset_index() df6.head()
fig = px.treemap( df6, path=[px.Constant("all"),"Major","Sex"], # 重點:傳遞數據路徑 values="CardNo", color="Major" # 指定顏色變化的參數 ) fig.update_traces(root_color="maroon") # fig.update_traces(textposition="top right") fig.update_layout(margin=dict(t=30,l=20,r=25,b=30)) fig.show()
進出門禁信息
地址信息
In [21]:
#1、處理address address = df3["Address"].str.extract(r"(?P<Address_New>[\w]+)\[(?P<Out_In>[\w]+)\]") address
進出門禁時間
In [25]: df8 = pd.merge(df3,df1,on="AccessCardNo") df8.loc[:,'Date'] = pd.to_datetime(df8.loc[:,'Date'],format='%Y/%m/%d %H:%M',errors='coerce') df8["Hour"] = df8["Date"].dt.hour #df8["Minute"] = df8["Date"].dt.minute #進出門禁人數統計/小時 df9 = df8.groupby(["Hour","Out_In"]).agg({"AccessCardNo":"count"}).reset_index() df9.head()
#準備畫布
fig = go.Figure() #添加不同的數據 fig.add_trace(go.Scatter( x=df9.query("Out_In == '出門'")["Hour"].tolist(), y=df9.query("Out_In == '出門'")["AccessCardNo"].tolist(), mode='lines + markers', # mode模式選擇 name='出門')) # 名字 fig.add_trace(go.Scatter( x=df9.query("Out_In == '進門'")["Hour"].tolist(), y=df9.query("Out_In == '進門'")["AccessCardNo"].tolist(), mode='lines + markers', name='進門')) fig.show()
消費信息
In [30]: #數據合併 只取出兩個欄位:卡號和性別 df10 = pd.merge(df2,df1[["CardNo","Sex"]],on="CardNo")
合併信息
In [32]: df10["Card_Sex"] = df10["CardNo"].apply(lambda x: str(x)) + "_" + df10["Sex"]
主要地點
In [33]: #Card_Sex:統計消費人次 #Money:統計消費金額 df11 = (df10.groupby("Dept").agg({"Card_Sex":"count","Money":sum}) .reset_index().sort_values("Money",ascending=False)) df11.head(10)
fig = px.bar(df11,x="Dept",y="Card_Sex") fig.update_layout(title_text='不同地方的消費人數',xaxis_tickangle=45) fig.show()
fig = px.bar(df11,x="Dept",y="Money") fig.update_layout(title_text='不同地方的消費金額',xaxis_tickangle=45) fig.show()
關聯規則挖掘
時間處理
時間處理主要是兩個點:
•時間格式的轉換
•時間離散化:每5分鐘一個類型
在這裡我們預設:如果兩個時間在同一個類型中,認為兩人在一起消費
import datetime def change_time(x): # 轉成標準時間格式 result = str(datetime.datetime.strptime(x, "%Y/%m/%d %H:%M")) return result def time_five(x): # ‘2022-02-24 15:46:09’ ---> '2022-02-24 15_9' res1 = x.split(":")[0] res2 = str(round(int(x.split(":")[1]) / 5)) return res1 + "_" + res2 df10["New_Date"] = df10["Date"].apply(change_time) df10["New_Date"] = df10["New_Date"].apply(time_five) df10.head(3)
提起每個時間類型的人員信息:
#方式1 df11 = df10.groupby(["New_Date"])["Card_Sex"].apply(list).reset_index() #每個列表中的元素去重 df11["Card_Sex"] = df11["Card_Sex"].apply(lambda x: list(set(x))) all_list = df11["Card_Sex"].tolist() #方式2 #all_list = [] #for i in df10["New_Date"].unique().tolist(): #lst = df10[df10["New_Date"] == i]["Card_Sex"].unique().tolist() #all_list.append(lst)
頻繁項集尋找
In [44]: import efficient_apriori as ea #itemsets:頻繁項 rules:關聯規則 itemsets, rules = ea.apriori(all_list, min_support=0.005, min_confidence=1 )
一個人
一個人消費的數據最多:2565條數據,單身畢竟多!
len(itemsets[1]) # 2565條 #部分數據 {('181539_男',): 52, ('180308_女',): 47, ('183262_女',): 100, ('182958_男',): 88, ('180061_女',): 83, ('182936_男',): 80, ('182931_男',): 87, ('182335_女',): 60, ('182493_女',): 75, ('181944_女',): 67, ('181058_男',): 93, ('183391_女',): 63, ('180313_女',): 82, ('184275_男',): 69, ('181322_女',): 104, ('182391_女',): 57, ('184153_女',): 31, ('182711_女',): 40, ('181594_女',): 36, ('180193_女',): 84, ('184263_男',): 61,
兩個人
len(itemsets[2]) # 378條
查看了全部的數據,統計了下麵的結果:
('180433_男', '180499_女'): 34 #可疑渣男1 ('180624_男', '181013_女'): 36, ('180624_男', '181042_女'): 37, #可疑渣男2 ('181461_男', '180780_女'): 38, ('181461_男', '180856_女'): 34, ('181597_男', '183847_女'): 44, ('181699_男', '181712_女'): 31, ('181889_男', '180142_女'): 33, #可疑渣男3:NB ('182239_男', '182304_女'): 39, ('182239_男', '182329_女'): 40, ('182239_男', '182340_女'): 37, ('182239_男', '182403_女'): 35, ('182873_男', '182191_女'): 31, ('183343_男', '183980_女'): 44,
1、可疑男生1-180624
回到原始數據,查看他和不同女生在時間上消費的交集情況。
(1)和女生181013的交集:
•4月1號早上7.36:應該是一起吃了早餐;11點54一起吃了午飯
•4.10、4.12等不同時間點的交集
(2)和女生181042的交集:
2、看看可疑的渣男3
這哥們實在是厲害呀~數據挖掘顯示居然和4個女生同時存在一定的關聯!
('182239_男', '182304_女'): 39 ('182239_男', '182329_女'): 40 ('182239_男', '182340_女'): 37 ('182239_男', '182403_女'): 35
除了可能的男女朋友關係,在2元數據中更多的是基友或者閨蜜:
('180450_女', '180484_女'): 35, ('180457_女', '180493_女'): 31, ('180460_女', '180496_女'): 31, ('180493_女', '180500_女'): 47, ('180504_女', '180505_女'): 43, ('180505_女', '180506_女'): 35, ('180511_女', '181847_女'): 42, ('180523_男', '182415_男'): 34, ('180526_男', '180531_男'): 33, ('180545_女', '180578_女'): 41, ('180545_女', '180615_女'): 47, ('180551_女', '180614_女'): 31, ('180555_女', '180558_女'): 36, ('180572_女', '180589_女'): 31, ('181069_男', '181103_男'): 44, ('181091_男', '181103_男'): 33, ('181099_男', '181102_男'): 31, ('181099_男', '181107_男'): 34, ('181102_男', '181107_男'): 35, ('181112_男', '181117_男'): 43, ('181133_男', '181136_男'): 52, ('181133_男', '181571_男'): 45, ('181133_男', '181582_男'): 33,
3-4個人
3-4元的數據可能是一個宿舍的同學或者朋友一起的,相對數量會比較少:
len(itemsets[3]) # 18條 {('180363_女', '181876_女', '183979_女'): 40, ('180711_女', '180732_女', '180738_女'): 35, ('180792_女', '180822_女', '180849_女'): 35, ('181338_男', '181343_男', '181344_男'): 40, ('181503_男', '181507_男', '181508_男'): 33, ('181552_男', '181571_男', '181582_男'): 39, ('181556_男', '181559_男', '181568_男'): 35, ('181848_女', '181865_女', '181871_女'): 35, ('182304_女', '182329_女', '182340_女'): 36, ('182304_女', '182329_女', '182403_女'): 32, ('183305_女', '183308_女', '183317_女'): 32, ('183419_女', '183420_女', '183422_女'): 49, ('183419_女', '183420_女', '183424_女'): 45, ('183419_女', '183422_女', '183424_女'): 48, ('183420_女', '183422_女', '183424_女'): 51, ('183641_女', '183688_女', '183690_女'): 32, ('183671_女', '183701_女', '183742_女'): 35, ('183713_女', '183726_女', '183737_女'): 36}
4元數據只有一條:
總結
關聯規則分析是一個經典數據挖掘演算法,在消費明細數據、超市購物籃數據、金融保險、信用卡等領域應用的十分廣泛。
當我們運用關聯分析技術挖掘出頻繁出現的組合和強關聯規則之後,就可以指定相應的營銷策略或者找到不同對象之間的關係。
上面的數據挖掘過程,其實也存在一定的缺陷:
•約束太寬:僅僅是根據時間間隔類型進