Home > OS >  How do I seperate two overlapping legends for a dual axis ggplot, one legend representing variables
How do I seperate two overlapping legends for a dual axis ggplot, one legend representing variables

Time:01-10

I have the following dataframe as a reprex:

weather <- data.frame(time= c("12:19","12:15","13:20","13:22","16:19"), sensor_rh = c("A","B","C","A","A"), sensor_t = c("A","B","C","C","A"), t = c(30.4,29.4,29.4,30.3,28.9), rh = c(66.8,67.1,67.6,67.1,68.0))

I want the plot to show me two different shapes, distinguishing the rh and t variables, and three colors, distinguishing the sensors for rh and t.

I am managing to plot the points as desired in a scatterplot with a primary axis for the variable relative humidity (rh) and a secondary axis for the variable temperature (temp). However, as an example, the following code does not give me two seperate legends; one for the variables and one for the sensors.

scale <- 2
ggplot(weather, aes(x = time))  
  geom_point(aes(y = rh, color = sensor_rh), shape = 1)  
  geom_point(aes(y = t*scale, color = sensor_t), shape = 3)  
  scale_color_manual(name = "sensor", values = c("A" = "red", "B" = "blue", "C" = "green"), guide = guide_legend(title = "Sensor", title.position = "top", title.hjust = 0.5 ))  
  scale_shape_manual(name = "variable", values = c("rh" =1, "t" = 3), guide = guide_legend(title = "variable", title.position = "top", title.hjust = 0.5))  
  scale_y_continuous(name = "rh(%)", sec.axis = sec_axis(~./scale, name = "t(°C)"))   
  labs(x= "time")

scatterplot with dual axis only one (overlapping)legend

Can someone help me figure out how to plot the desired graph? I feel I have played around with the code in so many ways, with questions that seem almost duplicate to mine, but mostly I either do not get correctly plotted scatter points or I dont get a seperate legend.

It seems that the shapes are overlapping for the two variables.

I know there is controversy in the use of dual axis, but please lets not get into that discussion here.

Thank you in advance!

CodePudding user response:

Instead of setting the shape as an argument map on the shape aesthetic, i.e. inside aes(). As you already included scale_shape_manual you could use shape="rh" and shape="t" in your geom_point layers:

library(ggplot2)

scale <- 2
ggplot(weather, aes(x = time))  
  geom_point(aes(y = rh, color = sensor_rh, shape = "rh"))  
  geom_point(aes(y = t * scale, color = sensor_t, shape = "t"))  
  scale_color_manual(
    name = "sensor", values = c("A" = "red", "B" = "blue", "C" = "green"),
    guide = guide_legend(title = "Sensor", title.position = "top", title.hjust = 0.5)
  )  
  scale_shape_manual(
    name = "variable", values = c("rh" = 1, "t" = 3),
    guide = guide_legend(title = "variable", title.position = "top", title.hjust = 0.5)
  )  
  scale_y_continuous(name = "rh(%)", sec.axis = sec_axis(~ . / scale, name = "t(°C)"))  
  labs(x = "time")

  • Related