
在数据分析中,我们经常需要对dataframe进行多级分组聚合。然而,有时我们希望这种分组行为是条件性的:如果某个分组的行数过少(低于某个预设阈值),我们就不再对该分组进行更细粒度的拆分,而是将其作为当前层级的最终聚合结果。对于行数足够多的分组,则继续进行下一级的分组。
考虑以下示例DataFrame:
import pandas as pd
import numpy as np
df = pd.DataFrame({'a': [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2],
'b': [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
'c': [1, 1, 1, 2, 2, 2, 3, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2]
})我们希望按照 ['a', 'b', 'c'] 的顺序进行分组。如果某个分组的行数小于等于阈值(例如,n_threshold = 3),则停止对该分组进行后续列的更细粒度分组。例如,对于 a=1, b=1, c=1,其计数为3,达到阈值,因此停止分组,将其作为最终结果。而 a=1, b=2 整体计数为3,也应停止在 c 列上继续分组,其 c 列应显示为 NaN。最终期望的输出结果如下:
a b c count 0 1 1 1.0 3 1 1 1 2.0 3 2 2 2 2.0 9 0 1 2 NaN 3
解决此问题的核心在于采用一种迭代的、自底向上的聚合策略。我们从最细粒度的分组开始(即所有分组列),然后逐步向上(减少分组列),在每一步中检查当前分组的大小。
下面是具体的实现代码及其详细解释:
import pandas as pd
import numpy as np
# 示例数据
df = pd.DataFrame({'a': [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2],
'b': [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
'c': [1, 1, 1, 2, 2, 2, 3, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2]
})
thresh = 3 # 设定阈值
# 获取所有列名,作为初始分组列
cols = list(df.columns)
# 使用 value_counts() 进行初始最细粒度计数,结果是一个MultiIndex Series
s = df.value_counts()
out = [] # 用于存储符合条件的最终分组结果
# 循环处理,直到所有列都被移除或所有组都被处理完毕
while cols and len(s):
# 根据当前 cols 中的列进行聚合求和。
# 对于 MultiIndex Series,groupby(level=cols).sum() 会根据指定的层级重新聚合。
s = s.groupby(level=cols).sum()
# 找出计数低于或等于阈值的组
m = s < thresh
# 将计数大于阈值的组(即 ~m)添加到结果列表 out 中
# 这些组将不再进行更粗粒度的聚合,因为它们已经满足了当前层级的条件
out.append(s[~m])
# 将计数低于阈值的组(即 m)保留,它们需要在下一轮进行更粗粒度的聚合
s = s[m]
# 移除最右侧的列,以便在下一轮迭代中进行更粗粒度的聚合
if cols: # 确保列表不为空,避免pop()错误
cols.pop()
# 循环结束后,如果 s 中还有剩余的组(即在最粗粒度分组时也低于阈值的组),
# 将它们添加到结果列表 out 中。例如,如果只有一列'a',且'a'的某个值计数也低于阈值。
if len(s):
out.append(s)
# 将 out 列表中的所有 Series 转换为 DataFrame 并合并
# reset_index() 将 MultiIndex 转换为普通列
out_df = pd.concat([x.reset_index() for x in out])
# 对结果进行排序,使其更具可读性(可选)
out_df = out_df.sort_values(by=list(out_df.columns[:-1]), na_position='last').reset_index(drop=True)
print(out_df)执行上述代码,将得到以下输出:
a b c count 0 1 1 1.0 3 1 1 1 2.0 3 2 1 2 NaN 3 3 2 2 2.0 9
结果解读:
通过上述迭代聚合与筛选的策略,我们能够优雅地在Pandas中实现基于阈值的条件式分层分组,大大提高了数据处理的效率和灵活性。
以上就是Pandas条件式分层分组:基于阈值动态停止聚合的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号