您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
利用Python进行数据分析——数据聚合与组操作
 
  3902  次浏览      15
 2019-4-2 
 
编辑推荐:
来源csdn ,主要讲解了GroupBy机制,groups中的迭代,Dicts与Series分组,应用函数进行分组,根据索引等级分组,数据聚合等结合案例详细讲解。

import numpy as np
import pandas as pd

GroupBy机制

上图显示了一个分组背后的具体操作,当操作一个数据集按照某个key进行分组时,数据集首先会按组进行分割,然后再对每一组应用函数,最后返回分组后的结果。

df=pd.DataFrame({
'key1':['a','a','b','b','a'],
'key2':['one','two','one','two','one'],
'data1':np.random.randn(5),
'data2':np.random.randn(5)
})
df.loc[:,'data1'].groupby(df.loc[:,'key1']).mean() #将data1列按照key1进行分组,再求均值

当需要按照多个key进行分组时,给groupby()传递一个列表即可,得到的结果是具有层级index的Series:

mean=df.loc[:,'data1'].groupby([df.loc[:,'key1'],df.loc[:,'key2']]).mean()
mean.unstack()

当对整个数据集进行分组时,可以直接给groupby()传递key的值,此时不可再用loc()与iloc()方法,因为groupby()生成的是一个groupby对象,而不是DataFrame:

df.groupby(['key1','key2'])['data2'].mean()

另一个应用于groupby()之后的方法为size():

df.groupby(['key1','key2']).size()

groups中的迭代

GroupBy对象是一个可迭代对象:

for key,data in df.groupby('key1'):
print(key)
print(data)

根据Dicts与Series分组

建立映射关系如dict或series,将列先进行映射再进行分组。

people=pd.DataFrame(
np.random.randn(5,5),
index=['Joe','Steve','Wes','Jim','Travis'],
columns=['a','b','c','d','e']
)
people.iloc[2,[1,2]]=None
mapping={
'a':'red',
'b':'red',
'c':'blue',
'd':'blue',
'e':'red',
'f':'orange'
}
people.groupby(mapping,axis=1).mean()

map_series=pd.Series(mapping)
people.groupby(map_series,axis=1).mean()

应用函数进行分组

比如对上述数据集,如需要对名字长度进行分组,则可以给groupby()传递一个函数作为参数:

people.groupby(len,axis=0).mean()

根据索引等级分组

对于带层级索引的数据集,可以根据某一层级的索引名称进行分组,指定参数level=即可:

hier_df=pd.DataFrame(
np.random.randn(4,5),
columns=[['US','US','US','JP','JP'],
[1,3,5,1,3]]
)
hier_df.columns.names=['city','tensor']
hier_df.groupby(level='city',axis=1).count()

数据聚合

tips=pd.read_csv('examples/tips.csv')
tips.loc[:,'tip_pct']=tips.loc[:,'tip']/tips.loc[:,'total_bill']
tips.sample(3)

grouped=tips.groupby(['day','smoker'])
grouped['tip_pct'].mean()

可以对groupby对象的agg()方法传递一个函数名列表,会返回一个groupby对象应用函数后生成的DataFrame:

grouped.agg(['min','max','mean'])

返回无行索引的聚合数据

使用参数as_index=参数来返回一个无行索引的数据:

tips.groupby(['day','smoker'],as_index=False).mean()

 

可见行索引被转换成了列值。

Apply

GroupBy()方法最普遍的目的就是在数据集上应用函数以筛选出想要的数据。比如用户自己写了一个top()函数,它会返回DataFrame指定列中值最大的n条记录:

def top(df,n=5,column='tip_pct'):
return df.sort_values(by=column).iloc[-n:,:]

 

tips.groupby('smoker').apply(top,n=3) #筛选3条tip_pct最大的数据

可以看到以’smoker’分组方法筛选出来的数据条目中还包含了由分组产生的’smoker’行索引,可以使用参数group_keys=来消除分组索引:

tips.groupby ('smoker',group_keys =False).apply(top,n=3) #筛选3条tip_pct最大的数据

