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

在R语言散点图中添加基于X区间中位数Y的经验最佳拟合线

实现自定义X区间的中位数拟合线(非参数方法)

刚好我之前做过类似的需求,这种非参数的区间中位数拟合线很适合展示数据趋势,而且完全不需要参数拟合,灵活性拉满。下面一步步给你演示怎么实现:

首先,我们先模拟一组匹配你场景的示例数据:

set.seed(123) # 固定随机种子,保证结果可重复
x <- runif(200, min = 0.1, max = 0.3) # 生成0.1到0.3之间的随机X值
y <- 5 + 10*(x - 0.2)^2 + rnorm(200, 0, 0.2) # 带噪声的二次曲线Y值
df <- data.frame(x, y)

第一步:自定义X区间分组

用cut()函数可以轻松实现灵活的区间分组,你可以完全自定义区间的间隔或者断点:

# 这里按0.01的步长划分区间,你可以修改breaks参数调整区间
# 比如想要0.02的步长,就把by改成0.02;非等距区间直接写breaks=c(0.1,0.12,0.15,...)
df$x_group <- cut(df$x, breaks = seq(0.1, 0.3, by = 0.01), include.lowest = TRUE)

include.lowest=TRUE是为了确保第一个区间能包含最小的X值,避免数据遗漏。

第二步:计算每个区间的中位数Y和区间中点

我个人习惯用dplyr来做数据汇总,代码更直观;如果你不想加载额外包,也可以用base R实现,我后面也会提。

library(dplyr)

fit_data <- df %>%
  group_by(x_group) %>%
  summarize(
    # 提取区间的上下限,然后计算中点
    lower = as.numeric(strsplit(gsub("\\(|\\)|\\[|\\]", "", as.character(x_group)), ",")[[1]][1]),
    upper = as.numeric(strsplit(gsub("\\(|\\)|\\[|\\]", "", as.character(x_group)), ",")[[1]][2]),
    x_mid = (lower + upper)/2,
    # 计算该区间内Y值的中位数
    y_median = median(y, na.rm = TRUE)
  ) %>%
  # 去掉没有数据的区间(避免画图时出现断点)
  filter(!is.na(y_median)) %>%
  select(x_mid, y_median) # 只保留需要的列

如果用base R的话,可以这样写:

# Base R 版本的分组计算
x_groups <- unique(df$x_group)
fit_data_base <- data.frame(x_mid = numeric(), y_median = numeric())

for (group in x_groups) {
  group_data <- df[df$x_group == group, ]
  if (nrow(group_data) == 0) next
  # 提取区间上下限
  interval_str <- gsub("\\(|\\)|\\[|\\]", "", as.character(group))
  bounds <- as.numeric(strsplit(interval_str, ",")[[1]])
  x_mid <- mean(bounds)
  y_median <- median(group_data$y, na.rm = TRUE)
  fit_data_base <- rbind(fit_data_base, data.frame(x_mid, y_median))
}

第三步:画出散点图+中位数拟合线

用ggplot2(美观易调整)

library(ggplot2)

ggplot() +
  # 画原始散点,alpha调小一点避免点重叠
  geom_point(data = df, aes(x = x, y = y), alpha = 0.6, color = "steelblue") +
  # 画中位数拟合线,用红色加粗突出
  geom_line(data = fit_data, aes(x = x_mid, y = y_median), color = "red", linewidth = 1.2) +
  labs(title = "散点图 + 自定义X区间中位数拟合线", x = "X值", y = "Y值") +
  theme_minimal()

用Base R(轻量无依赖)

plot(df$x, df$y, pch = 16, col = "steelblue", alpha = 0.6, 
     main = "散点图 + 自定义X区间中位数拟合线", 
     xlab = "X值", ylab = "Y值")
# 画拟合线
lines(fit_data$x_mid, fit_data$y_median, col = "red", lwd = 2)

这样就能得到你想要的效果:每个X区间的中点对应该区间Y的中位数,连接起来就是一条完全基于数据分布的经验拟合线,而且区间可以随便调整,完全不需要参数拟合~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:44:04