Search code examples
rggplot2

changing color/linestyle for a second geom_smooth


I am trying to make a plot with mulitple groups, each group fit to a linear model one type I fit to an equally weighted model, the next time I fit to a model that is weighted by the number of points in the bin.

Here is some sample simulated data:

test_data <- 
  bind_rows(
  tibble(test_x=rbeta(500,0.05,0.05),
         test_y=5*test_x+4+runif(length(test_x),0,3),
         group="group-a" ),
  tibble(test_x=rbeta(500,0.05,0.05),
         test_y=3*test_x+3+runif(length(test_x),0,3),
         group="group-b" ),
  ) |>
  mutate(test_x=floor(test_x * 20)/20 + 1/(2*20) ) |>
  group_by(test_x,group) |> summarise(n=n(),test_y=mean(test_y))

and here is how a plot the data

test_data |> ggplot(aes(x=test_x,y=test_y,group=group,color=group)) + 
  geom_point() +geom_smooth(method = lm,se=FALSE) + 
  geom_smooth(aes(weight=n),method = lm,se=FALSE)

I can add linetype="dashed" but that does not add to the legend. Can I add this to the legend? Better yet, can I set the color/style for each line and customize the legend to have group-a weighted fit, group-a unweighted fit,group-b weighted fit, group-b unweighted fit?

forgot:

sessionInfo()
R version 4.3.3 (2024-02-29)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS 15.3

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/New_York
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] dplyr_1.1.4    ggplot2_3.5.1  tibble_3.2.1   devtools_2.4.5 usethis_3.1.0 

loaded via a namespace (and not attached):
 [1] generics_0.1.3    lattice_0.22-6    digest_0.6.37     magrittr_2.0.3    grid_4.3.3       
 [6] pkgload_1.4.0     fastmap_1.2.0     Matrix_1.6-5      pkgbuild_1.4.5    sessioninfo_1.2.2
[11] urlchecker_1.0.1  promises_1.3.2    mgcv_1.9-1        purrr_1.0.2       socR_0.5.9       
[16] scales_1.3.0      cli_3.6.3         shiny_1.9.1       rlang_1.1.4       ellipsis_0.3.2   
[21] munsell_0.5.1     splines_4.3.3     remotes_2.5.0     withr_3.0.2       cachem_1.1.0     
[26] tools_4.3.3       memoise_2.0.1     colorspace_2.1-1  httpuv_1.6.15     vctrs_0.6.5      
[31] R6_2.5.1          mime_0.12         lifecycle_1.0.4   fs_1.6.5          htmlwidgets_1.6.4
[36] miniUI_0.1.1.1    pkgconfig_2.0.3   pillar_1.10.0     later_1.4.1       gtable_0.3.5     
[41] glue_1.8.0        profvis_0.4.0     Rcpp_1.0.13-1     tidyselect_1.2.1  rstudioapi_0.17.1
[46] farver_2.1.2      xtable_1.8-4      htmltools_0.5.8.1 nlme_3.1-166      labeling_0.4.3   
[51] compiler_4.3.3  

Solution

  • If you want to have a legend you have to map on aesthetics, i.e. move linetype= inside aes().

    Moreover, to achieve your preferred result, i.e. one legend with a separate entry for the groups aka color and the type of model aka linetype requires to use the interaction of both variables and to set the desired colors and linetypes using scale_xxx_manual:

    library(ggplot2)
    
    test_data |> ggplot(aes(
      x = test_x, y = test_y, group = group
    )) +
      geom_point() +
      geom_smooth(
        aes(
          color = paste(group, "unweighted fit"),
          linetype = paste(group, "unweighted fit")
        ),
        method = lm, se = FALSE
      ) +
      geom_smooth(
        aes(
          weight = n,
          color = paste(group, "weighted fit"),
          linetype = paste(group, "weighted fit")
        ),
        method = lm, se = FALSE
      ) +
      scale_color_manual(
        values = rep(scales::hue_pal()(2), each = 2),
        name = NULL
      ) +
      scale_linetype_manual(
        values = rep(c("solid", "dashed"), 2),
        name = NULL
      )
    

    enter image description here