前言
本文的文字及圖片來源于網絡,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯系我們以作處理。
作者:嚴小樣兒
分布分析法,一般是根據分析目的,將數據進行分組,研究各組別分布規律的一種分析方法。數據分組方式有兩種:等距或不等距分組。
分布分析在實際的數據分析實踐中應用非常廣泛,常見的有用戶性別分布,用戶年齡分布,用戶消費分布等等。
本文將進行如下知識點講解:
1.數據類型的修改
2.新字段生成方法
3.數據有效性校驗
4.性別與年齡分布
分布分析
1.導入相關庫包
import pandas as pd
import matplotlib.pyplot as plt
import math
2.數據處理
>>> df = pd.read_csv('UserInfo.csv')
>>> df.info()
RangeIndex: 1000000 entries, 0 to 999999
Data columns (total 4 columns):
UserId 1000000 non-null int64
CardId 1000000 non-null int64
LoginTime 1000000 non-null object
DeviceType 1000000 non-null object
dtypes: int64(2), object(2)
memory usage: 30.5+ MB
由于接下來我們需要做年齡分布分析,但是從源數據info()方法可知,并無年齡字段,需要自己生成。
# 查看年齡區間,進行分區
>>> df['Age'].max(),df['Age'].min()
# (45, 18)
>>> bins = [0,18,25,30,35,40,100]
>>> labels = ['18歲及以下','19歲到25歲','26歲到30歲','31歲到35歲','36歲到40歲','41歲及以上']
>>> df['年齡分層'] = pd.cut(df['Age'],bins, labels = labels)
3.計算年齡
由于數據來源于線下,并未進行數據有效性驗證,在進行年齡計算前,先針對數據進行識別,驗證。
# 提取出生日期:月和日
>>> df[['month','day']] = df['DateofBirth'].str.split('-',expand=True).loc[:,1:2]
# 提取小月,查看是否有31號
>>> df_small_month = df[df['month'].isin(['02','04','06','09','11'])]
# 無效數據,如圖所示
>>> df_small_month[df_small_month['day']=='31']
# 統統刪除,均為無效數據
>>> df.drop(df_small_month[df_small_month['day']=='31'].index,inplace=True)
# 同理,校驗2月
>>> df_2 = df[df['month']=='02']
# 2月份的校驗大家可以做的仔細點兒,先判斷是否潤年再進行刪減
>>> df_2[df_2['day'].isin(['29','30','31'])]
# 統統刪除
>>> df.drop(df_2[df_2['day'].isin(['29','30','31'])].index,inplace=True)
# 計算年齡
# 方法一
>>> df['Age'] = df['DateofBirth'].apply(lambda x : math.floor((pd.datetime.now() - pd.to_datetime(x)).days/365))
# 方法二
>>> df['DateofBirth'].apply(lambda x : pd.datetime.now().year - pd.to_datetime(x).year)
4.年齡分布
# 查看年齡區間,進行分區
>>> df['Age'].max(),df['Age'].min()
# (45, 18)
>>> bins = [0,18,25,30,35,40,100]
>>> labels = ['18歲及以下','19歲到25歲','26歲到30歲','31歲到35歲','36歲到40歲','41歲及以上']
>>> df['年齡分層'] = pd.cut(df['Age'],bins, labels = labels)
由于該數據記錄的是用戶登錄信息,所以必定有重復數據。而Python如此強大,一個nunique()方法就可以進行去重統計了。
# 查看是否有重復值
>>> df.duplicated('UserId').sum() #47681
# 數據總條目
>>> df.count() #980954
分組后用count()方法雖然也能夠計算分布情況,但是僅限于無重復數據的情況。而Python這么無敵,提供了nunique()方法可用于計算含重復值的情況
>> df.groupby('年齡分層')['UserId'].count()
年齡分層
18歲及以下 25262
19歲到25歲 254502
26歲到30歲 181751
31歲到35歲 181417
36歲到40歲 181589
41歲及以上 156433
Name: UserId, dtype: int64
# 通過求和,可知重復數據也被計算進去
>>> df.groupby('年齡分層')['UserId'].count().sum()
# 980954
>>> df.groupby('年齡分層')['UserId'].nunique()
年齡分層
18歲及以下 24014
19歲到25歲 242199
26歲到30歲 172832
31歲到35歲 172608
36歲到40歲 172804
41歲及以上 148816
Name: UserId, dtype: int64
>>> df.groupby('年齡分層')['UserId'].nunique().sum()
# 933273 = 980954(總)-47681(重復)
# 計算年齡分布
>>> result = df.groupby('年齡分層')['UserId'].nunique()/df.groupby('年齡分層')['UserId'].nunique().sum()
>>> result
# 結果
年齡分層
18歲及以下 0.025731
19歲到25歲 0.259516
26歲到30歲 0.185189
31歲到35歲 0.184949
36歲到40歲 0.185159
41歲及以上 0.159456
Name: UserId, dtype: float64
# 格式化一下
>>> result = round(result,4)*100
>>> result.map("{:.2f}%".format)
年齡分層
18歲及以下 2.57%
19歲到25歲 25.95%
26歲到30歲 18.52%
31歲到35歲 18.49%
36歲到40歲 18.52%
41歲及以上 15.95%
Name: UserId, dtype: object
通過以上結果及分布圖可以知道,19到25歲年齡段的用戶占比最高,為26%。