2
votes

I'm plotting two variables in the same plot, and each variable is grouped by year. My legend shows the color differentiation by year, but I can't figure out how to add linetype to the legend. Ideally there would be 4 lines in the legend: pink=2015, blue=2016, and dotted line=Var1, solid line=Var2

Here is my sample df:

year <- c(2015,2015,2015,2015,2015,2015,2015,2015,2015,2015,2015,2015,2016,2016,2016,2016,2016,2016,2016,2016,2016,2016,2016,2016)
month <-c(1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12)
Var1 <- sample(30:60, 24, rep=TRUE)
Var2 <- sample(70:90, 24, rep=TRUE)
df <- data.frame(year,month,Var1, Var2)

And plot:

plot <- ggplot(df)+
  geom_line(aes(x=as.factor(month), y=Var1, 
            group=as.factor(year), color=as.factor(year)), linetype=2, size=0.9)+
  geom_point(aes(x=as.factor(month), y=Var1, group=as.factor(year)))+
  geom_line(aes(x=as.factor(month), y=Var2, 
            group=as.factor(year), color=as.factor(year)), linetype=1, size=0.9)+
  geom_point(aes(x=as.factor(month), y=Var2, group=as.factor(year)))+
  theme_tufte()+
  theme(legend.title=element_blank())+
  labs(x=NULL,y="",title="Var1 vs. Var2")+
  scale_x_discrete(expand=c(0,0.2),
               labels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
plot

I've tried changing the aes within geom_line, as well as adding & configuring a few scale_xxx_yyyy's, including scale_linetype_manual. All unsuccessful so far. Ideally I won't have to draw my legend separately, but be able to direct it from within ggplot.

2

2 Answers

2
votes

For this we will have to change your dataset around just a bit. Firstly we will gather(from the tidyr package) your var1 and var2 together such that we have two new variable, one called var which will have values "var1" and "var2" and a variable called n that will have the values var1 and var2 had.

df <- data.frame(year,month,Var1,Var2) %>%
        gather("var", "n", 3:4)

then for each combination of of "year" X "var" we will create a segment variable that indicates which line we will draw.

  • 1 for year == 2015 & var == var1
  • 2 for year == 2016 & var == var1
  • 3 for year == 2015 & var == var2
  • 4 for year == 2016 & var == var2

done lazily like so

df$segment <- rep(1:4, each = 12)

Now the goal is then to draw the lines one by one according to segment. This will be done with the following loop

gg <- ggplot()
for (i in 1:4) gg <- gg + 
  geom_line(data = subset(df, segment == i), 
            aes(x = as.factor(month), y = n, linetype = var,
                group = as.factor(year), color = as.factor(year))) +
  geom_point(data = subset(df, segment == i), 
            aes(x = as.factor(month), y = n, group = as.factor(year)))

Notice how the difference between this and yours was that the geom_line have a subsetted dataset acording to segment (we only need the data for the line we are drawing). y = n acording to the gather we did before and now we set a new aesthetic which was our var. This is looped 4 times, same as the number of segments.

Lastly adding other themes and labs

gg <- gg + theme(legend.title = element_blank())+
    labs(x = NULL,y = "", title = "Var1 vs. Var2")+
    scale_x_discrete(expand = c(0,0.2),
                     labels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", 
                                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))
gg

and we have the result

enter image description here

1
votes
year <-   c(2015,2015,2015,2015,2015,2015,2015,2015,2015,
2015,2015,2015,2016,2016,2016,2016,2016,2016,2016,2016,2016,2016,2016,2016)
month <-c(1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12)
Var1 <- sample(30:60, 24, rep=TRUE)
Var2 <- sample(70:90, 24, rep=TRUE)
df <- data.frame(year,month,Var1, Var2)

If you modify the format of you data.frame a little bit and by using interaction to group 2 variables in ggplot2. Here you go. I'm using data.table as I don't know anymore how to tranform data.frame to long anymore.

library(data.table)
library (ggplot2)
ggplot(melt(as.data.table(df),id.vars=c("year","month")))+   
geom_line(aes(x=as.factor(month), 
y=value, group=interaction(variable,  as.factor(year)),
color=as.factor(year),linetype=variable), size=0.9) + 
labs(x = NULL,y = "", title = "Var1 vs. Var2")+
 scale_x_discrete(expand = c(0,0.2),
                  labels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", 
                            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"))

enter image description here