<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Pandas知識點-詳解分組函數groupby

          共 10526字,需瀏覽 22分鐘

           ·

          2022-07-23 14:14

          在數據分析時,經常需要將數據分成不同的群組,pandas中的groupby()函數可以完美地完成各種分組操作。


          分組是根據DataFrame/Series的某個字段值,將該字段的值相等的行/列分到同一組中,每一個小組是一個新的DataFrame或Series。


          groupby()也可以按DataFrame中的多個字段分組,當多個字段的值都相等時分到同一組。


          groupby()經常與批處理函數apply()、聚合函數agg()等配合使用,實現對數據的多元處理。


          groupby用法和參數介紹


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


          •  by: 指定根據哪個/哪些字段分組,默認值是None,按多個字段分組時傳入列表。by參數可以按位置參數的方式傳入。

          • axis: 設置按列分組還是按行分組,0或index表示按列分組,1或columns表示按行分組,默認值為0。

          • level: 當DataFrame的索引為多重索引時,level參數指定用于分組的索引,可以傳入多重索引中索引的下標(0,1...)或索引名,多個用列表傳入。


          level參數不能與by參數同時使用,如果兩者同時存在,當by參數傳入的是多重索引中的索引,則level不生效,當by參數傳入的是DataFrame的列名,則報錯。

          • as_index: 分組結果默認將分組列的值作為索引,如果按單列分組,結果默認是單索引,如果按多列分組,結果默認是多重索引。將as_index設置為False可以重置索引(0,1...)。


          • sort: 結果按分組列的值升序排列,將sort設置為False則不排序,可以提升性能。


          • dropna: 默認情況下,分組列的NaN在分組結果中不保留,將dropna設置為False,可以保留NaN分組。


          其他三個參數不用關注,group_keys參數在源碼中未使用,squeeze參數因為類型不兼容,官方已棄用,observed參數表示重設索引時,保留創(chuàng)建的全NaN行。


          分組對象的內部結構


          # coding=utf-8
          import pandas as pd
          import numpy as np

          vip_df = pd.DataFrame(
              {'isVip': ['vip''svip''member''vip''member''vip''svip'],
               'gender': ['male''female''female''female''male''female''male'],
               'age': [25304025401830],
               'vipLevel': ['LV2''LV5', np.nan, 'LV3''LV2''LV2''LV3'],
               'growValue': [180425, np.nan, 288190110240]}
          )
          print(vip_df)
          grouped = vip_df.groupby('isVip')
          print(grouped)
              isVip  gender  age vipLevel  growValue
          0 vip male 25 LV2 180.0
          1 svip female 30 LV5 425.0
          2 member female 40 NaN NaN
          3 vip female 25 LV3 288.0
          4 member male 40 LV2 190.0
          5 vip female 18 LV2 110.0
          6 svip male 30 LV3 240.0
          <pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001C3E81D1370>


          groupby()分組得到的是一個DataFrameGroupBy對象,直接打印DataFrameGroupBy對象只能看到它的內存地址,看不到內部的結構。


          for name, group in grouped:
              print(name)
              print(group)
          member
          isVip gender age vipLevel growValue
          2 member female 40 NaN NaN
          4 member male 40 LV2 190.0
          svip
          isVip gender age vipLevel growValue
          1 svip female 30 LV5 425.0
          6 svip male 30 LV3 240.0
          vip
          isVip gender age vipLevel growValue
          0 vip male 25 LV2 180.0
          3 vip female 25 LV3 288.0
          5 vip female 18 LV2 110.0


          for group in grouped:
              print(group)
              print(type(group), type(group[0]), type(group[1]))
          ('member',     isVip  gender  age vipLevel  growValue
          2 member female 40 NaN NaN
          4 member male 40 LV2 190.0)
          <class 'tuple'> <class 'str'> <class 'pandas.core.frame.DataFrame'>
          ('svip', isVip gender age vipLevel growValue
          1 svip female 30 LV5 425.0
          6 svip male 30 LV3 240.0)
          <class 'tuple'> <class 'str'> <class 'pandas.core.frame.DataFrame'>
          ('vip', isVip gender age vipLevel growValue
          0 vip male 25 LV2 180.0
          3 vip female 25 LV3 288.0
          5 vip female 18 LV2 110.0)
          <class 'tuple'> <class 'str'> <class 'pandas.core.frame.DataFrame'>


          DataFrameGroupBy是一個可迭代對象,可以轉換成list打印,也可以直接遍歷打印出來。遍歷出來的是一個個元組,每個元組對應一個分組,元組的第一個元素與分組列里的值對應,元組的第二個元素是分到當前小組的數據,是一個DataFrame。


          DataFrameGroupBy對象的內部結構為:[(分組名1, 子DataFrame1),  (分組名2, 子DataFrame2), ...],相當于groupby()將DataFrame按字段值分成了多個小的DataFrame,然后將字段值和小的DataFrame用元組的方式保存在DataFrameGroupBy對象中。


          print(grouped.groups)
          group_name = [gn for gn in grouped.groups.keys()]
          print(group_name)
          group = grouped.get_group(group_name[2])
          print('-'*40'\n', group, sep='')
          {'member': [2, 4], 'svip': [1, 6], 'vip': [0, 3, 5]}
          ['member', 'svip', 'vip']
          ----------------------------------------
          isVip gender age vipLevel growValue
          0 vip male 25 LV2 180.0
          3 vip female 25 LV3 288.0
          5 vip female 18 LV2 110.0


          分組對象的groups屬性可以返回分組信息,結果是一個形似字典的對象,由分組名和此分組數據在原DataFrame中的行索引組成。


          借用groups可以提取出所有分組的分組名,分組對象的get_group()方法可以返回指定分組名的子DataFrame。


          按多重索引分組


          vip_multi_df = vip_df.set_index(['isVip''gender'])
          print('-'*40'\n', vip_multi_df, sep='')
          ----------------------------------------
          age vipLevel growValue
          isVip gender
          vip male 25 LV2 180.0
          svip female 30 LV5 425.0
          member female 40 NaN NaN
          vip female 25 LV3 288.0
          member male 40 LV2 190.0
          vip female 18 LV2 110.0
          svip male 30 LV3 240.0


          # 按多重索引中的指定索引進行分組
          grouped = vip_multi_df.groupby(level='isVip')
          print('-'*40'\n', grouped.mean(), sep='')
          # 按多重索引中除指定索引之外的索引分組
          grouped = vip_multi_df.groupby(level=vip_multi_df.index.names.difference(['gender']))
          print('-'*40'\n', grouped.mean(), sep='')
          # 按多重索引中的多個索引分組
          grouped = vip_multi_df.groupby(level=[01])
          print('-'*40'\n', grouped.mean(), sep='')
          ----------------------------------------
          age growValue
          isVip
          member 40.000000 190.000000
          svip 30.000000 332.500000
          vip 22.666667 192.666667
          ----------------------------------------
          age growValue
          isVip
          member 40.000000 190.000000
          svip 30.000000 332.500000
          vip 22.666667 192.666667
          ----------------------------------------
          age growValue
          isVip gender
          member female 40.0 NaN
          male 40.0 190.0
          svip female 30.0 425.0
          male 30.0 240.0
          vip female 21.5 199.0
          male 25.0 180.0


          level參數用于設置按多重索引中的指定索引分組,level傳入的方式可以是索引name,也可以是索引在多重索引中的下標,還可以是排除某個索引外的其他索引。指定多個時用列表的方式傳入。


          grouped = vip_multi_df.groupby('gender')
          print('-'*40'\n', grouped.mean(), sep='')
          grouped = vip_multi_df.groupby(['gender''age'])
          print('-'*40'\n', grouped.mean(), sep='')
          ----------------------------------------
          age growValue
          gender
          female 28.250000 274.333333
          male 31.666667 203.333333
          ----------------------------------------
          growValue
          gender age
          female 18 110.0
          25 288.0
          30 425.0
          40 NaN
          male 25 180.0
          30 240.0
          40 190.0


          多重索引中的索引也可以傳給groupby()的by參數,分組結果與將多重索引作為DataFrame的列是一樣的。


          如果用DataFrame的列作為分組列,多重索引會被轉換成列保留在結果中。也可以用多重索引中的索引與列一起組合分組,相當于先對DataFrame重設索引再分組。


          重置結果的索引


          grouped = vip_multi_df.groupby(['isVip''gender'])
          print('-'*40'\n', grouped.mean(), sep='')
          # 重設索引
          grouped = vip_multi_df.groupby(['isVip''gender'], as_index=False)
          print('-'*40'\n', grouped.mean(), sep='')
          ----------------------------------------
          age growValue
          isVip gender
          member female 40.0 NaN
          male 40.0 190.0
          svip female 30.0 425.0
          male 30.0 240.0
          vip female 21.5 199.0
          male 25.0 180.0
          ----------------------------------------
          age growValue
          0 40.0 NaN
          1 40.0 190.0
          2 30.0 425.0
          3 30.0 240.0
          4 21.5 199.0
          5 25.0 180.0


          分組結果的索引默認是分組列的值,將as_index設置為False可以重置索引,相當于先分組再調用reset_index()函數。


          結果是否排序


          grouped = vip_df.groupby('isVip')
          print('-'*40'\n', grouped.mean(), sep='')
          grouped = vip_df.groupby('isVip', sort=False)
          print('-'*40'\n', grouped.mean(), sep='')
          ----------------------------------------
          age growValue
          isVip
          member 40.000000 190.000000
          svip 30.000000 332.500000
          vip 22.666667 192.666667
          ----------------------------------------
          age growValue
          isVip
          vip 22.666667 192.666667
          svip 30.000000 332.500000
          member 40.000000 190.000000


          groupby()默認對結果按分組列的值升序排列,如果將sort參數修改為False,則不排序,保留原DataFrame中的順序,不排序可以提升性能。


          是否保留空值


          grouped = vip_df.groupby('vipLevel')
          print('-'*40'\n', grouped.mean(), sep='')
          grouped = vip_df.groupby('vipLevel', dropna=False)
          print('-'*40'\n', grouped.mean(), sep='')
          ----------------------------------------
          age growValue
          vipLevel
          LV2 27.666667 160.0
          LV3 27.500000 264.0
          LV5 30.000000 425.0
          ----------------------------------------
          age growValue
          vipLevel
          LV2 27.666667 160.0
          LV3 27.500000 264.0
          LV5 30.000000 425.0
          NaN 40.000000 NaN


          當分組列有空值(NaN)時,默認的分組結果中不保留NaN分組,將dropna參數修改為False,正常保留NaN分組。


          提取分組結果的指定列


          grouped = vip_df.groupby('isVip', dropna=False)
          print('-'*40'\n', grouped['gender'], sep='')
          for name, group in grouped['gender']:
              print(name)
              print(group)
          ----------------------------------------
          <pandas.core.groupby.generic.SeriesGroupBy object at 0x00000285CA1B0790>
          member
          2 female
          4 male
          Name: gender, dtype: object
          svip
          1 female
          6 male
          Name: gender, dtype: object
          vip
          0 male
          3 female
          5 female
          Name: gender, dtype: object


          從groupby()分組結果中取一列,得到的是一個SeriesGroupBy對象,直接打印SeriesGroupBy對象只能看到它的內存地址,看不到內部的結構。


          SeriesGroupBy的內部結構與DataFrameGroupBy相似,SeriesGroupBy對象的內部結構為:[(分組名1, 子Series1),  (分組名2, 子Series2), ...],因此SeriesGroupBy也可以轉換成list打印,也可以遍歷取出每一個元素。


          grouped = vip_df['gender'].groupby(vip_df['isVip'])
          for name, group in grouped:
              print(name)
              print(group)
          member
          2 female
          4 male
          Name: gender, dtype: object
          svip
          1 female
          6 male
          Name: gender, dtype: object
          vip
          0 male
          3 female
          5 female
          Name: gender, dtype: object


          也可以先指定需要獲取的列,再按DataFrame的另一個列進行分組,結果與先分組再獲取指定列相同。


          以上就是pandas中groupby()函數的用法介紹和分析,本文都是用DataFrame舉例,Series的用法相似,不重復了。


          如果本文的內容對你有幫助,歡迎點贊、在看、收藏,也可以關注和聯系我一起交流討論。


          參考文檔: 

          [1] pandas中文網:https://www.pypandas.cn/docs/

          瀏覽 72
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操逼综合网站 | 少妇白洁在线播放 | 欧美一级片在线电影 | 吖v在线观看 | 日韩mv欧美mv国产网址 |