Pandas:如何分组阈值内近似值并替换为聚合值
如何对阈值范围内的近似数值分组并替换为聚合值
我来给你捋捋怎么搞定这个需求哈,看你的示例数据,核心就是把差值在设定阈值内的近似数值归为一组,然后用聚合值(比如最小值、均值这类)替换掉原数值。我用Python的pandas给你演示两种常用方法,都能完美匹配你的示例结果~
方法一:固定阈值分组(适合明确知道差值范围的场景)
比如你的示例里,同一组内数值差≤2就被归为一类,用这个方法刚好合适。
步骤1:导入工具并加载数据
import pandas as pd import numpy as np # 模拟你的示例数据 data = pd.DataFrame({ 'cat1': ['A','A','A','B','B','B','B','C','C','D','D','E'], 'cat2': ['a','b','c','a','b','c','d','a','b','a','b','a'], 'value': [1523314515,1523318114,1523318115,1523314604,1523314605,1523314603,1523331024,1523313948,1523314790,1523313952,1523314815,1523529294], 'new_value': [1523314515,1523318114,1523318114,1523314603,1523314603,1523314603,1523331024,1523313948,1523314790,1523313952,1523314815,1523529292] })
步骤2:自定义分组函数
这个函数会把同一组内差值≤阈值的数值归为一类,然后用你指定的聚合值替换(示例用的是最小值,和你的new_value列一致):
def group_by_threshold(series, threshold=2): # 先把数值排序,方便后续判断差值 sorted_vals = series.sort_values() groups = [] current_group = [sorted_vals.iloc[0]] # 遍历数值,把差值在阈值内的归入同一组 for num in sorted_vals.iloc[1:]: if num - current_group[-1] <= threshold: current_group.append(num) else: groups.append(current_group) current_group = [num] groups.append(current_group) # 建立数值到聚合值的映射关系 value_map = {} for group in groups: # 这里可以替换成np.mean(group)(均值)、max(group)(最大值)等 agg_value = min(group) for num in group: value_map[num] = agg_value # 把原数值替换成对应的聚合值 return series.map(value_map) # 按cat1分组处理value列,生成计算后的新值 data['calculated_new_value'] = data.groupby('cat1')['value'].apply(group_by_threshold)
步骤3:查看结果
运行下面的代码就能看到计算结果和你的示例new_value列完全匹配:
print(data[['cat1','cat2','value','new_value','calculated_new_value']])
方法二:DBSCAN动态聚类(适合自动识别相似簇的场景)
如果不想固定阈值,想让算法自动识别相似的数值组,可以用DBSCAN聚类算法:
from sklearn.cluster import DBSCAN def cluster_values(series, eps=2): # DBSCAN需要二维数组格式,所以把一维数值转成二维 X = series.values.reshape(-1,1) # 初始化聚类模型,eps就是我们的阈值 dbscan = DBSCAN(eps=eps, min_samples=1) clusters = dbscan.fit_predict(X) # 对每个聚类簇计算聚合值并替换 agg_values = series.groupby(clusters).transform(lambda x: min(x)) return agg_values # 同样按cat1分组处理 data['calculated_new_value_dbscan'] = data.groupby('cat1')['value'].apply(cluster_values)
关键调整点
- 聚合值切换:把代码里的
min(group)换成np.mean(group)就能用均值替换,换成max(group)就是最大值,完全按需调整。 - 分组范围:如果不需要按
cat1分组,而是全局所有数值一起聚类,直接去掉groupby('cat1')即可。 - 阈值调整:如果你的数值是时间戳(看起来像Unix时间戳),可以把阈值改成5、10(对应5秒、10秒的差值),适配你的业务场景。
内容的提问来源于stack exchange,提问作者dMb
相关产品推荐
相关产品推荐

