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

使用stat_smooth时按组指定特定线型的方法

问题

我有两组时间序列数据,想用stat_smooth绘制线性拟合回归线,要求一组为实线,另一组为虚线。尝试了几种方法,但要么线型分配给了错误的组,要么出现多余的图例,求正确实现方式。

测试代码如下:

library(tidyverse) 

# 示例时间序列数据
set.seed(222)

df <- data.frame(
  date = rep(seq(as.Date('2024-04-01'),
                 as.Date('2024-04-05'),
                 '1 day'), times = 2),
  group = c('a','a','a','a','a',
            'z','z','z','z','z'),
  value = rnorm(10, 1, 2)
)

# 图1:两组拟合线线型相同
df %>%
  ggplot(aes(x = date, y = value, group = group)) +
  geom_line(aes(col = group)) +
  geom_point(aes(col = group), shape = 16) +
  stat_smooth(method = 'lm', se = F, color = 'black') +
  theme_bw()
#> `geom_smooth()` using formula = 'y ~ x'
# 图2:线型改变但分配给了错误的组
df %>%
  ggplot(aes(x = date, y = value, group = group, linetype = group)) +
  geom_line(aes(col = group), linetype = 'solid') +
  geom_point(aes(col = group), shape = 16) +
  stat_smooth(method = 'lm', se = F, color = 'black') +
  theme_bw()
#> `geom_smooth()` using formula = 'y ~ x'
# 图3:线型分配正确但出现第二个图例
df %>%
  ggplot(aes(x = date, y = value, group = group, linetype = fct_rev(group))) + # 用rev()也会出现同样问题
  geom_line(aes(col = group), linetype = 'solid') +
  geom_point(aes(col = group), shape = 16) +
  stat_smooth(method = 'lm', se = F, color = 'black') +
  theme_bw()
#> `geom_smooth()` using formula = 'y ~ x'
解决方案

方法1:精准控制拟合线的线型

只给stat_smooth单独映射linetype,手动指定每组对应的线型,同时让原始折线保持实线,避免生成多余图例:

df %>%
  ggplot(aes(x = date, y = value, group = group)) +
  geom_line(aes(col = group), linetype = "solid") + # 原始折线固定为实线
  geom_point(aes(col = group), shape = 16) +
  stat_smooth(aes(linetype = group), method = "lm", se = F, color = "black") + # 给拟合线映射线型
  scale_linetype_manual(values = c("a" = "solid", "z" = "dashed")) + # 按需设置每组拟合线的线型
  theme_bw()

方法2:合并颜色与线型图例

如果希望把颜色和线型的图例合并成一个(让图例同时显示颜色和对应拟合线的线型),可以在全局aes里同时映射col和linetype到group,然后覆盖原始折线的线型为实线,最后统一图例样式:

df %>%
  ggplot(aes(x = date, y = value, group = group, col = group, linetype = group)) +
  geom_line(linetype = "solid") + # 覆盖全局线型,让原始折线都是实线
  geom_point(shape = 16) +
  stat_smooth(method = "lm", se = F, color = "black") +
  scale_linetype_manual(values = c("a" = "solid", "z" = "dashed")) +
  # 手动设置图例的样式,匹配颜色和线型
  guides(linetype = guide_legend(override.aes = list(
    linetype = c("solid", "dashed"),
    color = scales::hue_pal()(2) # 自动匹配ggplot默认的颜色
  ))) +
  theme_bw()

之前方法的问题分析

  • 图1:没有给stat_smooth映射linetype,两组拟合线默认都是实线。
  • 图2:全局aes里映射了linetype,但geom_line手动设置linetype='solid'覆盖了这个映射,导致stat_smooth的线型对应关系混乱。
  • 图3:用fct_rev(group)反转了线型映射,但全局aes的linetype会生成独立图例,而geom_line的实线设置未关联该图例,因此出现两个图例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 00:43:18