ggplot2 - Как добавить уникальную легенду для нескольких графиков с помощью grid.arrange? - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть сюжет с 4 панелями внутри, сделанный из ggplot2 и grid.arrange.У каждой панели есть легенда, которая одинакова для всех них.

Как я могу удалить 4 легенды и создать уникальную на дне сюжета?

Вот мои примерные данные и график:

set.seed(100)
df_1 = data.frame(lat = rnorm(20), 
                  lon = rnorm(20), 
                  cor = c(rep('positive', 7), rep('negative', 13)), 
                  sign = c(rep(99, 5), rep(95, 6), rep(90,9)))

lst_df = list(df_1, df_1, df_1, df_1)


library(ggplot2)
library(gridExtra)
library(grid)

for (i in 1:length(lst_df)) {
p[[i]] = ggplot() +

    geom_point(data=lst_df[[i]], aes(x=lon, y=lat, size=sign, colour = cor), alpha = 0.5) +

    scale_color_manual(values=c("blue", "orange"),
                       name='col', 
                       labels = c('neg', 'pos'),
                       guide = guide_legend(override.aes = list(alpha = 1, size = 3))) +

    scale_size(range = c(1,3), 
               breaks = c(90, 95, 99),
               labels = c(1, 5, 10),
               name = 'test',
               guide = guide_legend(override.aes = list(colour = 'black', 
                                                        alpha = 1)))
}


grid.arrange(p[[1]], p[[2]], p[[3]], p[[4]], 
             ncol=2, nrow=2,
             top=textGrob(expression(bold("test")), gp=gpar(fontsize=25, face= 'bold')))

enter image description here

Есть предложения?Спасибо

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Как указала Камилла, у cowplot есть действительно простой способ сделать это. Вы также можете сделать это, вручную расположив grobs. Это особенно хорошо работает, если у вас есть графики с разной шириной, масштабами и разрывами. Один пример здесь.

Преимущество выполнения этого вручную, если только cowplot не может, заключается в том, что вы можете указать, какие графики получают метки оси x, а также заголовки / метки оси y, поэтому в итоге вы можете иметь только заголовки оси x / надписи на ваших нижних сетках и заголовки / надписи по оси Y на ваших левых сетках. Недостатком является утомительное определение нескольких функций построения графиков, если у вас есть несколько графиков.

df_plots <- lapply(lst_df, function(x) {
ggplot() +    
geom_point(data=lst_df[[i]], aes(x=lon, y=lat, size=sign, colour = cor), alpha = 0.5) +
scale_color_manual(values=c("blue", "orange"),
                   name='col', 
                   labels = c('neg', 'pos'),
                   guide = guide_legend(override.aes = list(alpha = 1, size = 3))) +
scale_size(range = c(1,3), 
           breaks = c(90, 95, 99),
           labels = c(1, 5, 10),
           name = 'test',
           guide = guide_legend(override.aes = list(colour = 'black', 
                                                    alpha = 1)))
})

df_leg <-  get_legend(df_plots[[1]]) # get legend

df_plots_noleg <- lapply(lst_df, function(x) { # make plots with no legends, however you want to do this
ggplot() +

geom_point(data=lst_df[[i]], aes(x=lon, y=lat, size=sign, colour = cor), alpha = 0.5) +

scale_color_manual(values=c("blue", "orange"),
                   name='col', 
                   labels = c('neg', 'pos'),
                   guide = guide_legend(override.aes = list(alpha = 1, size = 3))) +
theme(legend.position = "none")
})

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

#maxWidth_df_plots <- grid::unit.pmax(df_plots_noleg1$widths[2:5], df_plots_noleg2$widths[2:5], df_plots_noleg3$widths[2:5], df_plots_noleg4$widths[2:5]) #get your grob widths

#df_plots_noleg1$widths[2:5] <- as.list(maxWidth1Page1)
#df_plots_noleg2$widths[2:5] <- as.list(maxWidth1Page1)
#df_plots_noleg3$widths[2:5] <- as.list(maxWidth1Page1)
#df_plots_noleg4$widths[2:5] <- as.list(maxWidth1Page1)

