首页 > 编程语言 > 详细

Python--DataFrame分组-GroupBy

时间:2019-11-20 23:21:29      阅读:139      评论:0      收藏:0      [点我收藏+]

DataFame分组功能及其他配合使用方法


 

分组统计 ?? GroupBy

 

# *.groupby(by=None,axis=0,level=None,as_index=True,sort=True,group_keys=True,squeeze=False,observed=False,**kwargs)
# axis=0 行  / 1 列

 

有这样一组数据 : 

技术分享图片
df = pd.DataFrame({
    key1:[a,a,b,b,a],
    key2:[one,two,one,two,three],
    data1:np.random.randn(5),
    data2:np.random.randn(5)
})

#-------------------------------#
    key1    key2    data1    data2
0    a    one    -0.205263    1.820120
1    a    two    0.436864    -1.858459
2    b    one    0.695624    1.134222
3    b    two    0.281301    1.735320
4    a    three    1.040519    0.657742
View Code

如何对 ‘key1’ 进行 分组 并求 平均值 ?

ass = df[‘data1‘].groupby(df[key1]) #这是一个分组对象,没有进行任何计算
ass.mean()  # 对"对象" 进行调用方法

# df.groupby(‘key1‘).mean()
# df[[‘data1‘,‘data2‘]].groupby(‘key1‘).mean()

技术分享图片

 

 比较简单 ,呵 ,那么如何对多个 ‘字段‘ 进行分组 ? 要求对 key1 , key2进行分组并计算data2的平均值

技术分享图片
df[data2].groupby([df[key1],df[key2]]).mean()

# 这种分组  只需要将需要的字段放入数组( 也是列表[] )中即可

#---------------------------#
key1  key2 
a     one      1.820120
      three    0.657742
      two     -1.858459
b     one      1.134222
      two      1.735320
Name: data2, dtype: float64
View Code

有如下数据

city =Series([北京,长沙,长沙,北京,北京])
years = Series([2018,2018,2019,2018,2019])

#---------------------------#
0    北京
1    长沙
2    长沙
3    北京
4    北京
dtype: object
0    2018
1    2018
2    2019
3    2018
4    2019
dtype: int64

那么 , 如何用城市年份df 进行分组呢?

技术分享图片
df[data1].groupby([city,years]).mean()  

#----------------------------#
北京  2018   -0.681558
    2019    1.580496
长沙  2018   -0.112299
    2019   -0.498441
Name: data1, dtype: float64

# 分组的键可以是任何长度适当(=len(index))的数组
# ??  这个就是将分组键改成了自定义城市和年份 匹配相同的相加求平均值 ,不匹配的不计算
# 北京的2018相加 求平均  北京2019 相加求平均 . 长沙的也一样
View Code

那又 如何对整个 dfkey1 分组求平均值

技术分享图片
df.groupby([key1]).mean() 
# ?? 自动聚合数值列,忽略 非数值 列

df.groupby([key1,key2]).mean()
# ?? 可以将 列名 作为分组键


#----------------------# 
    data1    data2
key1        
a    0.424040    0.206468
b    0.488462    1.434771

#----------------------#
        data1    data2
key1    key2        
a    one    -0.205263    1.820120
        three    1.040519    0.657742
        two    0.436864    -1.858459
b    one    0.695624    1.134222
        two    0.281301    1.735320
View Code

如何求分组大小组数量分组的行数

df.groupby(key1).size()   # の , 我。。。。。

#-----------------# 
key1  key2 
a     one      1
      three    1
      two      1
b     one      1
      two      1
dtype: int64

对分组进行迭代groupby 对象支持迭代,可以产生一组 二元元组,由 分组名数据块 组成。代码如下

for df1 ,df2 in df.groupby([key1]):
    print(df1)
    print(df2)

#--------------------------#
a
  key1   key2     data1     data2
0    a    one  -0.245438 -1.030687
1    a    two  -0.112299  1.817918
4    a    three  1.580496  0.861224
b
  key1   key2     data1     data2
2    b    one  -0.498441 -0.946496
3    b    two  -1.117678  0.129720

# ?? 以key1中的数据分组,分出N元元组,名字是key1中的数据名称为分组名

len(df[df[‘key1‘].duplicated()==False])  df的key1列中数据不重复的长度 上面输出的是 2

还可以在多元分组的基础上再对 key2 分组 ,如何实现呢? 如下

技术分享图片
for (k1,k2),group in df.groupby([key1,key2]):
    print(k1,k2)  # key1的值, key2的值
    print(group)  # key1的值+key2的值+后面的数据  同累型a one,a two,b one。。。这种

#------------------------#
a one
  key1 key2     data1     data2
