基于R语言按季节计算数据框中化合物的异常值占比
按季节统计化合物异常值占比解决方案
问题背景
现有一个含31列、12万+行的小时测量数据框,结构如下:
| DateTime | Ethane | Ethene | [...] | Season |
|---|---|---|---|---|
| 2008-01-01 01:00:00 | 10.81 | 1.47 | [...] | DJF_2008 |
| 2008-01-01 02:00:00 | 10.31 | 1.13 | [...] | DJF_2008 |
需求:
- 对所有化合物测量值(第2-30列)计算
log10转换 - 按
Season分组,统计每个化合物中超出均值±4倍标准差的数据占比,最终得到以季节为行、化合物为列的结果数据框
之前尝试分开计算上下限后,因数据框长度不匹配无法整合,以下是可行的解决方案:
完整代码实现
library(dplyr) # 1. 数据预处理:计算log10并整理列 LogC <- My_dataset %>% mutate(across(c(2:30), log10)) %>% # 对第2-30列(化合物)批量取log10 select(DateTime, Season, everything()) # 调整列顺序,便于后续操作 # 2. 按季节统计异常值占比 outlier_ratio <- LogC %>% group_by(Season) %>% summarise( # 遍历所有化合物列,计算异常值占比 across(c(3:ncol(.)), ~ { col_mean <- mean(., na.rm = TRUE) col_sd <- sd(., na.rm = TRUE) # 统计超出±4σ的数量,除以该季节该列非NA数据总数 sum(. < (col_mean - 4*col_sd) | . > (col_mean + 4*col_sd), na.rm = TRUE) / sum(!is.na(.)) }), .groups = "drop" # 计算完成后取消分组 ) # 处理全NA列导致的NaN结果 outlier_ratio <- outlier_ratio %>% mutate(across(-Season, ~ ifelse(is.nan(.), NA, .)))
代码说明
- 数据预处理:用
across批量处理化合物列的log10转换,替代原代码手动拼接列的操作,更简洁不易出错 - 分组统计:
- 按
Season分组后,用across遍历所有化合物列 - 对每列先计算组内均值和标准差,再判断每个值是否超出±4σ范围
- 异常值数量除以该季节该列的非NA数据总数,得到占比
- 按
- NA处理:将全NA列计算产生的
NaN替换为NA,保证结果整洁规范
结果说明
最终的outlier_ratio数据框即为需求结果:
- 行:每个唯一的
Season值 - 列:每个化合物名称,对应值为该季节该化合物的异常值占比
内容的提问来源于stack exchange,提问作者R beginer
相关产品推荐
相关产品推荐

