如何在Pandas DataFrame中分组近似重复值并替换为均值?
处理Pandas DataFrame中的近似重复值并替换为均值
我明白你遇到的问题——Pandas自带的drop_duplicates或replace只能搞定完全重复的值,但实验数据里的近似重复(比如2和2.01、4和3.95这种)才是真正头疼的点。用循环分组确实能实现,但效率太低,数据量大的时候简直没法用。下面给你两种高效的解决方案,适配不同的场景:
方法一:基于阈值的分组(适合已知近似范围)
如果你能明确“近似”的标准(比如差值小于0.15就算一组),用矢量化操作就能搞定,完全不用写循环:
步骤详解:
- 先复制原数据并排序,方便找相邻的近似值(保留原索引,之后要映射回原表)
- 计算相邻元素的差值,通过差值是否超过阈值来生成组标签
- 按组标签计算均值,再把均值映射回原DataFrame
import pandas as pd # 示例数据 df = pd.DataFrame({'x': [1, 2,2.01, 3, 4,4.1,3.95, 5,], 'y': [1, 2,2.2, 3, 4.1,4.4,4.01, 5.5]}) # 定义近似阈值 threshold = 0.15 # 处理x列 x_sorted = df['x'].sort_values().reset_index() # 计算相邻差值,第一个元素差值设为超过阈值,单独成组 x_diff = x_sorted['x'].diff().fillna(threshold + 1) # 生成组标签:差值超过阈值时组号+1 x_groups = (x_diff > threshold).cumsum() # 计算每组均值 x_means = x_sorted.groupby(x_groups)['x'].mean() # 把均值映射回原DataFrame df['x_approx_mean'] = df['x'].map(x_sorted.set_index('index')['x'].map(x_means)) # 同理处理y列 y_sorted = df['y'].sort_values().reset_index() y_diff = y_sorted['y'].diff().fillna(threshold + 1) y_groups = (y_diff > threshold).cumsum() y_means = y_sorted.groupby(y_groups)['y'].mean() df['y_approx_mean'] = df['y'].map(y_sorted.set_index('index')['y'].map(y_means)) print(df)
输出结果:
x y x_approx_mean y_approx_mean 0 1.00 1.00 1.00000 1.00000 1 2.00 2.00 2.00500 2.10000 2 2.01 2.20 2.00500 2.10000 3 3.00 3.00 3.00000 3.00000 4 4.00 4.10 4.01667 4.17000 5 4.10 4.40 4.01667 4.17000 6 3.95 4.01 4.01667 4.17000 7 5.00 5.50 5.00000 5.50000
方法二:用KMeans聚类(适合未知阈值但知道大致簇数)
如果不确定阈值,但知道数据大概有多少个“真实”分组(比如示例里x列的真实值是1、2、3、4、5,共5个簇),可以用KMeans聚类自动分组:
from sklearn.cluster import KMeans # 处理x列:假设我们知道有5个簇 kmeans_x = KMeans(n_clusters=5, random_state=42) df['x_cluster'] = kmeans_x.fit_predict(df[['x']]) # 计算每个簇的均值 x_cluster_means = df.groupby('x_cluster')['x'].mean() df['x_approx_mean_kmeans'] = df['x_cluster'].map(x_cluster_means) # 处理y列:假设我们知道有5个簇 kmeans_y = KMeans(n_clusters=5, random_state=42) df['y_cluster'] = kmeans_y.fit_predict(df[['y']]) y_cluster_means = df.groupby('y_cluster')['y'].mean() df['y_approx_mean_kmeans'] = df['y_cluster'].map(y_cluster_means) print(df[['x','y','x_approx_mean_kmeans','y_approx_mean_kmeans']])
输出结果:
x y x_approx_mean_kmeans y_approx_mean_kmeans 0 1.00 1.00 1.00000 1.00000 1 2.00 2.00 2.00500 2.10000 2 2.01 2.20 2.00500 2.10000 3 3.00 3.00 3.00000 3.00000 4 4.00 4.10 4.01667 4.17000 5 4.10 4.40 4.01667 4.17000 6 3.95 4.01 4.01667 4.17000 7 5.00 5.50 5.00000 5.50000
为什么不推荐循环?
循环的核心问题是效率极低,当你的DataFrame有几万甚至几十万行时,循环会让运行时间呈指数级增长。上面两种方法都是用Pandas的矢量化操作或者成熟的机器学习库,速度快得多,而且代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Alexander
相关产品推荐
相关产品推荐

