简体   繁体   中英

How to connect points of two different plots to each other 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, and connect each value of df1 to the corresponding value of df2 . Actually, here is the diagram which I want:

产量

The code which I wrote to try to get the above diagram is:

library(grid)
library(dplyr)

plot1 <- df1 %>%
  select(dateTime, value) %>%
  na.omit() %>%
  ggplot() +
  geom_point(data = df1, aes(dateTime, value)) +
  geom_line(data = df1, aes(x = dateTime, y = value), color = 'green') +
  geom_segment(data = setNames(cbind(df1, df2), c("x1", "y1", "x2", "y2")),
                aes(x = x1, y = y1, xend = x2, yend = y2), 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) %>%
  na.omit() %>%
  ggplot() +
  geom_point(data = df2, aes(dateTime, value)) + 
  geom_line(data = df2, aes(x = dateTime, y = value), color = 'red') +
  geom_segment(data = setNames(cbind(df1, df2), c("x1", "y1", "x2", "y2")),
                aes(x = x1, y = y1, xend = x2, yend = y2), linetype = "dashed") +
  xlab("dateTime") +
  theme(axis.text=element_text(size = 14), axis.title=element_text(size = 14))

grid.newpage()
grid.draw(rbind(ggplotGrob(plot1), ggplotGrob(plot2), size = "last"))

But the result is:

OUTPUT2

I have a slightly hacky solution to your problem using gtable. First, we'll make the plots similar to how you made them. The thing I've changed is to specify common mappings inside the ggplot() call. Next, in geom_segment() I've set the yend to -Inf and Inf in the segments for the plots respectively.

plot1 <- df1 %>%
  select(dateTime, value) %>%
  na.omit() %>%
  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) %>%
  na.omit() %>%
  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))

At this point we convert the combined grobs to a gtable:

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

From this gtable, we look up the values that we need to place an extra graphical object in between the plotting panels. I'd recommend not blindly trusting that your panel grobs are in gt$grobs[[6]] and that the segments arent in gt$grobs[[6]]$children[[5]] . Look through the data structure yourself and confirm where these elements are in your gtable.

# 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

Now, we're going to make a new grob that mimicks the x-positions of the segments but span the entire viewport. We'll add this to the gtable.

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)

And in my hands, that yielded the following plot:

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM