如何用Stripplot展示Boxplot中的极端异常值?R语言求助
我来帮你解决这个箱线图异常值的展示问题!你的核心需求是在不隐藏异常值的前提下,让主图美观,同时把极端值单独展示,这个思路非常合理,下面我会一步步带你实现,还会修正你之前代码里的问题。
首先先梳理你之前代码里的几个小问题:
- 拼写错误:
df$Trail2应该是df$Trial2(少了一个字母i) - 异常值筛选逻辑有误:
df[!(df %in% xout)]不能直接用在数据框上,因为xout是从多个分组提取的异常值集合,你需要针对每个分组(Trial2、Trial3)单独处理数据,同时保留分组信息。
方案实现:双图组合展示(主箱线图+异常值散点图)
我用ggplot2和tidyverse工具包来实现,它们能更灵活地处理数据和组合图表:
步骤1:准备数据与加载依赖包
先把你的示例数据加载好,同时把宽格式数据转成更适合分组处理的长格式:
# 加载必要的包(如果没安装先运行:install.packages("tidyverse")) library(tidyverse) # 示例数据(如果是从CSV读取,替换成 df <- read.csv("Inhibitor.csv", header=TRUE)) df <- tibble( Inhibitor = c("grak", "grab", "hhus", "hhuf", "kkul", "kkju", "juik", "jtui", "test"), Trial2 = c(0.20, 11.00, 0.21, 0.341, 1.66, 0.45, 0.30, 0.80, 0.233), Trial3 = c(0.45, 31.55, 0.18, 0.32, 0.80, 0.30, 0.20, 0.40, 0.36) ) # 转成长格式,方便后续分组处理 df_long <- df %>% pivot_longer(cols = starts_with("Trial"), names_to = "Trial", values_to = "Rate")
步骤2:标记每个分组的异常值
用箱线图的默认规则(超过四分位距IQR的1.5倍)来识别异常值:
df_long <- df_long %>% group_by(Trial) %>% mutate( q1 = quantile(Rate, 0.25), q3 = quantile(Rate, 0.75), iqr = q3 - q1, # 标记是否为异常值 is_outlier = Rate > q3 + 1.5*iqr | Rate < q1 - 1.5*iqr ) %>% ungroup()
步骤3:绘制主箱线图(y轴范围0-10)
主图只展示非异常值,同时隐藏默认的异常值点,避免干扰:
p_main <- ggplot(df_long %>% filter(!is_outlier | Rate <= 10), aes(x = Trial, y = Rate)) + geom_boxplot(fill = "#69b3a2", outlier.shape = NA) + # 隐藏默认异常值点 geom_jitter(width = 0.2, alpha = 0.6) + # 添加非异常值散点,更直观展示数据分布 ylim(0, 10) + labs(x = "Trial", y = "Rate") + theme_minimal()
步骤4:绘制上方的异常值散点图(y轴范围10-35)
这个图专门展示大于10的极端异常值,同时简化样式避免和主图重复:
p_outliers <- ggplot(df_long %>% filter(is_outlier & Rate > 10), aes(x = Trial, y = Rate)) + geom_point(color = "#ff4500", size = 3) + # 用醒目的橙色标记异常值 ylim(10, max(df_long$Rate) + 2) + # y轴从10开始,留出一点空间 labs(x = "", y = "") + # 去掉冗余的轴标签 theme_minimal() + theme( axis.text.x = element_blank(), # 隐藏x轴刻度,和主图共用 axis.ticks.x = element_blank(), panel.grid = element_blank() # 去掉网格线,保持简洁 )
步骤5:组合两个图表
用patchwork包把两个图垂直组合,对齐x轴,设置合理的高度比例:
# 如果没安装patchwork,先运行:install.packages("patchwork") library(patchwork) # 异常值图在上,主图在下,高度比例2:8 p_outliers / p_main + plot_layout(heights = c(2, 8))
可选方案:截断箱线图+标记
如果你不想用两个图,也可以直接在主图里截断y轴,用箭头和文本标记异常值:
ggplot(df_long, aes(x = Trial, y = Rate)) + geom_boxplot(fill = "#69b3a2", outlier.shape = NA) + geom_jitter(data = df_long %>% filter(Rate <=10), width = 0.2, alpha = 0.6) + # 在y=10的位置用三角形标记异常值位置 geom_point(data = df_long %>% filter(Rate >10), aes(x = Trial, y = 10), color = "#ff4500", shape = 2) + # 用箭头指向异常值实际位置 geom_segment(data = df_long %>% filter(Rate >10), aes(x = Trial, xend = Trial, y = 10, yend = 10), arrow = arrow(length = unit(0.2, "cm")), color = "#ff4500") + # 标注异常值的具体数值 annotate("text", x = df_long %>% filter(Rate >10) %>% pull(Trial), y = df_long %>% filter(Rate >10) %>% pull(Rate), label = df_long %>% filter(Rate >10) %>% pull(Rate), vjust = -0.5, color = "#ff4500") + ylim(0, 10) + labs(x = "Trial", y = "Rate") + theme_minimal()
这样处理后,你的箱线图既保持了美观的展示效果,又完整保留了所有数据信息,不会因为极端值被压缩成线条啦!
内容的提问来源于stack exchange,提问作者CuriousDude
相关产品推荐
相关产品推荐

