Pandas替换异常值时,DataFrame子集列赋值newcol不生效问题
异常值替换赋值未生效问题解决
问题描述
我参考某博客代码,尝试对数据集df2_clean的.iloc[:,6:]子集替换异常值。计算得到的newcol列表结果正确,但执行df2_clean.iloc[:,6:][col] = newcol后赋值未生效——打印newcol的最大值与赋值后对应列的最大值不一致。完整代码如下:
for col in df2_clean.iloc[:,6:].columns: mean = df2_clean.iloc[:,6:][col].mean() std = df2_clean.iloc[:,6:][col].std() N = 1 upper = mean + N*std lower = mean - N*std median = df2_clean.iloc[:,6:][col].median() newcol = [] for val in df2_clean.iloc[:,6:][col]: if val < lower or val > upper: newcol.append(median) else: newcol.append(val) print(max(newcol)) df2_clean.iloc[:,6:][col] = newcol print(df2_clean.iloc[:,6:][col].max(),"\n")
问题原因
核心问题是链式索引产生副本,赋值仅作用于副本而非原数据集。df2_clean.iloc[:,6:][col]这种写法会先通过iloc[:,6:]生成一个原数据集的临时副本,后续对[col]的赋值只会修改这个副本,原数据集df2_clean完全没变化。
修正方案
方案1:通过列索引位置直接赋值
直接定位列在原数据集中的索引位置,避免链式索引:
# 获取需要处理的列(从第7列开始) cols_to_process = df2_clean.columns[6:] for col in cols_to_process: # 获取当前列在原数据集中的索引位置 col_index = df2_clean.columns.get_loc(col) # 直接从原数据集取该列 col_data = df2_clean.iloc[:, col_index] mean = col_data.mean() std = col_data.std() N = 1 upper = mean + N*std lower = mean - N*std median = col_data.median() newcol = [] for val in col_data: if val < lower or val > upper: newcol.append(median) else: newcol.append(val) print(max(newcol)) # 直接对原数据集的列赋值 df2_clean.iloc[:, col_index] = newcol print(df2_clean.iloc[:, col_index].max(), "\n")
方案2:直接使用列名赋值
如果列名唯一且确定,直接用列名操作原数据集更简洁:
cols_to_process = df2_clean.columns[6:] for col in cols_to_process: col_data = df2_clean[col] mean = col_data.mean() std = col_data.std() N = 1 upper = mean + N*std lower = mean - N*std median = col_data.median() newcol = [] for val in col_data: if val < lower or val > upper: newcol.append(median) else: newcol.append(val) print(max(newcol)) # 直接对原数据集的列赋值 df2_clean[col] = newcol print(df2_clean[col].max(), "\n")
优化方案:用向量化操作替代循环
Pandas的向量化操作比Python循环效率更高,推荐使用:
cols_to_process = df2_clean.columns[6:] for col in cols_to_process: col_data = df2_clean[col] mean = col_data.mean() std = col_data.std() N = 1 upper = mean + N*std lower = mean - N*std median = col_data.median() # 用where函数向量化替换异常值 newcol = col_data.where((col_data >= lower) & (col_data <= upper), median) print(newcol.max()) df2_clean[col] = newcol print(df2_clean[col].max(), "\n")
内容的提问来源于stack exchange,提问作者Ad D
相关产品推荐
相关产品推荐

