【问题标题】:How do I conditionally aggregate values in projection part of pandas query?如何在熊猫查询的投影部分有条件地聚合值?
【发布时间】:2019-12-10 13:22:38
【问题描述】:

我目前有一个包含以下内容的 csv 文件:

 ID PRODUCT_ID        NAME  STOCK  SELL_COUNT DELIVERED_BY
1         P1  PRODUCT_P1     12          15          UPS
2         P2  PRODUCT_P2      4           3          DHL
3         P3  PRODUCT_P3    120          22          DHL
4         P1  PRODUCT_P1    423          18          UPS
5         P2  PRODUCT_P2      0           5          GLS
6         P3  PRODUCT_P3     53          10          DHL
7         P4  PRODUCT_P4     22           0          UPS
8         P1  PRODUCT_P1     94          56          GLS
9         P1  PRODUCT_P1      9          24          GLS

当我执行这个 SQL 查询时:


    SELECT
      PRODUCT_ID,
      MIN(CASE WHEN DELIVERED_BY = 'UPS' THEN STOCK END) as STOCK,
      SUM(CASE WHEN ID > 6 THEN SELL_COUNT END) as TOTAL_SELL_COUNT,
      SUM(CASE WHEN SELL_COUNT * 100 > 1000 THEN SELL_COUNT END) as COND_SELL_COUNT
    FROM products
    GROUP BY PRODUCT_ID;

我得到了想要的结果:

PRODUCT_ID  STOCK   TOTAL_SELL_COUNT    COND_SELL_COUNT
P1          12      80                  113
P2          null    null                null
P3          null    null                22
P4          22      0                   null

现在我正在尝试使用 pandas 以某种方式在该数据集上获得相同的结果,这就是我正在努力解决的问题。

我将 csv 文件导入到名为 df_products 的数据帧中。 然后我尝试了这个:

def custom_aggregate(grouped):

    data = {
        'STOCK': np.where(grouped['DELIVERED_BY'] == 'UPS', grouped['STOCK'].min(), np.nan)  # [grouped['STOCK'].min() if grouped['DELIVERED_BY'] == 'UPS' else None]
    }

    d_series = pd.Series(data)
    return d_series


result = df_products.groupby('PRODUCT_ID').apply(custom_aggregate)
print(result)

如您所见,我离预期结果还很远,因为我已经在根据 DELIVERED_BY 值使条件 STOCK 聚合工作时遇到问题。

这个输出:

                           STOCK
PRODUCT_ID                      
P1          [9.0, 9.0, nan, nan]
P2                    [nan, nan]
P3                    [nan, nan]
P4                        [22.0]

这甚至不是正确的格式,但如果我能得到预期的 12.0 而不是 P1 的 9.0,我会很高兴。

谢谢


我只是想补充一点,我通过创建额外的列来接近结果:

df_products['COND_STOCK'] = df_products[df_products['DELIVERED_BY'] == 'UPS']['STOCK']
df_products['SELL_COUNT_ID_GT6'] = df_products[df_products['ID'] > 6]['SELL_COUNT']
df_products['SELL_COUNT_GT1000'] = df_products[(df_products['SELL_COUNT'] * 100) > 1000]['SELL_COUNT'] 

该函数将如下所示:

def custom_aggregate(grouped):

    data = {
        'STOCK': grouped['COND_STOCK'].min(),
        'TOTAL_SELL_COUNT': grouped['SELL_COUNT_ID_GT6'].sum(),
        'COND_SELL_COUNT': grouped['SELL_COUNT_GT1000'].sum(),
    }

    d_series = pd.Series(data)
    return d_series


result = df_products.groupby('PRODUCT_ID').apply(custom_aggregate)

这是“几乎”想要的结果:

            STOCK  TOTAL_SELL_COUNT  COND_SELL_COUNT
PRODUCT_ID                                          
P1           12.0              80.0            113.0
P2            NaN               0.0              0.0
P3            NaN               0.0             22.0
P4           22.0               0.0              0.0

【问题讨论】:

    标签: python-3.x pandas aggregate pandas-groupby case-when


    【解决方案1】:

    通常我们可以这样写pandas

    df.groupby('PRODUCT_ID').apply(lambda x : pd.Series({'STOCK':x.loc[x.DELIVERED_BY =='UPS','STOCK'].min(),
                                                     'TOTAL_SELL_COUNT': x.loc[x.ID>6,'SELL_COUNT'].sum(min_count=1),
                                                     'COND_SELL_COUNT':x.loc[x.SELL_COUNT>10,'SELL_COUNT'].sum(min_count=1)}))
    

    输出[105]:

                STOCK  TOTAL_SELL_COUNT  COND_SELL_COUNT
    PRODUCT_ID                                          
    P1           12.0              80.0            113.0
    P2            NaN               NaN              NaN
    P3            NaN               NaN             22.0
    P4           22.0               0.0              NaN
    

    【讨论】:

    • 哇!!!非常令人印象深刻。非常感谢。如果我省略 min_count 设置,我会得到零而不是 NaN。我想我会深入研究为什么会这样。你是我今天的英雄!! (实际上是一周的......)
    • @user2549803u yw:-) 快乐编码
    • 也许还有一个与此非常相关的问题:是否可以通过使用可能比 == 'UPS 或 > 6 进行更复杂检查的自定义 python 函数来扩展此示例?假设我有一个包含日期值的列,以及一个名为 is_in_current_year() 的函数,并且我需要对该函数返回 true 的所有行的卖出计数求和?不知道为这个问题创建一个新帖子是否会更好......
    猜你喜欢
    • 1970-01-01
    • 2015-01-03
    • 2022-11-28
    • 1970-01-01
    • 1970-01-01
    • 2017-01-14
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    相关资源
    最近更新 更多