0

I want to create a customized legend that distinguishes two plotted geoms using appropriate shape and color. I see that guide_legend() should be involved, but my legend is presented with both shapes overlayed one on the other for both components of the legend. What is the right way to build these individual legend components using distinct shapes and colors? Thank you.

RStudio output

library(dplyr)

df <- tibble(year=seq(2010,2020,1), 
         annualNitrogen=seq(100,200,10),
         annualPotassium=seq(500,600,10))

ggplot() +  

geom_point(data = df, aes(x = year, y = annualNitrogen, fill="green"), shape=24, color="green", size = 4) +
geom_point(data = df, aes(x = year, y = annualPotassium, fill="blue"), color="blue", shape=21, size = 4) +

guides(fill = guide_legend(override.aes = list(color=c("green", "blue"))), 
    shape = guide_legend(override.aes = list(shape=c(21, 24)))
    ) +

scale_fill_manual(name = 'cumulative\nmaterial', 
     values = c("blue"="blue" , "green"="green" ), 
     labels = c("potassium" , "nitrogen") ) +

theme_bw() +
theme(legend.position="bottom") 
Cord
  • 196
  • 11

2 Answers2

1

Here it helps to transform to "long" format which is more in line with how ggplot is designed to be used when separating factor levels within a single time series.

This allows us to map shape and color directly, rather than having to manually assign different values to multiple plotted series, like you do in your question.

library(tidyverse)

df %>% 
  pivot_longer(-year, names_to = "element") %>% 
  ggplot(aes(x=year, y = value, fill = element, shape = element, color = element)) + 
  geom_point(size = 4)+
  scale_color_manual(values = c("green", "blue"))

enter image description here

Mako212
  • 6,787
  • 1
  • 18
  • 37
  • 1
    One minor point, ```gather``` is depreciated and replaced with ```pivot_longer```, something like ```pivot_longer(-year, names_to = "element")``` – Greg Dec 04 '19 at 21:27
  • @Greg Thanks, wasn't aware of that change, I appreciate it! Updated. – Mako212 Dec 04 '19 at 21:29
  • thank you for your insight; however, I'm trying to distinguish between multiple geoms (which ultimately will be loaded by different data sources). – Cord Dec 05 '19 at 02:24
  • @user1405141 why not combine the data sources into a single data frame for the chart? – Mako212 Dec 05 '19 at 06:00
  • thanks, that's certainly an option but I'm trying to focus on the capability of ggplot2. – Cord Dec 05 '19 at 15:19
  • @user1405141[This question](https://stackoverflow.com/questions/18394391/r-custom-legend-for-multiple-layer-ggplot) shows one way to do it, but you will have trouble merging the shape and color legends into a single one, hence my initial recommendation to combine the data sets. – Mako212 Dec 05 '19 at 18:34
  • yes, I have studied that one. I'm interpreting your comments as "it can't be done". Thank you very much. – Cord Dec 06 '19 at 15:08
1

Put your df into a long format that ggplot likes with tidyr::gather. You should only use one geom_point for this, you don't need separate geoms for separate variables. You can then specify the shape and variable in one call to geom_point.

df <- tibble(year=seq(2010,2020,1), 
         annualNitrogen=seq(100,200,10),
         annualPotassium=seq(500,600,10))


df <- tidyr::gather(df, key = 'variable', value='value', annualNitrogen, annualPotassium)

ggplot(df) +
    geom_point(aes(x = year, y = value, shape = variable, color = variable)) +
    scale_color_manual(
        name = 'cumulative\nmaterial', 
        values = c(
            "annualPotassium" = "blue",
            "annualNitrogen" = "green"), 
        labels = c("potassium" , "nitrogen")) +
    guides(shape = FALSE)

answer

heds1
  • 3,203
  • 2
  • 17
  • 32