如何批量将数据框数值列的异常值替换为列中位数?
批量替换数据集中所有数值列的异常值
我有一个包含分类变量与数值变量的数据集,希望用箱线图识别异常值并替换为对应列的中位数,但需要批量处理所有数值列,而非逐个列手动操作。单列处理的参考代码如下:
df$v3[df$v3 %in% boxplot(df)$out] <- median(df$v3)
数据集结构:
df<-structure(list(`Project Title` = c("Cameroun - Projet d’aide humanitaire d’urgence en faveur des réfugiés hors sites et des populations hôtes situés dans les régions de l’Adamaoua, de l’Est et du Nord\r\n(Version française uniquement)", "Multinational - Kenya-Tanzania Power Interconnection Project", "Multinational - Kenya-Tanzania Power Interconnection Project", "Zambia - Madison Finance Company Limited\r\n(under the Africa SME Program)", "Eritrea - Skills Development for Employability and Entrepreneurship Project", "Eritrea - Skills Development for Employability and Entrepreneurship Project", "Uganda - Water Supply and Sanitation Programme - Additional activities", "Cabo Verde - Aide d’urgence pour assister les populations affectées par l’éruption volcanique de l’île de Fogo\r\n(Version française uniquement)", "Kenya - Mombasa-Mariakani Highway Project", "Multinational - Africa Banking Corporation Holdings Ltd" ), `Approval date Year Trend` = structure(c(1421107200, 1424217600, 1424217600, 1425254400, 1425340800, 1425340800, 1425427200, 1425600000, 1426032000, 1426032000), tzone = "UTC", class = c("POSIXct", "POSIXt")), `Type of Financing Source` = c("Special Relief Fund (SRF)", "ADF", "ADF", "ADB Private Sector", "ADF", "ADF", "Global Environment Facility (GEF)", "Special Relief Fund (SRF)", "ADF", "ADB Private Sector"), `Approved Amount_UA Equivalent` = c(690221.630165446, 75290000, 27500000, 2131605.31196044, 7580000, 5920000, 5947178.82036962, 191844.478076439, 8e+07, 11842251.7331135), `Approved Amount_USDEquivalent` = c(920065.43301054, 100361570, 36657500, 2841429.88084326, 10104140, 7891360, 7927589.3675527, 255728.689275894, 106640000, 15785721.5602403), `Project ID` = c("P-CM-I00-001", "P-Z1-FA0-052", "P-Z1-FA0-086", "P-ZM-HAB-003", "P-ER-IA0-001", "P-ER-IA0-001", "P-UG-E00-013", "P-CV-I00-001", "P-KE-DB0-021", "P-Z1-HAB-046"), `Employe Name` = c("BISSAKONOU Judes", "MUGUWA Andrew", "MUGUWA Andrew", "FRENCH Laura Katherine Smith", "ELAHEEBOCUS Bibi Nawsheen", "ELAHEEBOCUS Bibi Nawsheen", "MBIRO Andrew", "TRAORE Rokhaya", "MAMMO Zerfu Tessema", "MACHARIA Julius Karuga"), `Financing Source` = c("OTHERS", "ADF Including TSF", "ADF Including TSF", "ADB Private", "ADF Including TSF", "ADF Including TSF", "OTHERS", "OTHERS", "ADF Including TSF", "ADB Private"), `Financial Access Category` = c("Blend Countries", "Multinational", "Blend Countries", "Blend Countries", "ADF Countries", "ADF Countries", "ADF Countries", "ADB Countries", "Blend Countries", "Multinational"), `Country Classifaction` = c("Non-Transition States", "Multinational", "Non-Transition States", "Non-Transition States", "Transition States", "Transition States", "Non-Transition States", "Non-Transition States", "Non-Transition States", "Multinational" ), `Country Name` = c("CAMEROON", "MULTINATIONAL", "KENYA", "ZAMBIA", "ERITREA", "ERITREA", "UGANDA", "Cape Verde", "KENYA", "MULTINATIONAL" ), `REGION NAME` = c("Central", "Multinational", "East", "South", "East", "East", "East", "West", "East", "Multinational"), `Sectoral Analysis` = c("Social", "Power", "Power", "Finance", "Social", "Social", "WASH Sector", "Social", "Transport", "Finance"), `High Five Prority 1: Feed Africa` = c(NA, NA, NA, NA, NA, NA, 178415.364611089, NA, NA, NA), `High Five Prority 2: Light Up And Power Africa` = c(NA, 75290000, 27500000, NA, NA, NA, 59471.7882036962, NA, NA, NA), `High Five Prority 3: Industrialize Africa` = c(NA, NA, NA, 2131605.31196044, NA, NA, NA, NA, NA, 11842251.7331135), `High Five Prority 4: Integrate Africa` = c(NA, NA, NA, NA, NA, NA, NA, NA, 8e+07, NA), `High Five Prority 5: Improve Quality Of Life` = c(690221.630165446, NA, NA, NA, 7580000, 5920000, 5709291.66755484, 191844.478076439, NA, NA), `Financing Instrument` = c("Emergency Assistance", "Investment Project", "Investment Project", "Investment Project", "Investment Project", "Investment Project", "ISP and Investment Project", "Emergency Assistance", "Investment Project", "Investment Project" ), `Infrastructure vs Sector` = c("Social", "Infrastructure", "Infrastructure", "Finance", "Social", "Social", "Infrastructure", "Social", "Infrastructure", "Finance"), `SECTOR DEPARTMENT` = c("AHAI", "PESD", "PESD", "PIFD", "AHHD", "AHHD", "AHWS", "AHHD", "PICU", "PIFD"), `Sector Complex Name` = c("AHVP", "PEVP", "PEVP", "PIVP", "AHVP", "AHVP", "AHVP", "AHVP", "PIVP", "PIVP"), `Operations Type` = c("Sovereign", "Sovereign", "Sovereign", "Non-Sovereign", "Sovereign", "Sovereign", "Sovereign", "Sovereign", "Sovereign", "Non-Sovereign"), `NUMBER OF PROJECT` = c(1, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 1), `Amount in UA Million` = c(0.690221630165446, 75.29, 27.5, 2.13160531196044, 7.58, 5.92, 5.94717882036962, 0.191844478076439, 80, 11.8422517331135)), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"))
解决方案
方法1:Base R 批量处理
通过lapply遍历所有数值列,自动完成异常值识别与替换:
# 筛选所有数值类型的列 numeric_cols <- sapply(df, is.numeric) # 对每个数值列执行异常值替换 df[numeric_cols] <- lapply(df[numeric_cols], function(col) { # 不绘制箱线图,仅获取异常值列表 outliers <- boxplot(col, plot = FALSE)$out # 计算列的中位数(忽略缺失值) col_median <- median(col, na.rm = TRUE) # 将异常值替换为中位数 col[col %in% outliers] <- col_median return(col) })
方法2:tidyverse/dplyr 风格实现
如果使用tidyverse工具链,用across函数可以更简洁地批量处理:
library(dplyr) df_clean <- df %>% mutate(across(where(is.numeric), ~{ outliers <- boxplot(., plot = FALSE)$out median_val <- median(., na.rm = TRUE) # 替换异常值 replace(., . %in% outliers, median_val) }))
关键细节说明
plot = FALSE:避免每次处理列都弹出箱线图,仅返回异常值数据na.rm = TRUE:计算中位数时自动忽略缺失值,避免结果出错- 两种方法都会保留原数据集的分类列,仅修改数值列的异常值
内容的提问来源于stack exchange,提问作者firmo23
相关产品推荐
相关产品推荐

