如何在Pandas的value_counts中设置容差实现分组统计?
问题描述
现有如下数据集,使用Pandas的value_counts()方法统计时会得到精确值的计数结果:
import pandas as pd df = pd.DataFrame( [5.01, 5.01, 5.08, 6.1, 5.54, 6.3, 5.56, 5.55, 6.7], columns=['val'] )
执行df.val.value_counts()后会得到每个精确值的出现次数,但希望设置±0.01的容差,将5.54、5.55、5.56这类相近数值归为一组统计,期望输出类似:
[5.54,5.56,5.55] 3 [5.01] 2 [5.08] 1 [6.10] 1 ...
解决方案
方法一:基于层次聚类分组
可以用scipy的层次聚类,将差值≤0.02的数值归为同一组(因为±0.01的容差意味着组内任意两个数的最大差值为0.02):
import pandas as pd from scipy.cluster.hierarchy import linkage, fcluster df = pd.DataFrame( [5.01, 5.01, 5.08, 6.1, 5.54, 6.3, 5.56, 5.55, 6.7], columns=['val'] ) # 生成聚类链接矩阵,采用单链接(最小距离)方法 Z = linkage(df[['val']], method='single', metric='euclidean') # 设置距离阈值为0.02,划分聚类 df['cluster'] = fcluster(Z, t=0.02, criterion='distance') # 按聚类分组,收集每组的唯一值并统计总数量 result = df.groupby('cluster')['val'].agg( values=lambda x: list(x.unique()), count='size' ) # 输出指定格式的结果 for _, row in result.iterrows(): print(f"{row['values']} {row['count']}")
运行后输出:
[5.01] 2 [5.08] 1 [5.54, 5.56, 5.55] 3 [6.1] 1 [6.3] 1 [6.7] 1
方法二:手动遍历分组
如果不想依赖第三方库,可以手动遍历去重后的数值,将符合容差范围的数值归为一组:
import pandas as pd df = pd.DataFrame( [5.01, 5.01, 5.08, 6.1, 5.54, 6.3, 5.56, 5.55, 6.7], columns=['val'] ) # 对唯一值进行排序 unique_vals = sorted(df['val'].unique()) groups = [] current_group = [unique_vals[0]] for val in unique_vals[1:]: # 判断当前值与组内最小值的差值是否≤0.02(对应±0.01的容差) if val - current_group[0] <= 0.02: current_group.append(val) else: groups.append(current_group) current_group = [val] groups.append(current_group) # 统计每组的总出现次数并输出 for group in groups: count = df[df['val'].isin(group)].shape[0] print(f"{group} {count}")
输出结果与方法一完全一致。
内容的提问来源于stack exchange,提问作者Sun Jar
相关产品推荐
相关产品推荐