分位数与桶分析

frame=pd.DataFrame({
'data1':np.random.randn(1000),
'data2':np.random.randn(1000)
})
quartiles= pd.cut(frame.loc[:,'data1'],4) #以data1生成四个区间

 

def get_stats(group):
return {
'min':group.min(),
'max':group.max(),
'mean':group.mean()
}

 

grouped= frame.loc[:,'data2' ].groupby(quartiles) #以data1的区间来对data2进行分组
grouped.apply(get_stats).unstack()

示例

随机采样与改序

假设需要生成一组随机采样(有放回或无放回)来做蒙特卡洛分析,或者是用做机器学习项目中的数据子集,需要对原数据集进行随机采样或者改序。

#生成一副牌组Series
suits=['H','S','C','D']
base_name=['A']+list(range(2,11))+['J','Q','K']
cards=[]
for suit in suits:
cards.extend(str(num)+suit for num in base_name)
card_val=(list(range(1,14)))*4
deck=pd.Series(card_val,index=cards)

 

#抽牌函数
def draw(deck,n=5):
return deck.sample(n)

 

draw(deck)

 

4H 4

6C 6

5C 5

AH 1

7C 7

dtype: int64

假设现在需要从每个花色中随机抽出两张牌,可以先按花色来对牌组进行分组再应用抽牌函数:

get_suit=lambda card:card[-1] #card的最后一位表示花色,这里没太懂
deck.groupby (get_suit,group_keys=False).apply (draw,n=2)

 

6C 6

10C 10

KD 13

QD 12

9H 9

JH 11

5S 5

6S 6

dtype: int64

分组的加权均值与相关系数

如果数据是带权重的,使用apply()方法可以很方便的计算加权平均值:

frame=pd.DataFrame({
'category':['a','a','b','b'],
'data':np.random.randn(4),
'weights':np.random.rand(4)
})
frame

get_wavg=lambda grouped:np.average(grouped.loc[:,'data'],weights=grouped.loc[:,'weights'])
frame.groupby('category').apply(get_wavg)

 

在下一个例子前,先了解一下pct_change()方法:

obj=pd.Series(np.arange(1,5))
obj.pct_change()

接下来我们导入一个真实数据集,进行相关性分析:

close_px=pd.read_csv ('examples/stock_px_2.csv', parse_dates=True,index_col=0)
close_px.info()

close_px.head()

使用pct_change()来计算日回报率:

eturns=close_px.pct_change().dropna()
returns.head()

我们把数据按年进行聚合,再使用apply()方法显示以SPX为参照的各公司收益相关性:

get_year=lambda timestamp:timestamp.year #此数据集的行索引为时间对象,无loc()方法
spx_cor=lambda x:x.corrwith(x.loc[:,'SPX'])

 

returns.groupby(get_year).apply(spx_cor)

还可以得到指定两家公司的年收益相关性:

AAPL_cor_MSFT=lambda x:x.loc[:,'AAPL'].corr(x.loc[:,'MSFT'])
returns.groupby(get_year).apply(AAPL_cor_MSFT)

 

2003 0.480868

2004 0.259024

2005 0.300093

2006 0.161735

2007 0.417738

2008 0.611901

2009 0.432738

2010 0.571946

2011 0.581987

dtype: float64

透视表与交叉表

pivot_table()方法与groupby()方法能得到相似的结果,不过pivot_table()方法能提供更强大的功能。

tips=pd.read_csv('examples/tips.csv')
tips.pivot_table(index=['day','smoker'])

以上结果同样可以通过tips.groupby(['day','smoker'])得到。如果现在我们只想生成tip和size列的透视表,以time和day来分组:

tips.pivot_table(['tip','size'],index=['time','day'],columns='smoker')

交叉表

以两个Series或list组成一个表

pd.crossta([tips.loc[:,'time'], tips.loc[:,'day']], tips.loc[:,'smoker'], margins=True) #margins显示总额

   
3902 次浏览       15
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试