1

I want to plot two lines with the same x-axis but different y-axis.

Reading the conversation here geom_bar + geom_line: with different y-axis scale? I have created the following code in order to plot visit_time and item_bought on the same graph. I have managed to create the secondary axis on the right, however I am not able to add color legend and the y-axis labels (the one one the left works, but not on the right)

temp <- data.frame
(day = c("2017-01-01",  "2017-01-02", "2017-01-03", "2017-01-04", "2017-01-05", "2017-01-06" ,"2017-01-07" ,"2017-01-08", "2017-01-09", "2017-01-10", "2017-01-11", "2017-01-12", "2017-01-13", "2017-01-14", "2017-01-15", "2017-01-16", "2017-01-17", "2017-01-18", "2017-01-19", "2017-01-20", "2017-01-21", "2017-01-22", "2017-01-23"),
                  items =c(33,34,12,31,26,45,15,20,30,44,31,48,18,4,12,38,1,3,3,1,6,7,20),
                  visit_time =c(2,  1,  11, 12, 16, 20, 10, 6,  19, 22, 18, 22, 15, 1,  9,  23, 2,  4,  5,  2,  12, 4,  22))
temp$day <- as.Date(temp$day, "%Y-%m-%d")

                p1 = ggplot(temp, aes(day, items)) + geom_line(colour="darkblue", size = 1) +
                  ylab("items") +
                  theme(legend.position="none",axis.text.x = element_text(angle = 90, hjust = 0), 
                        panel.background = element_rect(fill = NA), 
                        panel.grid = element_blank())

                p2 = ggplot(temp, aes(day, visit_time)) + geom_line(colour="darkorange3", size =1) +  ylab("visit_time") +
                  theme(legend.position="none",axis.text.x = element_text(angle = 90, hjust = 0), 
                        panel.background = element_rect(fill = NA), 
                        panel.grid = element_blank())

                g1 <- ggplot_gtable(ggplot_build(p1))
                g2 <- ggplot_gtable(ggplot_build(p2))

                # overlap the panel of 2nd plot on that of 1st plot
                pp <- c(subset(g1$layout, name == "panel", se = t:r))
                g <- gtable_add_grob(g1, g2$grobs[[which(g2$layout$name == "panel")]], pp$t, 
                                     pp$l, pp$b, pp$l)

                # axis tweaks
                ia <- which(g2$layout$name == "axis-l")
                ga <- g2$grobs[[ia]]
                ax <- ga$children[[2]]
                ax$widths <- rev(ax$widths)
                ax$grobs <- rev(ax$grobs)
                ax$grobs[[1]]$x <- ax$grobs[[1]]$x - unit(1, "npc") + unit(0.15, "cm")
                g <- gtable_add_cols(g, g2$widths[g2$layout[ia, ]$l], length(g$widths) - 1)
                g <- gtable_add_grob(g, ax, pp$t, length(g$widths) - 1, pp$b)

                # draw it
                grid.draw(g)

I am not sure this is the most efficient way, so I am happy to have another methodology. As long as I have two lines and clear y-axis names on both side and color legend.

Many thanks in advance.

Community
  • 1
  • 1
Elly
  • 129
  • 2
  • 12
  • 2
    [This is the canonical question](https://stackoverflow.com/questions/3099219/plot-with-2-y-axes-one-y-axis-on-the-left-and-another-y-axis-on-the-right). The short answer is that you can't easily because Hadley thinks it's a bad idea, as he explains in his answer there. He has since made it possible for conversions, though, e.g. Celcius and Fahrenheit. It can, as you found, be hacked through grid, but it takes some work. – alistaire May 12 '17 at 16:04

1 Answers1

4
dat <- temp %>% gather(y, val, items:visit_time)

ggplot(dat, aes(day, val, colour=y)) + 
    geom_line(data=dat %>% filter(y=="items")) + 
    geom_line(data=dat %>% filter(y=="visit_time"), aes(y=val*2)) + 
    scale_y_continuous(sec.axis= sec_axis(~./2, name="visit_time"))

enter image description here

Add a scale_colour_manual to adjust the colour if you find the default too displeasing.

scale_colour_manual(values = c("darkblue", "darkorange3"))
Adam Quek
  • 6,973
  • 1
  • 17
  • 23