You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用R函数或循环批量统计各列中超出指定组范围的样本数

批量统计分组数据中各列的异常值数量

问题根源

你遇到的错误是因为函数中直接使用column参数时,dplyr无法识别它对应数据框的列,加上调用函数时传入的是裸变量(如x),没有做非标准求值处理,导致column被当成整个列向量,和分组后的向量长度不匹配,从而触发长度错误。

修复后的单列处理函数

使用rlang的非标准求值语法({{}}和!!)解决列参数识别问题,同时让结果列名自动匹配传入的列:

library(dplyr)

count_outliers <- function(data, column, min_val, max_val) {
  # 获取传入列的名称
  col_name <- rlang::as_name(rlang::enquo(column))
  
  data %>% 
    filter(!is.na({{ column }})) %>%
    group_by(change) %>%
    mutate(
      lower_bound = min_val,
      upper_bound = max_val,
      is_pos_outlier = {{ column }} > upper_bound,
      is_neg_outlier = {{ column }} < lower_bound
    ) %>%
    summarise(
      # 动态生成列名
      !!paste0(col_name, "_pos_outliers") := sum(is_pos_outlier),
      !!paste0(col_name, "_neg_outliers") := sum(is_neg_outlier),
      .groups = "drop"  # 取消分组,避免后续操作警告
    )
}

调用示例

先优化normal组极值的计算(无需多余分组):

normal <- c('normal1', 'normal2', 'normal3', 'normal4')

minmax_normal <- data %>% 
  filter(change %in% normal) %>%
  summarise(across(c(x, y, z), list(min = min, max = max), na.rm = TRUE))

# 处理x列
x_outliers <- count_outliers(data, x, minmax_normal$x_min, minmax_normal$x_max)

批量处理所有列

如果要一次性处理所有数值列,推荐两种高效方案:

方法1:用purrr批量遍历列

library(purrr)

# 指定需要处理的列(排除sample和change)
target_cols <- setdiff(names(data), c("sample", "change"))

# 批量生成所有列的异常值统计
all_outliers <- map_dfr(target_cols, function(col) {
  # 获取当前列的normal组极值
  min_val <- minmax_normal[[paste0(col, "_min")]]
  max_val <- minmax_normal[[paste0(col, "_max")]]
  # 调用函数,用!!sym()将字符串转成列对象
  count_outliers(data, !!sym(col), min_val, max_val)
})

方法2:一步到位的dplyr流程(无需单独函数)

通过数据格式转换,直接完成批量统计:

all_outliers <- data %>%
  # 提取normal组的各列极值,转成窄表方便合并
  filter(change %in% normal) %>%
  summarise(across(c(x, y, z), list(min = min, max = max), na.rm = TRUE)) %>%
  pivot_longer(
    everything(), 
    names_to = c("column", ".value"), 
    names_pattern = "(.*)_(min|max)"
  ) %>%
  # 将极值合并到原数据的每一行
  right_join(data, by = character()) %>%
  # 过滤掉各列的NA值
  filter(across(c(x, y, z), ~!is.na(.x))) %>%
  # 按分组和列名统计异常值
  group_by(change, column) %>%
  summarise(
    pos_outliers = sum(.data[[column]] > max, na.rm = TRUE),
    neg_outliers = sum(.data[[column]] < min, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  # 转成宽表格式(可选,更易读)
  pivot_wider(
    names_from = column, 
    values_from = c(pos_outliers, neg_outliers),
    names_glue = "{column}_{.value}"
  )

内容的提问来源于stack exchange,提问作者Mitchel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 15:56:04