如何使用R语言ggplot实现散点图、箱线图与线性回归线同图绘制
实现方案
你之前的核心冲突是散点用了离散因子型x轴,无法叠加需要连续x轴的线性回归线,我们通过统一x轴为连续数值、手动设置刻度标签的方式解决该问题,完整实现代码如下:
1. 加载依赖包
library(tidyverse) # 可选依赖,用于自动生成回归公式,无需手动计算位置 library(ggpmisc)
2. 原数据(无需修改)
df <- structure(list(Sample = c(2113, 2113, 2114, 2114, 2115, 2115, 2116, 2116, 2117, 2117, 2118, 2118, 2119, 2119, 2120, 2120, 2121, 2121, 2122, 2122, 2123, 2123, 2124, 2124), Rep_No = c("A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B"), Fe = c(57.24, 57.12, 57.2, 57.13, 57.21, 57.14, 57.16, 57.31, 57.11, 57.18, 57.21, 57.12, 57.14, 57.17, 57.1, 57.18, 57, 57.06, 57.13, 57.09, 57.17, 57.23, 57.09, 57.1), SiO2 = c("6.85", "6.83", "6.7", "6.69", "6.83", "6.8", "6.76", "6.79", "6.82", "6.82", "6.8", "6.86", "6.9", "6.82", "6.81", "6.83", "6.79", "6.76", "6.8", "6.88", "6.83", "6.79", "6.8", "6.83"), Al2O3 = c("2.9", "2.88", "2.88", "2.88", "2.92", "2.9", "2.89", "2.87", "2.9", "2.89", "2.9", "2.89", "2.89", "2.88", "2.89", "2.91", "2.91", "2.91", "2.9", "2.9", "2.91", "2.91", "2.88", "2.86")), row.names = c(NA, -24L ), class = "data.frame")
3. 数据预处理
df_plot <- df %>% # 给每个唯一样本分配1~12的连续序号,作为散点的x轴位置 mutate(sample_pos = as.integer(factor(Sample, levels = unique(Sample)))) # 自定义x轴标签,第一个位置对应箱线图,后面对应样本编号 x_ticks <- c("All Data", unique(df_plot$Sample))
4. 完整绘图代码(满足所有需求)
ggplot() + # 箱线图放在x=0的最左侧位置 geom_boxplot(aes(x = 0, y = Fe), data = df_plot) + # 散点用样本序号作为x位置,保留按Sample分组的原有配色逻辑 geom_point(aes(x = sample_pos, y = Fe, color = factor(Sample)), data = df_plot) + # 添加线性回归线 geom_smooth(aes(x = sample_pos, y = Fe), data = df_plot, method = "lm", se = FALSE, color = "gray30") + # 自动添加回归公式与R²,不需要手动设置坐标 stat_poly_eq(aes(x = sample_pos, y = Fe), data = df_plot, formula = y ~ x, label = paste(after_stat(eq.label), after_stat(rr.label), sep = "*\", \"*"), parse = TRUE, label.y = "bottom") + # 自定义x轴刻度和标签 scale_x_continuous(breaks = 0:12, labels = x_ticks) + # 主题和标签设置,和你原有样式保持一致 ggtitle("Lab Test Order Fe") + xlab("Sample No") + ylab("Homogeneity Test Fe %") + theme( plot.title = element_text(hjust = 0.5), legend.position = "none" )
无额外依赖的替代方案
如果你不想安装ggpmisc包,可以用你原来的lm_eqn函数,把公式部分替换为自适应坐标的版本即可:
# 你原来的公式计算函数,适配新的x轴映射 lm_eqn <- function(df,...){ x <- df$sample_pos y <- df$Fe m <- lm(y ~ x, df); eq <- substitute(italic(y) == a + b %.% italic(x)*","~~italic(r)^2~"="~r2, list(a = format(unname(coef(m)[1]), digits = 2), b = format(unname(coef(m)[2]), digits = 2), r2 = format(summary(m)$r.squared, digits = 3))) as.character(as.expression(eq)); } a <- lm_eqn(df_plot) # 把stat_poly_eq部分替换为下面的代码即可,不需要手动指定固定坐标 geom_text(aes(x = median(unique(df_plot$sample_pos)), y = min(df_plot$Fe) + 0.02, label = a, parse = TRUE), check_overlap = TRUE)
实现效果说明
- 箱线图固定在x轴最左侧的0位置,和右侧散点区域完全分隔
- 散点的颜色映射逻辑和你原有代码完全一致,配色保留
- 回归公式通过计算取值范围自动定位,不需要手动输入固定坐标,适配不同数据范围
内容的提问来源于stack exchange,提问作者Spooked
相关产品推荐
相关产品推荐

