如何在R的ggplot平滑曲线上用不同形状区分多条实线?
解决平滑曲线用不同形状区分的问题
要实现所有平滑曲线为实线,同时用不同形状标识区分分组,可基于ggplot2用以下两种方法实现:
方法一:直接用stat_smooth同时绘制实线和曲线上的形状点
无需提前拟合模型,直接在ggplot中通过stat_smooth生成平滑点,适配多数场景:
假设你的原始代码类似这样(基于分组变量映射线型):
ggplot(your_data, aes(x = x_col, y = y_col, color = group_col, linetype = group_col)) + geom_smooth(method = "loess", se = FALSE)
修改后的代码:
library(ggplot2) ggplot(your_data, aes(x = x_col, y = y_col, color = group_col, shape = group_col)) + # 强制所有曲线为实线 geom_smooth(method = "loess", se = FALSE, linetype = 1, linewidth = 1) + # 在平滑曲线上添加对应分组的形状点(点基于平滑拟合结果生成) stat_smooth(method = "loess", se = FALSE, geom = "point", size = 3) + # 自定义8种差异明显的形状,可按需调整 scale_shape_manual(values = c(1, 2, 3, 4, 16, 17, 18, 8)) + # 统一图例名称 labs(color = "分组", shape = "分组")
关键细节:
linetype = 1固定所有曲线为实线stat_smooth(geom = "point")生成的点落在平滑曲线上,而非原始数据点,完美匹配你的需求- 形状编号对应R内置样式:1=空心圆,2=空心三角,3=十字,4=叉,16=实心圆,17=实心三角,18=实心菱形,8=星形,刚好覆盖8个分组
方法二:提前提取平滑拟合值,再绘图(更灵活)
如果需要精准控制采样点数量或拟合逻辑,可先拟合模型提取拟合值,再绘制曲线和形状:
library(ggplot2) library(dplyr) # 按分组拟合平滑模型,提取50个均匀采样点的拟合值 fitted_df <- your_data %>% group_by(group_col) %>% do( model = loess(y_col ~ x_col, data = .), x_range = list(seq(min(.$x_col), max(.$x_col), length.out = 50)) ) %>% mutate(fitted_y = list(predict(model, newdata = data.frame(x_col = x_range[[1]])))) %>% unnest(c(x_range, fitted_y)) %>% rename(x_col = x_range, y_col = fitted_y) # 绘制实线+形状点 ggplot(fitted_df, aes(x = x_col, y = y_col, color = group_col, shape = group_col)) + geom_line(linetype = 1, linewidth = 1) + geom_point(size = 3) + scale_shape_manual(values = c(1, 2, 3, 4, 16, 17, 18, 8)) + labs(color = "分组", shape = "分组")
关键细节:
- 用
group_by+loess按分组拟合模型,生成50个均匀采样点,保证曲线平滑且点分布均匀 - 完全规避原始数据点干扰,仅基于平滑拟合结果绘图
通用注意事项:
- 若你使用的平滑方法不是
loess,只需将method参数替换为你实际用的方法(如lm、gam) - 可调整
size改变形状点大小,linewidth改变曲线粗细 - 形状编号可自由替换,R内置形状编号范围为0-25,选8种视觉差异大的即可
内容的提问来源于stack exchange,提问作者Subu
相关产品推荐
相关产品推荐

