如何删除浮点型数据集中重复值占比超阈值的列?
删除重复值占比超阈值的浮点型列问题解决方案
问题描述
现有时间序列数据集df,需编写函数删除重复值占比超过设定阈值的浮点型列。例如:
val1中4.772234出现次数超过半数,该列应被删除;- 若阈值设为0.3,
val2中-6.538462出现4次(占比0.4),也需被删除。
现有问题
尝试的两种方法均未得到正确结果:
- 直接用
df.apply(lambda x: x.value_counts().iloc[0]/len(x))计算浮点列重复占比失败; - 以下函数调用后,
val3中1.101784占比0.4(超过0.3阈值)却未被删除:
def remove_columns_with_too_many_duplicates(df, threshold=0.5): duplicate_ratio = df.duplicated(keep=False).mean() columns_to_remove = duplicate_ratio[duplicate_ratio > threshold].index df = df.drop(columns_to_remove, axis=1) return df
循环判断的方法也存在同样问题。
示例数据集
import pandas as pd from io import StringIO data = """ date,val1,val2,val3 2017-01-31 00:00:00,4.772234,-6.538462,1.101784 2017-02-28 00:00:00,4.772234,-6.538462,1.101784 2017-03-31 00:00:00,4.772234,-6.538462,1.101784 2017-04-30 00:00:00,4.772234,-6.538462,1.101784 2017-05-31 00:00:00,4.772234,-4.526749,-0.622730 2017-06-30 00:00:00,4.772234,0.000000,-1.033943 2017-07-31 00:00:00,4.772234,3.448276,0.253271 2017-08-31 00:00:00,6.997930,-1.666667,-0.526316 2017-09-30 00:00:00,4.247291,5.084746,-2.476190 2017-10-31 00:00:00,4.377417,0.000000,-0.462963 """ data_io = StringIO(data) df = pd.read_csv(data_io)
正确解决方案
问题根源
- 原代码
df.duplicated(keep=False).mean()是计算整行重复的占比,而非单列内某个值的重复占比,完全不符合需求; - 浮点型数据直接用
value_counts()可能因精度问题(比如存储的微小差异)导致统计错误,需要先对浮点值进行精度舍入。
实现代码
def remove_high_duplicate_float_columns(df, threshold=0.5, precision=6): # 筛选浮点型列 float_cols = df.select_dtypes(include=['float64', 'float32']).columns cols_to_remove = [] for col in float_cols: # 对浮点值进行精度舍入,避免精度误差影响统计 rounded_series = df[col].round(precision) # 获取出现次数最多的值的占比 max_count = rounded_series.value_counts().iloc[0] ratio = max_count / len(df) if ratio > threshold: cols_to_remove.append(col) # 删除目标列 df_cleaned = df.drop(cols_to_remove, axis=1) return df_cleaned
代码说明
- 筛选浮点列:只处理
float64/float32类型的列,避免影响日期等非数值列; - 精度舍入:通过
round(precision)统一浮点值的精度,解决因浮点存储精度导致的统计错误; - 计算重复占比:对每列舍入后的值统计出现次数,取最大值计算占比,判断是否超过阈值;
- 删除列:收集所有符合条件的列并删除,返回清理后的数据集。
验证结果
调用函数测试:
# 测试阈值0.5 df_cleaned_05 = remove_high_duplicate_float_columns(df, threshold=0.5) print("阈值0.5保留的列:", df_cleaned_05.columns.tolist()) # 输出:阈值0.5保留的列: ['date', 'val2', 'val3'] # 测试阈值0.3 df_cleaned_03 = remove_high_duplicate_float_columns(df, threshold=0.3) print("阈值0.3保留的列:", df_cleaned_03.columns.tolist()) # 输出:阈值0.3保留的列: ['date']
完全符合预期:
- 阈值0.5时,
val1(占比0.7)被删除; - 阈值0.3时,
val1(0.7)、val2(0.4)、val3(0.4)均被删除。
内容的提问来源于stack exchange,提问作者ah bon
相关产品推荐
相关产品推荐

