zoukankan      html  css  js  c++  java
  • Pandas分组

    分组

    一.分组模式及其对象

    分组的一般模式

    df.groupby(分组依据)[数据来源].使用操作
    

    来看下面这列代码:

    df = pd.read_csv('data/learn_pandas.csv')
    df.groupby('Gender')['Height'].median()
    

    根据df.groupby(分组依据)[数据来源].使用操作可以很好的理解这段代码。

    通过性别来统计身高的中位数。

    二.分组依据的本质
    上面的分组依据仅仅是单个,但如果需要面对多个分组依据的时候,仅仅需要再group by中传入相应列名构成的列表即可。

    看这个例子:

     df.groupby(['School', 'Gender'])['Height'].mean()
    

    通过学校和性别来统计身高的平均数。
    但是如果我们想要有选择性的(自定义)分组依据时,我们可以先写出分组条件,

    condition = df.Weight > df.Weight.mean()
    

    然后将分组条件传入group by中。

    df.groupby(condition)['Height'].mean()
    

    表示通过自定义的分组条件去统计身高的平均数。

    group by对象
    通过上面的代码,我们发现分组是使用Pandas中的group by对象进行操作,group by对象上定义了很多方法,也提供了一些方便的属性。

    gb = df.groupby(['School', 'Grade'])
    gb
    

    通过ngroups属性,可以得到分组个数。

    gb.ngroups
    

    通过groups属性,可以返回从组名映射到组索引列表的字典

    res = gb.groups
    res.keys()
    

    通过 get_group 方法可以直接获取所在组对应的行
    当 size 作为 DataFrame 的属性时,返回的是表长乘以表宽的大小。

    分组三大操作
    分组的三大操作:聚合、变换和过滤

    聚合函数

    一.内置聚合函数
    一些直接定义再group by对象中的聚合函数,因为它们的速度都经过内部的优化,建议优先考虑
    max/min/mean/median/count/all/any/idxmax/idxmin/mad/nunique/skew/quantile/sum/std/var/sem/size/prod
    当这些聚合函数传入的数据来源包含多个列时,将按照列进行迭代计算

    gb = df.groupby('Gender')[['Height', 'Weight']]
    gb.max()
    

    agg方法
    尽管group by对象中定义了很多简便的函数,但是仍有一些不足:

    • 无法同时使用多个函数
    • 无法对特定的列使用特定的聚合函数
    • 无法使用自定义的聚合函数
    • 无法直接对结果的列名在聚合前进行自定义命名
      所以agg方法的诞生用来解决这些问题。
    1. 使用多个函数
      当使用多个聚合函数时,把需要使用的内置聚合函数以列表的形式写成字符串传入
    gb.agg(['sum', 'idxmax', 'skew'])
    
    1. 对特定的列使用特定的聚合函数
      对于方法和列的特殊对应,可以通过构造字典传入 agg 中实现,其中字典以列名为键,以聚合字符串或字符串列表为值。
    gb.agg({'Height':['mean','max'], 'Weight':'count'})
    
    1. 使用自定义函数
      如果要使用自定义函数,需要注意传入函数的参数是之前数据源中的列,逐列进行计算
    gb.agg(lambda x: x.mean()-x.min())
    

    表示分组计算身高和体重的极差。
    4. 聚合结果重命名
    如果想要对聚合结果的列名进行重命名,只需要将上述函数的位置改写成元组,元组的第一个元素为新的名字,第二个位置为原来的函数,包括聚合字符串和自定义函数。

    gb.agg([('range', lambda x: x.max()-x.min()), ('my_sum', 'sum')])
    

    另外需要注意,使用对一个或者多个列使用单个聚合的时候,重命名需要加方括号,否则就不知道是新的名字还是手误输错的内置函数字符串.

    变换和过滤

    一. 变换函数和transform方法
    变换函数的返回值为同长度的序列,常用的内置变换函数是累计函数:
    cumcount/cumsum/cumprod/cummax/cummin,使用操作与聚合函数类似,不过结果仅仅是组内的累计操作。

    gb.cummax().head()
    

    如果需要自定义变换函数就要使用transfrom方法,被调用的自定义函数,其传入值为数据源的序列,与agg的传入类型是一致的,其最后的返回结果是行列索引与数据源一致的DataFrame 。
    对身高和体重进行分组标准化,减去组均值后除以组的标准差:

    gb.transform(lambda x: (x-x.mean())/x.std()).head()
    

    二.组索引和过滤
    索引和过滤的区别:
    groupby对象中定义了 filter 方法进行组的筛选,其中自定义函数的输入参数为数据源构成的DataFrame本身.
    通过过滤得到表中容量大于100的组:

    gb.filter(lambda x: x.shape[0] > 100).head()
    

    跨列分组

    1.apply的引入
    事实上还有一种常见的分组场景,无法用前面介绍的任何一种方法处理,例如现在如下定义身体质量指数BMI:

    其中体重和身高的单位分别为千克和米,需要分组计算组BMI的均值。
    首先,这显然不是过滤操作,因此 filter 不符合要求;其次,返回的均值是标量而不是序列,因此 transform 不符合要求;最后,似乎使用 agg 函数能够处理,但是之前强调过聚合函数是逐列处理的,而不能够 多列数据同时处理 。由此,引出了 apply 函数来解决这一问题。
    apply的使用
    apply 的自定义函数传入参数与 filter 完全一致,不过filter允许返回布尔值。
    除了返回标量之外, apply 方法还可以返回一维 Series 和二维 DataFrame
    但它们产生的数据框维数和多级索引的层数应当如何变化?下面举三组例子理解:

    1. 标量情况:结果得到的是 Series ,索引与 agg 的结果一致
    gb = df.groupby(['Gender','Test_Number'])[['Height','Weight']]
    gb.apply(lambda x: 0)
    gb.apply(lambda x: [0, 0]) # 虽然是列表,但是作为返回值仍然看作标量
    

    2.Series 情况:得到的是 DataFrame ,行索引与标量情况一致,列索引为 Series 的索引

    gb.apply(lambda x: pd.Series([0,0],index=['a','b']))
    
    1. DataFrame 情况:得到的是 DataFrame ,行索引最内层在每个组原先 agg 的结果索引上,再加一层返回的 DataFrame 行索引,同时分组结果 DataFrame 的列索引和返回的 DataFrame 列索引一致。
    gb.apply(lambda x: pd.DataFrame(np.ones((2,2)),
                                        index = ['a','b'],
                                        columns=pd.Index([('w','x'),('y','z')])))
    
  • 相关阅读:
    gitlab使用
    小程序顶部导航栏标题不居中
    mpvue中使用vant-weapp
    原生js实现轮播图
    vue无法检测数组的变动
    vue报错TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function
    vue绑定style使用需要添加浏览器引擎前缀的 CSS 属性
    《孙子算经》之"物不知数"题:中国剩余定理
    Java大数处理类:BigInteger类和BigDecimal类
    【转】操作系统典型调度算法
  • 原文地址:https://www.cnblogs.com/wenqihe/p/14190450.html
Copyright © 2011-2022 走看看