0    a  one -0.245438 -1.030687
a three
  key1   key2     data1     data2
4    a  three  1.580496  0.861224
a two
  key1 key2     data1     data2
1    a  two -0.112299  1.817918
b one
  key1 key2     data1     data2
2    b  one -0.498441 -0.946496
b two
  key1 key2     data1    data2
3    b  two -1.117678  0.12972
View Code

如何将 groupby() 之后的对象做成一个字典呢??? dict()

dict([(a,b),(c,d)])

技术分享图片

 

 dfkey1 分组后的内容转换

技术分享图片
ps = dict(list(df.groupby([key1])))  # # 把分组内容变成一个字典对象,通过健取值,如所有a,所有b
print(ps) 

ps[a]    #取出字典中 的所有 a 组
#-----------------------#
{a:   key1   key2     data1     data2
 0    a    one -0.205263  1.820120
 1    a    two  0.436864 -1.858459
 4    a  three  1.040519  0.657742, b:   key1 key2     data1     data2
 2    b  one  0.695624  1.134222
 3    b  two  0.281301  1.735320}

    key1    key2    data1    data2
0    a    one    -0.205263    1.820120
1    a    two    0.436864    -1.858459
4    a    three    1.040519    0.657742
View Code

 

上面都是对 列 进行分组的, ‘行’ 可不可以呢?  怎么实现?

技术分享图片
# 按行的数据 , 对列进行分组  axis=1
line = df.groupby(df.dtypes,axis=1)  # 行 按数据类型进行分组
dict(list(line))

#--------------------# 
{dtype(float64):       data1     data2
 0 -0.205263  1.820120
 1  0.436864 -1.858459
 2  0.695624  1.134222
 3  0.281301  1.735320
 4  1.040519  0.657742, dtype(O):   key1   key2
 0    a    one
 1    a    two
 2    b    one
 3    b    two
 4    a  three}
View Code

按照 分组键 ,对整个对象进行分组

df.groupby([key1]).sum() 

技术分享图片

 

 

分组后有多列 , 那我如何选择其中的一列 或者多列 ,我如何得到 data1呢?

用列名对 groupby 对象进行索引,就能实现选取部分进行聚合达到目的  有效的提高效率

技术分享图片
df.groupby([key2])[data1].sum()  # 返回的是一个series对象
df.groupby([key2])[[data1,data2]].sum()   #返回的是一个DataFrame对象

#--------------------------------------#
key2
one      0.490361
three    1.040519
two      0.718165
Name: data1, dtype: float64


        data1    data2
key2    
——————————————    
one    0.490361    2.954342
three    1.040519    0.657742
two    0.718165    -0.123139
View Code

# ?? 选取一组列的时候 ,用列表的方式,返回的是 DataFrame 对象

## df[‘data1‘].groupby(df[‘key1‘]).mean() 等于 df.groupby([‘key1‘])[‘data1‘].mean() ##


通过 字典 或者 Series 进行分组

df = DataFrame(np.random.randn(5,5),columns=list(abcde),index=[长沙,北京,上海,杭州,深圳])
df.loc[2:3,[b,c]] = np.NaN  #添加几个NaN值

# 假设已知列的分组关系,希望根据分组计算列的总和
colors = {a:red,b:red,c:blue,d:blue,e:red,f:orange}

技术分享图片

 

 技术分享图片

 

技术分享图片
dt = df.groupby(colors,axis=1)
dt.sum()  # 就是对columns 使用colors重命名 同名合并 行的值  横向sum()

#------------------#
    blue            red
长沙    0.994708    0.519499
北京    -1.212472    1.080747
上海    0.472694    0.258676
杭州    -2.339634    0.598021
深圳    -1.938784    1.777040
View Code

技术分享图片

 

 

 Series 也有同样的功能  ,使用方法如下 : 

ser = Series(colors)
df.groupby(ser,axis=1).sum()  # axis =1  列之间相加 red+red+red , blue+blue

技术分享图片

 

 

 还可以通过 自定义函数 进行分组 :

def city_level(self):
    frist_city = [北京,上海,深圳]
    if self in frist_city:
        return 一线城市
    return 二线城市

df.groupby(city_level,axis=0).sum()
# ?? 会在分组键上调用一次city_level , 并且会将分组键作为参数传给city_level  返回值作为新的分组名称

技术分享图片

 

 

 还可以 组合使用,比如对城市分地域 , 所以是这么用的: 传入的函数和数组使用 ‘[ ] 列表的方式 用列表来包裹在一起

 

ars = [中部,北方,东方,东方,南方]
df.groupby([city_level,ars]).sum() 

 

