Home > Net >  Can I use shape for more one variable in ggplot?
Can I use shape for more one variable in ggplot?

Time:10-13

I am trying to create a graph using the below code. I currently use year as a shape, but I have another variable I would also like to display, position, which has two levels. I would like to differentiate between Upper and Lower position within years, ideally by having either Upper or Lower as hollow or filled shapes, depending on their respective year, and I would like this to be in the same colour as the stream. I thought about using different pch shapes for filled and unfilled but I'm really struggling to work out how I can set this to vary by colour across the different years? If it's possible, I'd additionally like the error bars inside the shape to be hidden and only visible externally. Really appreciate any help!

rep <- structure(list(stream = c("Rannoch", "Rannoch", "Vaich", "Vaich", 
"Rannoch", "Rannoch", "Vaich", "Vaich", "Blackwater", "Blackwater", 
"Rannoch", "Rannoch", "Vaich", "Vaich", "Rannoch", "Rannoch", 
"Vaich", "Vaich", "Blackwater", "Blackwater"), position = c("Upper ", 
"Lower", "Upper ", "Lower", "Upper ", "Lower", "Upper ", "Lower", 
"Upper ", "Lower", "Upper ", "Lower", "Upper ", "Lower", "Upper ", 
"Lower", "Upper ", "Lower", "Upper ", "Lower"), year = c("2020", 
"2020", "2020", "2020", "2021", "2021", "2021", "2021", "2021", 
"2021", "2020", "2020", "2020", "2020", "2021", "2021", "2021", 
"2021", "2021", "2021"), deg_hour_23 = c(197, 25, 6, 92, 24, 
123, 0, 15, 23.7, 29, 197, 25, 0, 92, 24, 123, 3, 15, 23.7, 29
), density = c(14L, 19L, 32L, 7L, 9L, 24L, 40L, 14L, 16L, 2L, 
16L, 17L, 28L, 9L, 15L, 20L, 36L, 18L, 12L, 6L), sample = c("A", 
"A", "A", "A", "B", "B", "B", "B", "B", "B", "C", "C", "C", "C", 
"D", "D", "D", "D", "D", "D")), row.names = c(NA, -20L), class = "data.frame")
rep$year <- as.character(rep$year)
rep %>%
  ggplot(aes(x= deg_hour_23, y= density, col=stream, shape=year)) 
  stat_summary(fun.y=mean, geom="point", size=4)   
  scale_shape_manual(values = c(19, 17), name="Year:", labels = c("2020", "2021"))    
  scale_color_manual(values= c("#AD9300", "#1566AD", "#FF677B"), name="Stream:", labels = c("Blackwater", "Rannoch", "Vaich")) 
  stat_summary(fun.data = mean_se, geom = "errorbar", linetype=1, width = 2.5) 
  theme(legend.title = element_text(size=20), legend.text=element_text(size=20)) 
  labs(x="Degree hours exceeding 23ºC", y= expression(Ln(fry~density)~(g/m^{"2"}))) 
  theme_classic(base_size = 25) 
  scale_x_continuous(breaks = seq(0, 200, by = 25)) 
  theme(legend.position="bottom", legend.margin=margin())

Existing plot

CodePudding user response:

From a technical point of view you can add yet another aesthetic to differentiate years like so:

rep %>%
  ggplot(aes(x = deg_hour_23, y= density, col = stream,
             shape = paste(stream, year))
        )  
    scale_shape_manual(values = c(15,2,17,1,16))  
  ## rest of plot instructions

However, if you want to demonstrate how fry density varies with temperature, your audience might already have a hard time to digest the visual overload of the existing plot version. (Let alone displaying standard deviations inferred from 2 observations each.)

You might, instead, make comparison easier by splitting your data into small multiples, i.e. one subplot for each distinct stream × year combination:

rep %>%
    ggplot()  
    geom_point(aes(deg_hour_23, density))  
    facet_wrap(stream ~ year, scales = 'free')
    ## polish as desired

... which shows at one glance that fry density decreases with temperature except in Rannoch 2021 (why?).

  • Related