基于变量分布填充缺失值时遇ValueError等问题求助
问题:基于分布特征填充缺失值的代码错误解决
需求:为50余个变量填充缺失值,逻辑如下:
- 若变量满足
mode>median>mean或mode<median<mean(偏态分布),用中位数填充 - 若
mode=median=mean(正态分布),用均值填充 - 其余情况用中位数填充
尝试三种方法均报错,以下是代码及错误信息:
方法1
#filling data based on the variable distribution for cols in num_cols2: if ((df[cols].mean() < df[cols].median()) & (df[cols].median() < df[cols].mode())) | ((df[cols].mean() > df[cols].median()) & (df[cols].median() > df[cols].mode())): df[cols]=df[cols].fillna(df.median()) elif ((df[cols].mean() == df[cols].median()) & (df[cols].median() == df[cols].mode())): df[cols]=df[cols].fillna(df.mean().iloc[0]) else: df[cols]=df[cols].fillna(df.median())
错误信息:
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) /Users/admin/Library/CloudStorage/OneDrive-Personal/DA Material/Data Science 6/EDAPipeDetectionleak.ipynb Cell 34 in <cell line: 3>() 1 #filling data based on distribution 3 for cols in num_cols2: ----> 4 if ((df[cols].mean() < df[cols].median()) & (df[cols].median() < df[cols].mode())) | ((df[cols].mean() > df[cols].median()) & (df[cols].median() > df[cols].mode())): 5 df[cols]=df[cols].fillna(df.median()) 6 elif ((df[cols].mean() == df[cols].median()) & (df[cols].median() == df[cols].mode())): File /opt/homebrew/lib/python3.10/site-packages/pandas/core/generic.py:1527, in NDFrame.__nonzero__(self) 1525 @final 1526 def __nonzero__(self): -> 1527 raise ValueError( 1528 f"The truth value of a {type(self).__name__} is ambiguous. " 1529 "Use a.empty, a.bool(), a.item(), a.any() or a.all()." 1530 ) ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
方法2(报错与方法1相同)
for cols in num_cols2: df[cols] = df[cols].apply(lambda cols:(df[cols].fillna(df.median()))) if (df[cols].mean() < df[cols].median()) & (df[cols].median() < df[cols].mode()) else (df[cols].fillna(df.mean()))
方法3
for cols in num_cols2: df.loc[(df[cols].mean() < df[cols].median()) & (df[cols].median() < df[cols].mode())] = df[cols].fillna(df.median()) df.loc[df[cols].mean() > df[cols].median() & (df[cols].median() > df[cols].mode())] = df[cols].fillna(df.median()) df.loc[((df[cols].mean() == df[cols].median()) & (df[cols].median() == df[cols].mode()))] = df[cols].fillna(df.mean().iloc[0])
for cols in num_cols2: df[cols] = df.loc[(df[cols].mean() < df[cols].median()) & (df[cols].median() < df[cols].mode())] = df[cols].fillna(df.median()) df[cols] = df.loc[df[cols].mean() > df[cols].median() & (df[cols].median() > df[cols].mode())] = df[cols].fillna(df.median()) df[cols] = df.loc[((df[cols].mean() == df[cols].median()) & (df[cols].median() == df[cols].mode()))] = df[cols].fillna(df.mean().iloc[0])
错误信息:
IndexingError: Unalignable boolean Series provided as indexer (index of the boolean Series and of the indexed object do not match).
错误原因与解决方案
核心问题
mode()返回值类型错误:df[cols].mode()返回的是Series类型(可能存在多个众数),直接和均值、中位数(单个数值)比较会生成布尔Series,导致if判断或索引时出现歧义报错。- 填充值范围错误:
df.median()/df.mean()是整个DataFrame的统计值,应该使用对应列的df[cols].median()/df[cols].mean()。 - 方法3的索引逻辑错误:用分布特征的布尔值去索引DataFrame行,完全不符合需求——我们需要对整列缺失值填充,而非筛选行。
修正后的代码
# 基于变量分布填充缺失值 for col in num_cols2: # 获取当前列的均值、中位数、众数(取第一个众数) col_mean = df[col].mean() col_median = df[col].median() col_mode = df[col].mode().iloc[0] # 判断分布类型并填充 if (col_mean < col_median < col_mode) or (col_mean > col_median > col_mode): # 偏态分布,用中位数填充 df[col] = df[col].fillna(col_median) elif abs(col_mean - col_median) < 1e-6 and abs(col_median - col_mode) < 1e-6: # 浮点数近似相等判断,避免精度问题,正态分布用均值填充 df[col] = df[col].fillna(col_mean) else: # 其余情况,用中位数填充 df[col] = df[col].fillna(col_median)
补充说明
- 若某列存在多个众数,
mode().iloc[0]取第一个众数,若需处理多众数场景,可根据业务需求调整逻辑。 - 浮点数比较时用
abs(a-b) < 1e-6替代==,避免因精度误差导致判断错误。
内容的提问来源于stack exchange,提问作者MOT
相关产品推荐
相关产品推荐

