PHP速学视频免费教程(入门到精通)
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
在数据分析中,我们经常需要根据一个或多个变量对数据进行分组并计算组的大小。然而,有时业务逻辑要求我们对分组行为进行更精细的控制:如果某个分组的成员数量过少(例如,低于某个预设阈值),我们就不希望继续在该分组内进行更细粒度的划分,而是将其视为一个整体,将其统计结果向上汇总到其父级分组中。对于那些成员数量足够大的分组,我们则希望继续按照所有指定的分组键进行细致的划分。
考虑以下示例数据集:
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] }) print("原始数据框:") print(df)
我们的目标是根据列 a, b, c 进行分组。假设阈值为3。
期望的输出结果如下,其中 NaN 表示在该层级不再进行细分:
a b c group_size 0 1 1 1.0 3 1 1 1 2.0 3 2 1 2 NaN 3 3 2 2 2.0 9
Pandas的 groupby() 函数通常会将数据一直分组到所有指定键的最细粒度。例如,df.groupby(['a', 'b', 'c']).size() 会直接计算每个 (a, b, c) 组合的行数,这无法实现动态停止分组的需求。如果一个 (a, b, c) 组合的行数很少,我们无法在计算时自动将其向上合并到 (a, b) 层面。
解决这种动态分组问题的核心思想是采用迭代式的向上聚合方法。其基本流程如下:
这种方法避免了复杂的条件判断和多次数据框合并操作,利用了Pandas groupby 在多级索引上的灵活性。
下面是实现上述策略的详细步骤和代码:
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 # 设定阈值 # 1. 初始化:获取最细粒度计数 # df.value_counts() 比 df.groupby(list(df)).size() 更高效,尤其在数据量大时 s = df.value_counts() print("\n初始最细粒度计数 (value_counts()):") print(s) out = [] # 用于存储最终符合阈值的分组结果 cols = list(df.columns) # 初始分组键列表:['a', 'b', 'c'] # 2. 迭代处理:逐层向上合并 while cols and len(s): # 根据当前 cols 进行分组并求和(s 已经是计数,这里是聚合计数) # level=cols 表示按多级索引的指定层级进行分组 s = s.groupby(level=cols).sum() print(f"\n当前分组键: {cols}, 聚合结果:\n{s}") # 找出行数低于阈值的组 (m) m = s < thresh print(f"低于阈值 ({thresh}) 的组:\n{s[m]}") # 将符合阈值的组(非 m)添加到结果列表 out # s[~m] 是那些计数 >= thresh 的组 out.append(s[~m]) print(f"符合阈值的组(已提取):\n{s[~m]}") # 更新 s,只保留低于阈值的组,供下一轮迭代处理(向上合并) s = s[m] print(f"待下一轮处理的组(低于阈值):\n{s}") # 移除最右边的分组键,准备进行更粗粒度的分组 if cols: # 避免列表为空时pop()报错 cols.pop() print(f"移除最右侧键后,剩余分组键: {cols}") # 循环结束后,如果 s 中还有剩余的组(即所有键都移除后仍有组),则将其添加到结果中 # 这通常发生在即使只按第一个键分组,其计数仍低于阈值的情况下 if len(s): out.append(s) # 3. 结果整合与格式化 # 将所有结果 Series 转换为 DataFrame 并重置索引 # reset_index() 会将多级索引转换为列 out_df = pd.concat([x.reset_index() for x in out]) # 默认的计数列名为 'count',可以根据需要重命名 out_df = out_df.rename(columns={'count': 'group_size'}) # 排序以便于查看,并处理 NaN out_df = out_df.sort_values(by=list(df.columns)).reset_index(drop=True) print("\n最终结果:") print(out_df)
代码解析:
本教程介绍了一种在Pandas中实现动态阈值条件分组的有效策略。通过迭代地从最细粒度向上聚合,并根据预设阈值分离已完成的分组和待处理的分组,我们能够优雅地解决常规 groupby 无法满足的复杂场景。这种方法不仅逻辑清晰,而且在性能上具有优势,是处理此类条件分组问题的推荐方案。
已抢7561个
抢已抢97277个
抢已抢15245个
抢已抢53878个
抢已抢198177个
抢已抢88289个
抢