技术分享图片

 

 

 


对于层次索引 , 如何根据索引的级别 来 分组 :

有这么一组数据 :

columns = pd.MultiIndex.from_arrays([[北京,北京,北京,长沙,长沙],[1,3,4,1,2]],names=[城市,级别])
dfs = DataFrame(np.random.randn(4,5),columns=columns,index=[2016,2017,2018,2019])

技术分享图片

 

 

 所以这样: ??

dfs.groupby(level=城市,axis=1).sum() 

这个就是按城市  合并sum()  行的值 = 各列相加   北京 1 3 4 相加  ,长沙1 2 相加  #

 

技术分享图片

 

 

 


常用的数据聚合函数(复习并知道)

count、sum、mean、median、std、var、min、max、prod、first、last -- 取到分组之后的每个组的函数运算的值

df.groupby(key1).get_group(a)  # 得到某一个分组
#运行前,重置下df 我运行前 前面的df都改动了#

技术分享图片

 

 

 


面向 多列的函数应用 --  Agg()

# 一次性应用多个函数计算 # 

# 有这么一个数据 # 
df = DataFrame({
    a:[1,1,2,2],
    b:np.random.rand(4),
    c:np.random.rand(4),
    d:np.random.rand(4)
})

技术分享图片

 

 

 如果我想拿到 [ b , c ,d ] 的 平均值总值 怎么搞? 一次拿到

技术分享图片
df.groupby(a).agg([mean,np.sum])
View Code

# 通过 agg 方法,传入一个列表,列表中的元素就是要作用到 每列 上的方法,可以是 字符串,也可是np的函数   #

技术分享图片

 

 


 还可以传入 字典 , key 就是columns , value 就是要 作用/使用 的函数

 

df.groupby(a)[b].agg({result:np.mean,result2:np.sum})
df.groupby(a).agg([(res1,mean),(res2,np.sum)])
# 通过二元元组列表指定列名
# 指定列名的时候,会形成层次化的索引   # df已更改,所以值和上面的对不上,使用方法是对的,###官方以后会改方法,我运行出警告了###

 

技术分享图片

 

 

 技术分享图片

 

 

 如何对不同的 列 ,进行不同的函数

df.groupby(a).agg({b:[mean,np.sum],c:np.std,d:max})
# 面向列的多函数应用

技术分享图片

 

 


数据分组转换    ??

有如下数据 : 

df = DataFrame({
    data1:np.random.rand(5),
    data2:np.random.rand(5),
    key1:list(AABBD),
    key2:[One,Two,One,Two,Four]
})

技术分享图片

 

 那么问题来了,如何为df 添加用于存放个索引分组平均值列 mean_*

# 方法一 : 先聚合,在合并

means = df.groupby(key1).mean().add_prefix(mean_)  #.add_prefix(‘**_‘) 给列名添加前缀

技术分享图片 

# 合并  merge()
pd.merge(df,key1,left_on=key1,right_index=True)  # 默认按分组排序  left_on  是列  l/r_index  是索引

技术分享图片

 

 # 方法二 : 通过 transform() 

dms = df.groupby(key1).transform(np.mean).add_prefix(mean_)
df.join(dms)  # dms 有对应索引   所以 join  会匹配索引合并

技术分享图片

 

 ?? transform 会将一个函数应用到各个分组, 然后将结果放在合适的位置上 。 


df.groupby(key1).apply(lambda x:x.describe()) # 对每个分组都进行计算,包括count,mean,std,min,max等等

技术分享图片

 

 # ?? 数据重新生成的#

 


 apply() :

传入的第一个参数是 函数 , apply方法会将分组(groupby后)的每一个片段作为参数传入函数 。返回结果,最后尝试将各个结果运行组合到一起,也就是函数运行后的结果组合到一起。 

def f_df1(d,m):
    return (d.sort_index()[:m])  #DataFrame排序后按索引选前m行数据
def f_df2(d,k1):
    return (d[k1])   # 选择DataFrame的k1列,结果为Series,层次化索引
dfs.groupby(key1).apply(f_df1,2)  # 返回分组‘key1‘排序后的每组前2行
dfs.groupby(key1).apply(f_df2,data2)  # 返回分组后表的k1列,也就是data2.结果为Series
# dfs 原数据

        data1    data2     key1    key2
0    0.363747    0.581347    A    One
1    0.982338    0.193684    A    Two
2    0.872498    0.377703    B    One
3    0.242360    0.946317    B    Two
4    0.976749    0.395238    D    Four

技术分享图片

 技术分享图片

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Python--DataFrame分组-GroupBy

原文:https://www.cnblogs.com/luowei93/p/11878639.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!