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

如何在stat_compare_means统计检验中自动剔除分组内异常值?

解决方案:先自动清理异常值再做统计检验

stat_compare_means 本身没有内置参数支持直接在计算时忽略异常值,所以核心思路是先按分组(含分面维度)自动剔除异常值,再用清理后的数据集绘图和执行统计检验。以下是具体实现步骤:


1. 定义自动剔除异常值的函数

用箱线图默认的IQR规则(小于Q1-1.5IQR 或 大于Q3+1.5IQR的值判定为异常值),写一个支持多分组、多分面维度的清理函数:

remove_outliers <- function(data, group_vars, value_var) {
  data %>%
    # 按指定的分组/分面变量分组
    group_by(across(all_of(group_vars))) %>%
    mutate(
      q1 = quantile({{value_var}}, 0.25, na.rm = TRUE),
      q3 = quantile({{value_var}}, 0.75, na.rm = TRUE),
      iqr = q3 - q1,
      lower_bound = q1 - 1.5 * iqr,
      upper_bound = q3 + 1.5 * iqr,
      is_outlier = {{value_var}} < lower_bound | {{value_var}} > upper_bound
    ) %>%
    # 过滤掉异常值
    filter(!is_outlier) %>%
    ungroup() %>%
    # 清理中间计算列
    select(-q1, -q3, -iqr, -lower_bound, -upper_bound, -is_outlier)
}

2. 处理你的示例数据集

library(ggplot2)
library(ggsignif)
library(dplyr)

# 原示例数据
df = data.frame(name = c(rep("Bob",5),rep("Tom",5)),
                score = c(2,3,4,5,100,5,8,9,10,95))

# 按name分组剔除异常值
df_clean <- remove_outliers(df, group_vars = "name", value_var = score)

清理后的数据会自动去掉Bob组的100和Tom组的95。


3. 用清理后的数据绘图+统计检验

df_clean %>% 
  ggplot(aes(x=name,y=score)) + 
  geom_boxplot() + 
  stat_compare_means(comparisons = list(c("Bob","Tom")),method="t.test", paired=F)

此时统计检验的结果完全基于剔除异常值后的样本。


4. 扩展到多分组+分面场景

如果你的数据集有分面变量(比如class),只需把分面变量加入group_vars参数即可:

# 构造带分面的示例数据
df_multi <- data.frame(
  name = rep(c("Bob", "Tom"), each=5, times=2),
  class = rep(c("Class1", "Class2"), each=10),
  score = c(2,3,4,5,100,5,8,9,10,95, 1,2,3,4,80,6,7,8,9,85)
)

# 按name+class(分面变量)分组清理异常值
df_multi_clean <- remove_outliers(df_multi, group_vars = c("name", "class"), value_var = score)

# 分面绘图+统计检验
df_multi_clean %>% 
  ggplot(aes(x=name,y=score)) + 
  geom_boxplot() + 
  facet_wrap(~class) +
  stat_compare_means(comparisons = list(c("Bob","Tom")),method="t.test", paired=F)

每个分面内的分组都会独立完成异常值清理,统计检验逻辑也会适配清理后的样本。


可选:自定义异常值规则

如果需要用其他规则(比如z-score±3),只需修改函数里的is_outlier计算逻辑:

# z-score规则的版本
remove_outliers_zscore <- function(data, group_vars, value_var, threshold=3) {
  data %>%
    group_by(across(all_of(group_vars))) %>%
    mutate(
      z_score = scale({{value_var}}),
      is_outlier = abs(z_score) > threshold
    ) %>%
    filter(!is_outlier) %>%
    ungroup() %>%
    select(-z_score, -is_outlier)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 23:39:16