Сочетание Boxplot и Гистограммы с использованием ggplot2 - PullRequest
21 голосов
/ 29 декабря 2010

Я пытаюсь объединить гистограмму и блок-график для визуализации непрерывной переменной.Вот код, который у меня пока естьМожет кто-нибудь сказать мне, как я могу выровнять их?С другой стороны, если у кого-то есть лучший способ сделать этот график с использованием ggplot2, это также будет оценено.

Ответы [ 4 ]

18 голосов
/ 29 декабря 2010

Вы можете сделать это с помощьюordin_cartesian () и align.plots в ggExtra.

library(ggplot2)
library(ggExtra) # from R-forge

p1 <- qplot(x = 1, y = mpg, data = mtcars, xlab = "", geom = 'boxplot') + 
  coord_flip(ylim=c(10,35), wise=TRUE)
p2 <- qplot(x = mpg, data = mtcars, geom = 'histogram') + 
  coord_cartesian(xlim=c(10,35), wise=TRUE)

align.plots(p1, p2)

Вот модифицированная версия align.plot для указания относительного размера каждой панели:

align.plots2 <- function (..., vertical = TRUE, pos = NULL) 
{
    dots <- list(...)
    if (is.null(pos)) pos <- lapply(seq(dots), I)
    dots <- lapply(dots, ggplotGrob)
    ytitles <- lapply(dots, function(.g) editGrob(getGrob(.g, 
        "axis.title.y.text", grep = TRUE), vp = NULL))
    ylabels <- lapply(dots, function(.g) editGrob(getGrob(.g, 
        "axis.text.y.text", grep = TRUE), vp = NULL))
    legends <- lapply(dots, function(.g) if (!is.null(.g$children$legends)) 
        editGrob(.g$children$legends, vp = NULL)
    else ggplot2:::.zeroGrob)
    gl <- grid.layout(nrow = do.call(max,pos))
    vp <- viewport(layout = gl)
    pushViewport(vp)
    widths.left <- mapply(`+`, e1 = lapply(ytitles, grobWidth), 
        e2 = lapply(ylabels, grobWidth), SIMPLIFY = F)
    widths.right <- lapply(legends, function(g) grobWidth(g) + 
        if (is.zero(g)) 
            unit(0, "lines")
        else unit(0.5, "lines"))
    widths.left.max <- max(do.call(unit.c, widths.left))
    widths.right.max <- max(do.call(unit.c, widths.right))
    for (ii in seq_along(dots)) {
        pushViewport(viewport(layout.pos.row = pos[[ii]]))
        pushViewport(viewport(x = unit(0, "npc") + widths.left.max - 
            widths.left[[ii]], width = unit(1, "npc") - widths.left.max + 
            widths.left[[ii]] - widths.right.max + widths.right[[ii]], 
            just = "left"))
        grid.draw(dots[[ii]])
        upViewport(2)
    }
}

использование:

# 5 rows, with 1 for p1 and 2-5 for p2
align.plots2(p1, p2, pos=list(1,2:5))
# 5 rows, with 1-2 for p1 and 3-5 for p2
align.plots2(p1, p2, pos=list(1:2,3:5))

align.plots2 second example

4 голосов
/ 17 сентября 2015

Использование пакета cowplot.

library(cowplot)

#adding xlim and ylim to align axis.
p1 = qplot(x = 1, y = mpg, data = mtcars, xlab = "", geom = 'boxplot') + 
  coord_flip() +
  ylim(min(mtcars$mpg),max(mtcars$mpg))

p2 = qplot(x = mpg, data = mtcars, geom = 'histogram')+
  xlim(min(mtcars$mpg),max(mtcars$mpg))

#result
plot_grid(p1, p2, labels = c("A", "B"), align = "v",ncol = 1)

enter image description here

2 голосов
/ 20 августа 2015

Другое возможное решение с использованием ggplot2, однако, пока я не знаю, как масштабировать два графика по высоте:

require(ggplot2)
require(grid)

fig1 <- ggplot(data = mtcars, aes(x = 1, y = mpg)) +
  geom_boxplot( ) +
  coord_flip() +
  scale_y_continuous(expand = c(0,0), limit = c(10, 35))

fig2 <- ggplot(data = mtcars, aes(x = mpg)) +
  geom_histogram(binwidth = 1) +
  scale_x_continuous(expand = c(0,0), limit = c(10, 35))

grid.draw(rbind(ggplotGrob(fig1),
                ggplotGrob(fig2),
                size = "first"))

plot

0 голосов
/ 25 апреля 2018

Лучшее из известных мне решений - использование пакета ggpubr:

require(ggplot2)
require(ggpubr)
p1 = qplot(x = 1, y = mpg, data = mtcars, xlab = "", geom = 'boxplot') + 
     coord_flip()
p2 = qplot(x = mpg, data = mtcars, geom = 'histogram')
ggarrange(p2, p1, heights = c(2, 1), align = "hv", ncol = 1, nrow = 2)

enter image description here

...