You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas迭代分组DataFrame缩减数据时的信息丢失问题求解

问题描述

我们有一个包含销售数据的DataFrame,需要通过属性分组分析销售与属性的关联,但部分属性组合的数据量不足,得进行聚合。之前用了自底向上的聚合方式,却发现输出结果没法当自上而下的查询模型——因为聚合过程中丢了信息,比如查询[a,b,c,d]=[2,2,3,4]对应的sales值时会出现歧义,现在要找可行的解决思路或替代方案。

原始数据代码

import pandas as pd
df=pd.DataFrame({'a':[1,1,1,1, 2,2,2, 2,2], 
                 'b':[1,1,1,1, 2,2,2, 3,2], 
                 'c':[1,1,1,1, 3,3,3, 5,5],
                 'd':[2,2,2,2, 9,8,7, 4,3],
                 'sale':[0,1,1,1,0,1,1,1,2]
                })

现有聚合方案代码

thresh = 3
df['n_rows'] = 1
cols = ['a', 'b', 'c', 'd']
df['n_rows'] = 1
s = df.groupby(cols).agg(n_rows=('n_rows', 'sum'), 
                         sale=('sale', 'mean')).reset_index()
out = []
while cols and len(s):
    s = s.groupby(cols).agg(n_rows=('n_rows', 'sum'), 
                         sale=('sale', 'mean')).reset_index()
    m = s['n_rows']<thresh
    out.append(s.loc[~m, ])
    s = s[m]
    cols.pop()
out.append(s)

out = pd.concat([x.reset_index() for x in out])
out

可行解决思路

1. 保留聚合溯源信息

在聚合过程中记录每个聚合组对应的原始细分属性组合,这样查询时能明确知道当前聚合值包含哪些原始分组,从根源上避免歧义。

修改后的示例代码:

import pandas as pd

df = pd.DataFrame({'a':[1,1,1,1, 2,2,2, 2,2], 
                   'b':[1,1,1,1, 2,2,2, 3,2], 
                   'c':[1,1,1,1, 3,3,3, 5,5],
                   'd':[2,2,2,2, 9,8,7, 4,3],
                   'sale':[0,1,1,1,0,1,1,1,2]
                  })

thresh = 3
df['n_rows'] = 1
cols = ['a', 'b', 'c', 'd']
# 先获取最细粒度分组,同时存储原始属性组合
s = df.groupby(cols).agg(
    n_rows=('n_rows', 'sum'), 
    sale=('sale', 'mean'),
    included_groups=('a', lambda x: [tuple(x.index.values[0])])
).reset_index()

out = []
while cols and len(s):
    # 聚合时合并原始分组信息
    agg_s = s.groupby(cols).agg(
        n_rows=('n_rows', 'sum'), 
        sale=('sale', 'mean'),
        included_groups=('included_groups', lambda x: [item for sublist in x for item in sublist])
    ).reset_index()
    m = agg_s['n_rows'] < thresh
    out.append(agg_s.loc[~m, ])
    # 剔除最后一个属性,准备下一轮聚合
    s = agg_s[m].drop(cols[-1], axis=1)
    cols.pop()
out.append(s)

out = pd.concat([x.reset_index(drop=True) for x in out])
out

查询时,通过included_groups字段就能清楚看到当前聚合值对应的所有原始细分组合,不会再出现歧义。

2. 自上而下预生成查询模型

换个思路,从最粗粒度的分组(比如仅按a分组)开始,逐步向下细分。只有当细分后的分组数据量满足阈值时,才保留这个细分组;否则就沿用更粗粒度的聚合值。这种方式能确保每个查询路径都有明确、数据量达标的结果。

示例代码:

import pandas as pd

df = pd.DataFrame({'a':[1,1,1,1, 2,2,2, 2,2], 
                   'b':[1,1,1,1, 2,2,2, 3,2], 
                   'c':[1,1,1,1, 3,3,3, 5,5],
                   'd':[2,2,2,2, 9,8,7, 4,3],
                   'sale':[0,1,1,1,0,1,1,1,2]
                  })

thresh = 3
cols = ['a', 'b', 'c', 'd']
result = []

# 从最粗到最细遍历所有分组粒度
for i in range(len(cols), 0, -1):
    current_cols = cols[:i]
    # 计算当前粒度的分组统计
    group_stats = df.groupby(current_cols).agg(
        n_rows=('sale', 'count'),
        sale_mean=('sale', 'mean')
    ).reset_index()
    # 筛选数据量达标的组
    valid_groups = group_stats[group_stats['n_rows'] >= thresh]
    # 标记分组粒度,方便查询时优先匹配最细粒度
    valid_groups['group_level'] = i
    result.append(valid_groups)

# 合并结果,确保每个属性组合优先匹配最细的达标分组
final_result = pd.concat(result).sort_values('group_level', ascending=False).drop_duplicates(subset=cols, keep='first')
final_result

查询任意属性组合时,会优先匹配最细粒度的达标分组;如果没有匹配项,就自动向上找更粗的粒度,完全避免歧义问题。

3. 模糊匹配+权重分配(适合精度要求不高的场景)

如果不需要严格的精确聚合,可以给每个属性组合计算与各聚合组的相似度,再结合数据量权重分配销售值。不过这种方式只适合对精度要求较低的分析场景。


内容的提问来源于stack exchange,提问作者Helen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:42:52