Pandas数据分析12——pandas数据分组聚合

 参考书目:《深入浅出Pandas:利用Python进行数据处理与分析》


分类数据可以进行分组,然后分组进行统计计算。

读取案例数据

import numpy as np
import pandas as pd 
data = 'https://www.gairuo.com/file/data/dataset/team.xlsx'
df = pd.read_excel(data) 

groupby参数用法

df.groupby(self, by=None, axis=0, level=None,
           as_index: bool=True, sort: bool=True,
           group_keys: bool=True,
           squeeze: bool=False,
           observed: bool=False, dropna=True)

基本用法

df.groupby('team').sum() # 按团队分组对应列相加
df.groupby('team').mean() # 按团队分组对应列求平均
# 不同列不同的计算方法
df.groupby('team').agg({'Q1': sum,  # 总和
                        'Q2': 'count', # 总数
                        'Q3':'mean', # 平均
                        'Q4': max}) # 最大值

df.groupby('team').agg({'Q1': [sum,'std',max]  # 三个方法
                        'Q2': 'count', # 总数
                        'Q3':'mean', # 平均
                        'Q4': max}) # 最大值
#如果按一列聚合,只传列名字符串,如果多个就要传由列名组成的列表
#聚合方法可以使用 Pandas 的数学统计函数 或者 Numpy 的统计函数
#如果是 python 的内置统计函数,直接使用变量,不需要加引号
#如果需要将空值也进行聚合,需要传入 dropna=Flase

分组对象

df.groupby('team')
df.Q1.groupby('team')
grouped=df.groupby('col')
grouped=df.groupby('col',axis='columns')
grouped=df.groupby(['col1','col2'])

###分组用法
grouped=df.groupby('team')
grouped.get_group('D')
grouped2=df.groupby(['team',df.name.str[0]])
grouped2.get_group('B','H')     #B组,名字H开头
df.groupby('team').groups       #查看分组内容(字典)
grouped.groups.indices          #组名为键,组内索引为数组的字典
dgrouped.groups.keys()          #查看分组名
grouped.Q1
grouped[['Q1','Q2']]
for name,group in grouped:
    print(name) #组名str
    print(group)#df
### 将数据分为两组
df.groupby(lambda x:x%2==0).sum()  #索引是否为偶数分为两组
df.groupby(df.index%2==0).sum() 
df.groupby(lambda x:x>50)          #索引是否大于50
df.groupby(df.index>=50).sum()
df.groupby(lambda x:'Q' in x ,axis=1).sum() #列名含有Q的
#其他筛选
df.groupby(df.index%2==0)   #奇偶列
df.groupby(df.name.str[0])  #姓名首字母
df.groupby(df.team.isin(['A','B']))         #A和B,其他,分组
df.groupby([df.name.str[0],df.name.str[1]]) #姓名的第一二个字母
df.groupby([df.time.date,df.time.hour])     #日期小时分组

函数分组

df.groupby(df.time.apply(lambda x:x.year)).count()  #从时间列time中提取年份来分组
#案例 ,按姓名的首字母为元音,辅音分组
def get_letter_type(letter):
    if letter[0].lower() in 'aeiou':
        return '元音'
    else:
        return '辅音'
df.set_index('name').groupby(get_letter_type).sum()


多种方法混合 

df.groupby(['team',df.name.apply(get_letter_type)]).sum()
#Groupby 操作后分组字段会成为索引,如果不想让它成为索引,可以使用 as_index=False 进行设置
#不想排序使用 sort=False


 pipe

#调用pipe分组用法
df.pipe(pd.DataFrame.groupby,'team').sum()

分组对象应用函数

df.groupby('team').apply(lambda x: x*2)
df.groupby('team').apply(lambda x: x['name'].to_list())    #分组一列输出为列表
df.groupby('team').apply(lambda x: x['name'].to_list()).A  #查看某个组
df.name.groupby('team').apply(np.array)                    # 输出一个 np.array
# 各组 Q1(为参数) 成绩的前3个
def first_5(df_, c):
    return df_[c].sort_values(ascending = False).head(3)
# 调用函数
df.set_index('name').groupby('team').apply(first_5, 'Q1')
# group_keys 可以使分组字段不做为索引
df.set_index('name').groupby('team', group_keys=False).apply(first_5, 'Q1')

筛选filter()

df.groupby('team').mean()
df.groupby('team').mean().mean(1)
df.groupby('team').filter(lambda x:x.mean(1).mean()>51)      #筛选所在组总平均分大于51的人
df.groupby('team').filter(lambda x: len(x) >= 3)             # 值的长度都大于等于 3 的 
df.groupby(['team']).filter(lambda x: (x['Q1'] > 97).any())  # Q1成绩只要有一个大于97的组
df.groupby(['team']).filter(lambda x: (x.mean() >= 60).all())# 所有成员平均成绩大于 60 的组
df.groupby('team').filter(lambda g: g.Q1.sum() > 1060)      # Q1 所有成员成绩之和超过 1060 的组

其他功能

df.groupby('team').first() # 组内第一个
df.groupby('team').last() # 组内最后一个
df.groupby('team').ngroups # 5 (分组数)
df.groupby('team').ngroup() # 分组序号
grouped=df.groupby('team')
grouped.backfill()
grouped.bfill()
grouped.head(2)#每组前2个
grouped.tail(1)#每组最后一个
grouped.rank() #组内排序值
grouped.fillna(0)
#分组中第几个值
grouped.nth(1)#第一个
grouped.nth(-1)#最后一个
grouped.nth([2,-1])
grouped.shift(-1)#组内移动
grouped.tshift(1)#时间周期移动
#仅series可用  返回还有索引
grouped.Q1.nlargest(2)     #每组最大两个
grouped.Q1.nsmallest(3)    #每组最小两个
grouped.Q1.nunique()       #每组去重数量
grouped.Q1.unique()        #每组去重值
grouped.Q1.value_counts()  #每组值种类和数量统计
grouped.Q1.is_monotonic_increasing #每组是否单调递增
grouped.Q1.is_monotonic_decreasing #每组是否单调递减
#仅df
grouped.corrwith(df2)  #计算相关性


