【问题标题】:Python Pandas groupby: how to do conditional aggregation dependent on other columnPython Pandas groupby:如何根据其他列进行条件聚合
【发布时间】:2020-07-04 08:37:19
【问题描述】:

我想将 Panda 的 groupby 与多个聚合函数一起使用,但也包括每个聚合的条件语句。想象一下以这些数据为例:

df = pd.DataFrame({
    'id': ['a', 'a', 'a', 'b', 'b'],
    'type': ['in_scope', 'in_scope', 'exclude', 'in_scope', 'exclude'],
    'value': [5, 5, 99, 20, 99]
})
INPUT DATA:
| id | in_scope | value |
|----|----------|-------|
| a  | True     | 5     |
| a  | True     | 5     |
| a  | False    | 99    |
| b  | True     | 20    |
| b  | False    | 99    |

我想做一个 Pandas groupby 像这样:

df.groupby('id').agg(
    num_records=('id', 'size'),
    sum_value=('value', np.sum)
)
OUTPUT OF SIMPLE GROUPBY:
| id | num_records | sum_value |
|----|-------------|-----------|
| a  | 3           | 109       |
| b  | 2           | 119       |

但是,我想根据条件进行求和,即只应使用在列in_scope 中定义为True 的“in_scope”记录。注意,第一个聚合应该仍然使用整个表。简而言之,这是所需的输出:

DESIRED OUTPUT OF GROUPBY:
| id | num_records | sum_value_in_scope |
|----|-------------|--------------------|
| a  | 3           | 10                 |
| b  | 2           | 20                 |

我正在考虑将两个参数传递给 lambda 函数,但我没有成功。当然,它可以通过对过滤和未过滤的数据执行两个单独的 groupbys 并在之后将它们组合在一起来解决。但我希望有一种更短更优雅的方式。

【问题讨论】:

    标签: python filter conditional-statements aggregate pandas-groupby


    【解决方案1】:

    更新答案:仅当typein_scope 时创建一个包含值的临时列,然后聚合:

    (
        df.assign(temp=np.where(df["type"] == "in_scope", df["value"], None))
        .groupby("id", as_index=False)
        .agg(num_records=("type", "size"), sum_value=("temp", "sum"))
    )
        
    id   num_records    sum_value   
    a       3             10
    b       2             20
    

    【讨论】:

      【解决方案2】:

      很遗憾,您不能使用聚合来执行此操作,但是您可以使用应用和自定义函数一步完成:

      def f(x):
          d = {}
          d['num_records'] = len(x)
          d['sum_value_in_scope'] = x[x.in_scope].value.sum()
          return pd.Series(d, index=['num_records', 'sum_value_in_scope'])
      
      df.groupby('id').apply(f)
      

      由于df.in_scope 列已经是布尔值,您可以直接将其用作掩码来过滤求和的值。如果您正在使用的列不是布尔值,最好使用df.query('<your query here>') 来获取数据子集(引擎盖下的优化使其比大多数其他方法更快)。

      【讨论】:

      • 好方法,谢谢!关于query 方法,根据我的经验,只有在使用多个条件时才会更快。 I like the example given here,这似乎也符合我的经验。
      猜你喜欢
      • 2019-08-10
      • 2016-10-23
      • 2018-09-29
      • 2018-02-02
      • 1970-01-01
      • 1970-01-01
      • 2018-11-09
      • 2022-11-26
      • 2021-04-29
      相关资源
      最近更新 更多