df_plots1 <- ggplotGrob(df_plots_noleg[[1]])
df_plots2 <- ggplotGrob(df_plots_noleg[[2]])
df_plots3 <- ggplotGrob(df_plots_noleg[[3]])
df_plots4 <- ggplotGrob(df_plots_noleg[[4]])

df_plot_arranged <- grid.arrange(arrangeGrob(df_plots1, df_plots2, df_plots3, df_plots4, nrow = 2),
                             arrangeGrob(nullGrob(), df_leg, nullGrob(), nrow = 1), ncol = 1, heights = c(4,0.5),
                             top = textGrob("Title Text Holder Here", gp = gpar(fotsize = 12, font = 2)))

Преимущество, которое я упомянул, заключается в том, что вы можете контролировать, какие графы получают, какую маркировку. Здесь вам поможет контроль ширины, как вы можете видеть на изображении, правые графики шире левых, а верхние выше, чем нижние.

df_plots1 <- df_plots_noleg[[1]] + theme(axis.title.x = element_blank(), axis.text.x = element_blank())

df_plots2 <- df_plots_noleg[[2]] + theme(axis.title.x = element_blank(), axis.title.y = element_blank(),
                               axis.text.x = element_blank(), axis.text.y = element_blank())

df_plots4 <- df_plots_noleg[[4]] + theme(axis.title.y = element_blank(), axis.text.y = element_blank())

df_plots1 <- ggplotGrob(df_plots1)
df_plots2 <- ggplotGrob(df_plots2)
df_plots3 <- ggplotGrob(df_plots_noleg[[3]])
df_plots4 <- ggplotGrob(df_plots4)

df_plot_arranged <- grid.arrange(arrangeGrob(df_plots1, df_plots2, df_plots3, df_plots4, nrow = 2),
                             arrangeGrob(nullGrob(), df_leg, nullGrob(), nrow = 1), ncol = 1, heights = c(4,0.5),
                             top = textGrob("Title Text Holder Here", gp = gpar(fotsize = 12, font = 2)))

0 голосов
/ 11 сентября 2018

Вот рабочий процесс с cowplot, который предоставляет некоторые удобные функции для объединения гробов и извлечения таких элементов, как легенды. У них есть подробная виньетка для создания сеток сюжетов с общими легендами, которые вы ищете. Точно так же виньетка на аннотациях графика включает в себя cowplot функции для создания и добавления меток - они функционируют так же, как и другие элементы графика, и могут использоваться в cowplot::plot_grid.

Процесс в основном

  1. Создание списка сюжетов без легенд с использованием lapply (вместо этого может быть цикл)
  2. Извлечение одной из легенд - не имеет значения, какая из них одна и та же - она ​​установлена ​​в нижней части
  3. Создание текстового гроба для заголовка
  4. Создание сетки из списка легендарных сюжетов
  5. Создание сетки из заголовка, сетки легендарных сюжетов и легенды

Кроме того, загрузка cowplot позволяет ему установить тему по умолчанию ggplot, которая мне не особенно нравится, поэтому я использую обозначение cowplot::function вместо library(cowplot).

Вы можете настроить относительную высоту, используемую для создания окончательной сетки - это было первое соотношение, которое мне помогло.

Если это произойдет, я отправил вопрос несколько месяцев назад о том, как заставить draw_label гроб руководствоваться темами, как вы ожидаете от обычных ggplot элементов, таких как заголовки; ответы от автора пакета и моя специальность: здесь .

library(ggplot2)
...

p_no_legend <- lapply(p, function(x) x + theme(legend.position = "none"))
legend <- cowplot::get_legend(p[[1]] + theme(legend.position = "bottom"))

title <- cowplot::ggdraw() + cowplot::draw_label("test", fontface = "bold")

p_grid <- cowplot::plot_grid(plotlist = p_no_legend, ncol = 2)
cowplot::plot_grid(title, p_grid, legend, ncol = 1, rel_heights = c(0.1, 1, 0.2))

Создано в 2018-09-11 пакетом Представ (v0.2.0).

...