聚合统计

df.groupby('team').describe() # 描述性统计
df.groupby('team').sum() # 求和
df.groupby('team').count() # 每组数量,不包括缺失值
df.groupby('team').max() # 求最大值
df.groupby('team').min() # 求最小值
df.groupby('team').size() # 分组数量
df.groupby('team').mean() # 平均值
df.groupby('team').median() # 中位数
df.groupby('team').std() # 标准差
df.groupby('team').var() # 方差
grouped.corr() # 相关性系数
grouped.sem() # 标准误差
grouped.prod() # 乘积
grouped.cummax() # 每组的累计最大值
grouped.cumsum() # 累加
grouped.mad() # 平均绝对偏差
grouped.median()#中位数
grouped.quantile()#中位数
grouped.quantile(0.75)#四分位
grouped.diff() #组内前后差值

agg()聚合方法

# 所有列使用一个计算计算方法
df.groupby('team').aggregate(sum)
df.groupby('team').agg(sum)
grouped.agg(np.size)
grouped['Q1'].agg(np.mean)

# 所有列指定多个计算方法
grouped.agg([np.sum, np.mean, np.std])
# 指定列使用多个计算方法
grouped[['Q1','Q3']].agg([sum, np.mean, np.std])
# 一列使用多个计算方法
df.groupby('team').agg({'Q1': ['min', 'max'], 'Q2': 'sum'})

# 指定列名,列表是为原列和方法
df.groupby('team').Q1.agg(Mean='mean', Sum='sum')
df.groupby('team').agg(Mean=('Q1', 'mean'), Sum=('Q2', 'sum'))
df.groupby('team').agg(Q1_max=pd.NamedAgg(column='Q1', aggfunc='max'),
                       Q2_min=pd.NamedAgg(column='Q2', aggfunc='min'))
# 如果列名不是有效的 python 变量,则可以用以下方法
df.groupby('team').agg(**{'1_max':pd.NamedAgg(column='Q1', aggfunc='max')})
# lambda/函数 所有方法都可以用
def max_min(x):
    return x.max() - x.min()  # 定义函数
df.groupby('team').agg(max_min)
df.groupby('team').Q1.agg(Mean='mean',
                          Sum='sum',
                          Diff=lambda x: x.max() - x.min(),
                          Max_min=max_min)
# 不同列不同的计算方法
df.groupby('team').agg({'Q1': sum,  # 总和
                        'Q2': 'count', # 总数
                        'Q3':'mean', # 平均
                        'Q4': max}) # 最大值

 


时间重采样方法 resample()

idx = pd.date_range('1/1/2000', periods=100, freq='T')
df2 = pd.DataFrame(data=1 * [range(2)],index=idx,
                  columns=['a', 'b'])
# 三个周期一聚合(一分钟一个周期)
df2.groupby('a').resample('3T').sum()
# 30 秒一分组
df2.groupby('a').resample('30S').sum()
# 每月
df2.groupby('a').resample('M').sum()
# 以右边时间点为标识
df2.groupby('a').resample('3T', closed='right').sum()

数据分箱

pd.cut(df.Q1, bins=[0, 60, 100]) #将Q1成绩分成两个区间
df.Q1.groupby(pd.cut(df.Q1, bins=[0, 60, 100])).count() #变成分类变量然后分组统计
df.groupby(pd.cut(df.Q1, bins=[0, 60, 100])).count()    #整个数据框分组

pd.cut(df.Q1, bins=[0, 60, 100],labels=False)            # 不显示区间,使用数字做为标签(0,1,2,n)
pd.cut(df.Q1, bins=[0, 60, 100],labels=['不及格','及格',]) # 指定标签名
pd.cut(df.Q1, bins=[0, 60, 100], include_lowest=True)    # 包含最低部分
pd.cut(df.Q1, bins=[0, 89, 100], right=False)            # 是否包含右边,闭区间,下例 [89, 100)

#不同分数映射案例
df3 = pd.DataFrame({'A':[1, 3, 5, 7, 9]})
df3.assign(B=pd.cut(df3.A, [0,5,7, float('inf')], labels=['差','中','好']))

扫描二维码关注公众号,回复: 14467516 查看本文章

等宽分箱 qcut

pd.qcut(df.Q1,q=2) #自动分为2组,且样本长度相同
pd.qcut(df.Q1,q=2).unique()
pd.qcut(df.Q1,q=3).value_counts()
df.groupby(pd.qcut(df.Q1,2)).count() #应用到分组上

#其他参数
pd.qcut(range(5), 4)
pd.qcut(range(5), 4, labels=False)
# 指定标签名
pd.qcut(range(5), 3, labels=["good", "medium", "bad"])
# 返回箱子标签 array([ 1. , 51.5, 98. ]))
pd.qcut(df.Q1,q=2, retbins=True)
# 分箱位小数位数
pd.qcut(df.Q1,q=2,precision=3)
# 排名分3个层次
pd.qcut(df.Q1.rank(method='first'),3)


分组可视化

grouped=df.set_index('name').groupby('team')
grouped.plot(figsize=(4,0.8))
grouped.hist()   #直方图hist()
grouped.boxplot()#箱线图
##或者是
df.boxplot(by='team')

猜你喜欢

转载自blog.csdn.net/weixin_46277779/article/details/126136836