将两个ggplots转换成一个

时间:2018-12-29 04:56:03

标签: r dataframe ggplot2 plot

我面临一个问题,要用一个图而不是两个来自单独数据框的图。我在下面解释了这种情况。数据帧如下:

df1 <- structure(list(value = c(9921L, 21583L, 11822L, 1054L, 13832L, 
16238L, 13838L, 20801L, 20204L, 13881L, 19935L, 13829L, 14012L, 
20654L, 13862L, 21191L, 3777L, 15552L, 13817L, 20428L, 16850L, 
21003L, 11072L, 22477L, 12321L, 12856L, 16295L, 11431L, 13469L, 
14680L, 10552L, 15272L, 9132L, 9374L, 15123L, 22754L, 10363L, 
12160L, 13729L, 11151L, 11451L, 11272L, 14900L, 14688L, 17133L, 
7315L, 7268L, 6262L, 72769L, 7650L, 16389L, 13027L, 7134L, 6465L, 
6490L, 15183L, 7201L, 14070L, 11210L, 10146L), limit = structure(c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("1Mbit", 
"5Mbit", "10Mbit"), class = "factor")), class = "data.frame", row.names = c(NA, 
-60L))

df2 <- structure(list(value = c(37262L, 39881L, 30914L, 32976L, 28657L, 
39364L, 39915L, 30115L, 29326L, 36199L, 37976L, 36694L, 33718L, 
36945L, 33182L, 35866L, 34188L, 33426L, 32804L, 34986L, 29355L, 
30470L, 37420L, 26465L, 28975L, 29144L, 27491L, 30507L, 27146L, 
26257L, 31231L, 30521L, 30370L, 31683L, 33774L, 35654L, 34172L, 
38554L, 38030L, 33439L, 34817L, 31278L, 33579L, 31175L, 31001L, 
29908L, 31658L, 33381L, 28709L, 34794L, 34154L, 30157L, 33362L, 
30363L, 31097L, 29116L, 27703L, 31229L, 30196L, 30077L), limit = structure(c(3L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("180ms", 
"190ms", "200ms"), class = "factor")), class = "data.frame", row.names = c(NA, 
-60L))

从上面的数据框中,我有这些图:

limit_bw <- factor(df1$limit, levels = c("1Mbit", "5Mbit", "10Mbit"))
limit_lt <- factor(df2$limit, levels = c("200ms", "190ms", "180ms"))

(按顺序使用它们)

bw_line <- ggplot(df1, aes(x = limit_bw, y = value, group=1)) + geom_quantile(method = "loess")
lt_line <- ggplot(df2, aes(x = limit_lt, y = value, group=1)) + geom_quantile(method = "loess")

(我实际上有很多数据,所以我使用了geom_quantile()

还有使用rbind/cbind (现在不想要)的网格中的两个图:

grid.draw(rbind(ggplotGrob(ggplot(df1, aes(limit_bw,value,group=1)) + geom_quantile(method = "loess") + labs(title = "value vs bw",x="bandwidth",y="value")),
ggplotGrob(ggplot(df2, aes(limit_lt, value, group = 1)) + geom_quantile(method="loess") + labs(title="value vs latency", x="latency", y="value")), size = "last"))

我正在寻求您的帮助,以将它们合并成一个图(在同一图中将bw_linelt_line放在一起),在顶部显示两个x轴底部或底部的两个轴提及其标题。请注意,value对于每个数据集都有不同的范围。但是,我需要为每个数据帧分别显示两个y轴,或者分别为一个y轴,以显示两个数据帧中的所有值(从最小到最大)。

我实际上从@RichieCotton看到了一个非常接近的解决方案here,但是由于我有一些factors而不是整数值,因此无法弄清楚我的数据。

非常感谢您的帮助。谢谢。

2 个答案:

答案 0 :(得分:5)

我认为将数据首先组合到一个数据帧中可能是最简单的方法。在这里,我将合并x值,并将您的数据映射到这些值。然后我们像往常一样绘制地图,并添加第二个y轴。

library(tidyverse); library(forcats)

# Create shared x axis and combine data frames
limit_combo <- data.frame(level_num = 1:3, 
                          level = as_factor(c("1Mbit\n200ms",
                                              "5Mbit\n190ms",
                                              "10Mbit\n180ms"))) 
df1b <- df1 %>%
  mutate(level_num = limit %>% as.numeric) %>%
  left_join(limit_combo)
df2b <- df2 %>%
  mutate(level_num = 4 - (limit %>% as.numeric)) %>%
  left_join(limit_combo)
df3 <- bind_rows(df1b, df2b, .id = "plot") %>%
  mutate(plot = if_else(plot == "1", "bw", "lt"))

# plot with adjusted y values and second axis for reference
ggplot(df3, aes(x = level, 
                y = value * if_else(plot == "lt", 0.44, 1), 
                group=plot, color = plot)) + 
  geom_quantile(method = "loess") +
  scale_y_continuous("value", sec.axis = sec_axis(~./0.44)) +
  theme(axis.text.y.left  = element_text(color = "#F8766D"),
        axis.text.y.right = element_text(color = "#00BFC4"))

enter image description here

答案 1 :(得分:3)

这是从两个数据集创建单个图的一种不同方法,该方法避免将两个数据集合并为一个并处理limit的因素。按照OP的规定使用df1df2limit_bwlimit_lt

该图分为三个步骤进行细化。

1。共同的x轴,共同的y比例

library(ggplot2)
ggplot() + aes(y = value) +
  geom_quantile(aes(x = as.integer(limit_bw), colour = "bw"), df1, method = "loess") + 
  geom_quantile(aes(x = as.integer(limit_lt), colour = "lt"), df2, method = "loess") +
  scale_x_continuous("limit",
    breaks = 1:nlevels(limit_bw), 
    labels = paste(levels(limit_bw), levels(limit_lt), sep = "\n")) +
  scale_colour_discrete(NULL)

enter image description here

2。分开的x轴,共同的y比例

library(ggplot2)
ggplot() + aes(y = value) +
  geom_quantile(aes(x = as.integer(limit_bw), colour = "bw"), df1, method = "loess") + 
  geom_quantile(aes(x = as.integer(limit_lt), colour = "lt"), df2, method = "loess") +
  scale_x_continuous("limit",
                     breaks = 1:nlevels(limit_bw), 
                     labels = levels(limit_bw), 
                     sec.axis = dup_axis(labels = levels(limit_lt))) +
  scale_colour_manual(NULL, values = c(bw = "blue", lt = "red")) +
  theme(axis.text.x.bottom = element_text(color = "blue"),
        axis.text.x.top    = element_text(color = "red"))

enter image description here

3。 x轴分开,y轴分开

此处,缩放第二个数据集的y值,以使两个数据集的最小值和最大值一致。

# compute scaling factor and offset
library(magrittr)   # used to improve readability
bw_rng <- loess(df1$value ~ as.integer(limit_bw)) %>% fitted() %>% range()
lt_rng <- loess(df2$value ~ as.integer(limit_lt)) %>% fitted() %>% range()
scl <- diff(bw_rng) / diff(lt_rng)
ofs <- bw_rng[1] - scl * lt_rng[1]
library(ggplot2)
ggplot() +
  geom_quantile(aes(x = as.integer(limit_bw), y = value, colour = "bw"), 
                df1, method = "loess") + 
  geom_quantile(aes(x = as.integer(limit_lt), y = scl * value + ofs, colour = "lt"), 
                df2, method = "loess") +
  scale_x_continuous("limit",
                     breaks = 1:nlevels(limit_bw), 
                     labels = levels(limit_bw), 
                     sec.axis = dup_axis(labels = levels(limit_lt))) +
  scale_y_continuous(sec.axis = sec_axis(~ (. - ofs) / scl)) +
  scale_colour_manual(NULL, values = c(bw = "blue", lt = "red")) +
  theme(axis.text.x.bottom = element_text(color = "blue"),
        axis.text.x.top    = element_text(color = "red"),
        axis.text.y.left   = element_text(color = "blue"),
        axis.text.y.right  = element_text(color = "red"))

enter image description here