【问题标题】:Way to use groupby over indices in pandas在熊猫中使用 groupby 索引的方法
【发布时间】:2022-01-11 01:40:09
【问题描述】:

[编辑以提供更好的工作示例数据]

想象一下,我在 pandas 中有一个面板,每个 id_var 有多个 time_vars。例如,假设数据包含一个状态变量和一个年份变量:

                   var1      var2
stcode year                      
WY     1996-01-01    14  0.000059
       1995-01-01     8  0.000059
       1994-01-01    21  0.000182
       1993-01-01    17  0.000063
       1992-01-01     9  0.000000
AK     1964-01-01    11  0.000213
       1965-01-01     6  0.000100
       1966-01-01    10  0.000189
       1967-01-01     9  0.000267
       1968-01-01     9  0.000084

有没有办法使用pd.groupby 并在多索引的year 级别上执行操作作为对象,还是我被限制在 groupby 变量中定义的列?

例如,假设我想检查日期是否已排序,但我只关心 year 级别是否已排序,而不关心 stcode 级别。我目前会这样实现:

# unsetting year from the index, so that I can groupby the remaining level and 
# check if year is monotonically increasing
df.reset_index('year').groupby('stcode').year.is_monotonic_increasing

这会返回(如您所见):

stcode
AK     True
WY    False
Name: year, dtype: bool

但是,以这种方式取消设置索引似乎非常低效。有没有一种通用的方法来做类似的事情:

df.groupby(level=0)[ -- the other level -- ].apply( -- operation -- )

类似地,相关地,有没有办法按第二级排序而忽略第一级?在这个例子中,我可能需要在每个 stcode 块中排序的时间变量来执行时间相关的操作,比如移位,但我不关心外部级别是按字母顺序还是数字顺序排序。换句话说,这最终会是:

                   var1      var2
stcode year                      
WY     1992-01-01     9  0.000000
       1993-01-01    17  0.000063
       1994-01-01    21  0.000182
       1995-01-01     8  0.000059
       1996-01-01    14  0.000059
AK     1964-01-01    11  0.000213
       1965-01-01     6  0.000100
       1966-01-01    10  0.000189
       1967-01-01     9  0.000267
       1968-01-01     9  0.000084

这是原始DataFrame的dict

{'var1': {('WY', Timestamp('1996-01-01 00:00:00')): 14,
  ('WY', Timestamp('1995-01-01 00:00:00')): 8,
  ('WY', Timestamp('1994-01-01 00:00:00')): 21,
  ('WY', Timestamp('1993-01-01 00:00:00')): 17,
  ('WY', Timestamp('1992-01-01 00:00:00')): 9,
  ('AK', Timestamp('1964-01-01 00:00:00')): 11,
  ('AK', Timestamp('1965-01-01 00:00:00')): 6,
  ('AK', Timestamp('1966-01-01 00:00:00')): 10,
  ('AK', Timestamp('1967-01-01 00:00:00')): 9,
  ('AK', Timestamp('1968-01-01 00:00:00')): 9},
 'var2': {('WY', Timestamp('1996-01-01 00:00:00')): 5.855486597283743e-05,
  ('WY', Timestamp('1995-01-01 00:00:00')): 5.91261159570422e-05,
  ('WY', Timestamp('1994-01-01 00:00:00')): 0.00018243736121803522,
  ('WY', Timestamp('1993-01-01 00:00:00')): 6.34477473795414e-05,
  ('WY', Timestamp('1992-01-01 00:00:00')): 0.0,
  ('AK', Timestamp('1964-01-01 00:00:00')): 0.0002131750516127795,
  ('AK', Timestamp('1965-01-01 00:00:00')): 0.00010040206689154729,
  ('AK', Timestamp('1966-01-01 00:00:00')): 0.0001891511055873707,
  ('AK', Timestamp('1967-01-01 00:00:00')): 0.00026726152282208204,
  ('AK', Timestamp('1968-01-01 00:00:00')): 8.391729352297261e-05}}

【问题讨论】:

    标签: python pandas pandas-groupby multi-index


    【解决方案1】:

    我个人认为您使用的方法干净合理。

    但是,您可以使用:

    df.groupby(level=0).apply(lambda g: g.index.is_monotonic_increasing)
    

    因为第一级必然是每组单调递增的。

    或者,如果需要(此处不需要),则真正放弃第一级:

    df.groupby(level=0).apply(lambda g: g.index.droplevel(0).is_monotonic_increasing)
    

    输出:

    AK     True
    WY    False
    dtype: bool
    

    只对第二层进行排序

    groupbygroup_keys=False, sort=False 一起使用:

    df.groupby(level=0, group_keys=False, sort=False).apply(lambda g: g.sort_index())
    

    输出:

                   var1      var2
    WY 1992-01-01     9  0.000000
       1993-01-01    17  0.000063
       1994-01-01    21  0.000182
       1995-01-01     8  0.000059
       1996-01-01    14  0.000059
    AK 1964-01-01    11  0.000213
       1965-01-01     6  0.000100
       1966-01-01    10  0.000189
       1967-01-01     9  0.000267
       1968-01-01     9  0.000084
    

    【讨论】:

    • 这按预期工作。我在测试中发现仅对第二级的排序比对整个多索引进行排序要慢,这很遗憾,因为理论上这应该更快,因为您可以固定外部组并在内部组中进行排序(即使是并行,最佳)。然而,很明显 sort_index() 的优化超出了这个 groupby 的能力。
    猜你喜欢
    • 2020-06-30
    • 1970-01-01
    • 2021-02-12
    • 2018-08-01
    • 2019-09-18
    • 1970-01-01
    • 2015-11-23
    • 2019-02-28
    • 1970-01-01
    相关资源
    最近更新 更多