Горизонтальное выравнивание стержней и граней

У меня есть два data.frames

df1 <- 
  data.frame(unit = factor(1:20, levels = 20:1),
             value = sample(1:10, 20, replace = T))

df2 <- 
  data.frame(unit = 
               factor(as.vector(sapply(1:20, FUN = function(x) rep(x, 10))).
                      levels = 1:20),
             time = rep(1:10, 20), 
             value = sample(1:100, 10*20, replace = T))

Который я хочу построить бок о бок следующим образом:

library(ggplot2)
library(cowplot)
plot_grid(ggplot(df1, aes(x=value,y=unit)) +
            geom_bar(stat = 'identity') +
            scale_x_continuous(position = "top"),
          ggplot(df2, aes(x=time,y=value)) +
                   geom_line() +
                   facet_grid(rows = vars(unit), scales = "free_y") +
            scale_x_continuous(position = "top") +
            theme(axis.text.y = element_text(size=6)),
          ncol = 2)

что приводит к этому выводу

введите здесь описание изображения

Тем не менее строки из двух графиков, отображающие переменные из одного и того же unit, не идеально выровнены:

введите здесь описание изображения

Как проще всего выровнять их программно (чтобы тоже работало с другим количеством units)? Решение не обязательно должно включать пакет cowplot.


person CptNemo    schedule 02.08.2020    source источник


Ответы (2)


Простое решение для достижения этого — использование фасетов и для гистограммы. Пока расстояние между панелями одинаково на обоих графиках, это должно гарантировать, что столбцы и линейные графики для каждой группы выровнены. Попробуй это:

df1 <- 
  data.frame(unit = factor(1:20, levels = 20:1),
             value = sample(1:10, 20, replace = T))

df2 <- 
  data.frame(unit = factor(as.vector(sapply(1:20, FUN = function(x) rep(x, 10))), levels = 1:20),
             time = rep(1:10, 20), 
             value = sample(1:100, 10*20, replace = T))

library(ggplot2)
library(cowplot)

plot_grid(ggplot(df1, aes(x=value,y=unit)) +
            geom_bar(stat = 'identity') +
            facet_grid(rows = vars(unit), scales = "free_y") +
            scale_x_continuous(position = "top") +
            theme(panel.spacing.y = unit(1, "pt"), strip.text = element_blank()),
          ggplot(df2, aes(x=time,y=value)) +
            geom_line() +
            facet_grid(rows = vars(unit), scales = "free_y") +
            scale_x_continuous(position = "top") +
            theme(axis.text.y = element_text(size=6), panel.spacing.y = unit(1, "pt")),
          ncol = 2)

person stefan    schedule 02.08.2020

Если мы посмотрим на то, как выровнены графики, становится ясно, что для того, чтобы столбцы соответствовали соответствующим граням, мы должны избавиться от пробелов на обоих концах оси y столбцов. Мы можем сделать это с помощью scale_y_discrete(expand = c(0, 0)). Мы также можем масштабировать ширину полос так, чтобы она равнялась пропорции, которую каждая из фасетных панелей занимает в отведенных им окнах просмотра. К сожалению, это несколько зависит от размеров устройства. Тем не менее, ширина 0,8 или 0,9 поможет вам довольно близко.

plot_grid(ggplot(df1, aes(x=value,y=unit)) +
            geom_bar(stat = 'identity', width = 0.8) +
            scale_x_continuous(position = "top") +
            scale_y_discrete(expand = c(0, 0)),
          ggplot(df2, aes(x=time,y=value)) +
                   geom_line() +
                   facet_grid(rows = vars(unit), scales = "free_y") +
            scale_x_continuous(position = "top") +
            theme(axis.text.y = element_text(size=6)),
          ncol = 2) 

введите здесь описание изображения

person Allan Cameron    schedule 02.08.2020