數(shù)據(jù)分組是對相同類別的數(shù)據(jù)進(jìn)行匯總,而數(shù)據(jù)透視表是通過對行或列的不同組合對數(shù)據(jù)進(jìn)行匯總,所使用的匯總方法有求和、計數(shù)、平均值、標(biāo)準(zhǔn)差等,本文使用Python對數(shù)據(jù)進(jìn)行數(shù)據(jù)分組和數(shù)據(jù)透視,下面一起來學(xué)習(xí)。
這里首先導(dǎo)入pandas和datetime庫,生成一個包含'用戶ID','日期','城市','年齡','性別','成交量'的DataFrame數(shù)據(jù)。
import pandas as pdimport datetime
df = pd.DataFrame({'用戶ID':[1001,1002,1003,1004,1005,1006], '日期':pd.date_range(datetime.datetime(2021,3,23),periods=6), '城市':['北京', '上海', '廣州', '上海', '杭州', '北京'], '年齡':[23,44,54,32,34,32], '性別':['F','M','M','F','F','F'], '成交量':[3200,1356,2133,6733,2980,3452]}, columns =['用戶ID','日期','城市','年齡','性別','成交量'])df
groupby可以通過傳入需要分組的參數(shù)實現(xiàn)對數(shù)據(jù)的分組,參數(shù)可以是單列,也可以是多列,分組后可以對單列進(jìn)行函數(shù)處理,也可以對多列進(jìn)行函數(shù)處理。
#按照單列分組df.groupby('城市').count()
#按照單列分組df.groupby('城市')['用戶ID'].count()
先篩選列再groupby與先groupby再篩選列得出來的結(jié)果是一樣的。
# 先篩選,然后groupby要加dfdf['成交量'].groupby([df['城市'],df['性別']]).sum()
如果先聚合,聚合列可以只寫列名,不加變量名,因為沒有篩選某列前,可以直接搜索到列。
#先groupby()再寫列,列不用加dfdf.groupby(['城市','性別'])['成交量'].count() #計數(shù)
#先groupby()再寫列,列不用加dfdf.groupby(['城市','性別'])['成交量'].sum() #求和
使用unstack函數(shù),增加數(shù)據(jù)透視的效果。
# 增加透視效果df['成交量'].groupby([df['城市'],df['性別']]).sum().unstack()
as_index=False,會按從0開始的數(shù)據(jù)索引。
#分組鍵一般會作為分層索引,如果不想要,可以在group()中加上參數(shù):as_index=False,會按從0開始的數(shù)據(jù)索引df.groupby([df['城市'], df['性別']],as_index=False).sum()
先數(shù)據(jù)分組,然后做描述分析。
df.groupby('城市').describe()
size顯示數(shù)據(jù)組分類的多少。
df.groupby('城市').size()
groupby與agg兩者可以結(jié)合使用,可以對單列或多列進(jìn)行單一或多個不同的聚合運(yùn)算, 常用聚合函數(shù)有count,sum,std等,直接用函數(shù)名加引號即可,如果有多個函數(shù)時,可以用逗號隔開;
# 常用聚合函數(shù)用引號即可引用df.groupby(['城市', '性別']).agg('sum')
列表可以同時使用多個函數(shù),用逗號隔開。
# 列表可以同時使用多個函數(shù)df.groupby(['城市', '性別']).agg(['mean','std','sum','count'])
reset_index用來重置索引。
# 列表可以同時使用多個函數(shù)df.groupby(['城市', '性別']).agg(['mean','std','sum','count']).reset_index()
用元組修改函數(shù)名。
# 可以用元組修改函數(shù)名df.groupby(['城市', '性別']).agg([('No.1', 'sum'), ('No.2', 'std')])
可以對不同的列使用不同的函數(shù)進(jìn)行運(yùn)算。
#如果不同列用不同函數(shù),可以對不同的列使用不同的函數(shù)df.groupby(['城市', '性別']).agg({'年齡': ['max','min'],'成交量': ['sum', 'count', 'std']})
apply與agg相同點:都可以對分組后的結(jié)果進(jìn)行運(yùn)算;
apply與agg不同點:agg只能對單列,apply可以對多列進(jìn)行;apply可以使用匿名函數(shù),agg不可以使用匿名函數(shù)。
#首先定義一個top函數(shù),使用apply函數(shù)進(jìn)行運(yùn)算def top(df, n=2, column='成交量'): return df.sort_values(by=column)[-n:] # 自建函數(shù)df.groupby('城市').apply(top)
直接使用apply函數(shù)進(jìn)行聚合運(yùn)算。
df.groupby('城市').apply(top, n=3, column='成交量')
qcut是等樣本數(shù),cut是等值區(qū)間分,groupby和cut和qcut結(jié)合使用,可以對等值或等樣本數(shù)分組后的結(jié)果進(jìn)行分析。
#使用numpy生成兩個隨機(jī)數(shù)import numpy as npdf = pd.DataFrame({'data1':np.random.randn(1000), 'data2': np.random.randn(1000)})df.head()
將數(shù)據(jù)data1等值區(qū)間四等分。
#將數(shù)據(jù)data1等值區(qū)間四等分quariles = pd.cut(df.data1, 4)quariles[:10]
數(shù)據(jù)data1等樣本數(shù)四等分。
#將數(shù)據(jù)data1等樣本數(shù)四等分quriles_1 = pd.qcut(df.data1,4)quriles_1[:10]
apply函數(shù)主要用于對DataFrame中的某一column或row中的元素執(zhí)行相同的函數(shù)操作,而applymap函數(shù)主要用于對DataFrame中每一個元素執(zhí)行系統(tǒng)的操作,apply和applymap都要與lambda結(jié)合使用。
#首先生成A,B,C的一個隨機(jī)數(shù)組import numpy as npdf = pd.DataFrame({'A':np.random.rand(3), 'B': np.random.rand(3), 'C': np.random.rand(3) })df.head()
#對A列的每一個元素加1df['A'].apply(lambda x:x+1)
#對表內(nèi)的每個元素加1df.applymap(lambda x:x+1)
定義一個get函數(shù),對data2數(shù)據(jù)使用apply函數(shù)做聚合運(yùn)算。
def get(group): return {'min':group.min(),'max':group.max(),'count': group.count(),'mean': group.mean()}df.data2.groupby(quariles).apply(get)
使用unstack函數(shù)顯示數(shù)據(jù)透視表效果。
df.data2.groupby(quariles).apply(get).unstack()
labels=False采用默認(rèn)的0開始的索引。
# 去掉分組數(shù)值lable,采用默認(rèn)的0開始的索引q = pd.qcut(df.data1, 10, labels=False) df.data2.groupby(q).apply(get).unstack()
數(shù)據(jù)透視表使用的是pivot_table函數(shù),接下來介紹該函數(shù)使用最多的幾個參數(shù)。data表示使用數(shù)據(jù)透視表數(shù)據(jù),values表示計算值,index表示數(shù)據(jù)透視的行,columns表示數(shù)據(jù)透視的列,aggfunc表示計算類型,margins表示是否顯示合計列,margins_name表示合計列的名字。
pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')
margins顯示合計,并且margins_name修改合計名稱。
#margins顯示合計,margins_name修改合計名稱pd.pivot_table(df,values = '用戶ID',columns ='性別',index='城市',aggfunc='count',margins = True,margins_name ='合計')
當(dāng)數(shù)據(jù)透視結(jié)果有缺失值時,用fill_value = 0缺失值填充。
#fill_value = 0缺失值填充pd.pivot_table(df,values = '用戶ID',columns ='性別',index='城市',aggfunc='count',fill_value = 0)
aggfunc={'用戶ID':'count','成交量':'sum'},對用戶ID做計數(shù)運(yùn)算,對成交量做求和運(yùn)算。
pd.pivot_table(df,values = ['用戶ID','成交量'],columns='性別',index='城市',aggfunc={'用戶ID':'count','成交量':'sum'},fill_value = 0)
reset_index對數(shù)據(jù)透視結(jié)果重置索引。
pd.pivot_table(df,values = ['用戶ID','成交量'],columns='性別',index='城市',aggfunc={'用戶ID':'count','成交量':'sum'},fill_value = 0).reset_index()