【问题标题】:How to do a 'groupby' by multilevel index in Pandas如何在 Pandas 中通过多级索引执行“groupby”
【发布时间】:2012-08-24 19:37:39
【问题描述】:

我有一个由 (STK_ID,RPT_Date) 索引的数据框“RPT”,其中包含每个季度的股票累计销售额:

                       sales
STK_ID  RPT_Date
000876  20060331      798627000
        20060630     1656110000
        20060930     2719700000
        20061231     3573660000
        20070331      878415000
        20070630     2024660000
        20070930     3352630000
        20071231     4791770000
600141  20060331      270912000
        20060630      658981000
        20060930     1010270000
        20061231     1591500000
        20070331      319602000
        20070630      790670000
        20070930     1250530000
        20071231     1711240000

我想用'groupby' by STK_ID & RPT_Yr 计算单季销售额,如:RPT.groupby('STK_ID','RPT_Yr')['sales'].transform(lambda x: x-x.shift(1)),怎么做?

假设我可以通过lambda x : datetime.strptime(x, '%Y%m%d').year 得到年份

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    这里假设 RPT_Data 是一个字符串,有什么理由不使用 Datetime?

    可以使用函数进行分组,但只能在非 MultiIndex 索引上。通过重置索引来解决此问题,并将“RPT_Date”设置为索引以提取年份(注意:pandas 在 object 和 int 之间切换为“RPT_Date”的 dtype)。

    In [135]: year = lambda x : datetime.strptime(str(x), '%Y%m%d').year
    
    In [136]: grouped = RPT.reset_index().set_index('RPT_Date').groupby(['STK_ID', year])
    
    In [137]: for key, df in grouped:
       .....:     print key
       .....:     print df
       .....:
    (876, 2006)
              STK_ID       sales
    RPT_Date
    20060331     876   798627000
    20060630     876  1656110000
    20060930     876  2719700000
    20061231     876  3573660000
    (876, 2007)
              STK_ID       sales
    RPT_Date
    20070331     876   878415000
    20070630     876  2024660000
    20070930     876  3352630000
    20071231     876  4791770000
    (600141, 2006)
              STK_ID       sales
    RPT_Date
    20060331  600141   270912000
    20060630  600141   658981000
    20060930  600141  1010270000
    20061231  600141  1591500000
    (600141, 2007)
              STK_ID       sales
    RPT_Date
    20070331  600141   319602000
    20070630  600141   790670000
    20070930  600141  1250530000
    20071231  600141  1711240000
    

    其他选项是使用 tmp 列

    In [153]: RPT_tmp = RPT.reset_index()
    
    In [154]: RPT_tmp['year'] = RPT_tmp['RPT_Date'].apply(year)
    
    In [155]: grouped = RPT_tmp.groupby(['STK_ID', 'year'])
    

    编辑 重新组织你的框架会更容易。

    In [48]: RPT
    Out[48]: 
                                      sales
    STK_ID RPT_Year RPT_Quarter            
    876    2006     0             798627000
                    1            1656110000
                    2            2719700000
                    3            3573660000
           2007     0             878415000
                    1            2024660000
                    2            3352630000
                    3            4791770000
    600141 2006     0             270912000
                    1             658981000
                    2            1010270000
                    3            1591500000
           2007     0             319602000
                    1             790670000
                    2            1250530000
                    3            1711240000
    
    In [49]: RPT.groupby(level=['STK_ID', 'RPT_Year'])['sales'].apply(sale_per_q)
    Out[49]: 
    STK_ID  RPT_Year  RPT_Quarter
    876     2006      0               798627000
                      1               857483000
                      2              1063590000
                      3               853960000
            2007      0               878415000
                      1              1146245000
                      2              1327970000
                      3              1439140000
    600141  2006      0               270912000
                      1               388069000
                      2               351289000
                      3               581230000
            2007      0               319602000
                      1               471068000
                      2               459860000
                      3               460710000
    

    【讨论】:

    • 这很棘手,代码很丑陋。是否有任何 pythonic 或 pandasnic 方式这样做?
    • def sale_per_q(s): sq = s.diff() sq[s.index[0]] = s.iget(0) return sq
    【解决方案2】:

    试试

    RPT['sales'].groupby([RPT['STK_ID'],RPT['RPT_Yr']]).sum()
    

    ^^ 您需要引用列表中的索引。这对我有用

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-05
      • 1970-01-01
      • 2019-10-27
      • 1970-01-01
      • 2018-04-17
      • 2022-07-19
      • 2018-12-09
      • 2020-12-17
      相关资源
      最近更新 更多