Search code examples
rggplot2lag

Connecting points of a shifted plot with another plot using ggplot in R


I have two dataframes df1 and df2 as follows:

> df1
  dateTime value
1        1     6
2        2     2
3        3     3
4        4     1

> df2
  dateTime value
1        1     3
2        2     8
3        3     4
4        4     5

I want to plot these dataframes in just one diagram, split them to two different plots with same x axis, shift df1 by 1 to the right, and connect each value of df1 to the corresponding value of df2. Here is my code:

#Shift df1 by 1 to the right
df1$value <- lag(df1$value, 1)

plot1 <- df1 %>%
  select(dateTime, value) %>%
  ggplot(aes(dateTime, value)) +
  geom_point() +
  geom_line(color = "green") +
  geom_segment(aes(xend = dateTime, yend = -Inf), linetype = "dashed") +
  theme(axis.text=element_text(size = 14), axis.title=element_text(size = 14),
        axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank())

plot2 <- df2 %>%
  select(dateTime, value) %>%
  ggplot(aes(dateTime, value)) +
  geom_point() +
  geom_line(color = "red") +
  geom_segment(aes(xend = dateTime, yend = Inf), linetype = "dashed") +
  xlab("dateTime") +
  theme(axis.text=element_text(size = 14), axis.title=element_text(size = 14))

gt <- rbind(ggplotGrob(plot1), ggplotGrob(plot2), size = "last")

# Panel positioning
is_panel <- which(gt$layout$name == "panel")
panel_x <- unique(gt$layout$l[is_panel])
panel_y <- gt$layout$t[is_panel]

# Coordinates and graphical parameters for segments
x_coords <- gt$grobs[[is_panel[1]]]$children[[5]]$x0
gpar <- gt$grobs[[is_panel[1]]]$children[[5]]$gp

linkgrob <- segmentsGrob(x0 = x_coords, y0 = 0, x1 = x_coords, y1 = 1, gp = gpar)
gt <- gtable_add_grob(gt, linkgrob,
                      t = panel_y[1] + 1, l = panel_x, b = panel_y[2] - 1)
grid.newpage()
grid.draw(gt)

Here is the result, but actually there is an additional line which I want to remove it and also there is no point for the last value of df1 which I also want to show the last point:

enter image description here


Solution

  • Lag

    I guess that lag is maybe the wrong function:

    lag(1:3)
    # [1] NA 1 2 
    

    If I understand you correctly, you want to shift your data and this depends on your real data, but for this dummy example something like

    df1 <- df1 %>%
       mutate(dateTime = dateTime + 1)
    

    should do the trick.

    Lines

    You need to adapt your base plots a bit:

    plot1 <- df1 %>%
      select(dateTime, value) %>%
      ## create a temp variable to which we can map the line type to
      mutate(lty = ifelse(dateTime == max(dateTime), "none", "dashed")) %>% 
      ggplot(aes(dateTime, value)) +
      geom_point() +
      geom_line(color = "green") +
      ## map the linetype to this variable
      geom_segment(aes(xend = dateTime, yend = -Inf, linetype = lty)) +
      ## use a manual scale to map the variable to dashed and blank linetype
      scale_linetype_manual(values = c(dashed = "dashed", none = "blank"),
                            guide = "none") + 
      ## add xlim to align scales properly in both plots
      xlim(c(1, 5)) +
      theme(axis.text=element_text(size = 14), axis.title=element_text(size = 14),
            axis.title.x=element_blank(),
            axis.text.x=element_blank(),
            axis.ticks.x=element_blank())
    
    plot2 <- df2 %>%
      select(dateTime, value) %>%
      mutate(lty = ifelse(dateTime == min(dateTime), "none", "dashed")) %>%
      ggplot(aes(dateTime, value)) +
      geom_point() +
      geom_line(color = "red") +
      geom_segment(aes(xend = dateTime, yend = Inf, linetype = lty)) +
      scale_linetype_manual(values = c(dashed = "dashed", none = "blank"),
                            guide = "none") + 
      xlab("dateTime") +
      xlim(c(1, 5)) +
      theme(axis.text=element_text(size = 14), axis.title=element_text(size = 14))
    

    This gives you this plot:

    Linechart