ggplot2 - настроить двухфакторную легенду - PullRequest
0 голосов
/ 11 мая 2018

Я использую ggplot2 для построения ежемесячных вертикальных профилей влажности почвы на двух участках, как для наблюдаемых, так и для смоделированных данных.

Я использую interaction, чтобы добавить цвета к обоим факторам (month и type).Я также создаю две разные ручные цветовые палитры с нужными мне цветами.Вот как воспроизвести сюжет:

library(ggplot2)

df1<- structure(list(site = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 
10L, 10L, 10L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 10L, 10L, 10L, 10L, 
10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 
10L, 10L, 10L, 10L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 10L, 10L, 10L, 
10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 
10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 
10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 
10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 
10L, 10L, 10L, 10L, 10L), .Label = c("IL_Shabbona_5_NNE", "ME_Limestone_4_NNW", 
"ME_Old_Town_2_W", "MI_Chatham_1_SE", "MI_Gaylord_9_SSW", "MN_Goodridge_12_NNW", 
"MN_Sandstone_6_W", "NY_Ithaca_13_E", "NY_Millbrook_3_W", "WI_Necedah_5_WNW"
), class = "factor"), month = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 
9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 
3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 
6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 
9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 
3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 
6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 
9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 
3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 
6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 
9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 
3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 
6L, 7L, 8L, 9L, 10L, 11L, 12L), depth = c(5, 5, 5, 5, 5, 5, 5, 
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 10, 
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 
10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 50, 50, 50, 
50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 
50, 50, 50, 50, 50, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 
100, 100, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 
10, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 20, 20, 20, 
20, 20, 20, 20, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 5, 
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 
10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 
20, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 100, 100, 
100, 100, 100, 100, 100, 100, 100, 100, 100, 100), value = c(0.38, 
0.4, 0.37, 0.32, 0.29, 0.3, 0.24, 0.28, 0.24, 0.26, 0.32, 0.39, 
0.13, NaN, 0.13, 0.12, 0.1, 0.1, 0.06, 0.07, 0.09, 0.1, 0.12, 
0.13, 0.39, 0.39, 0.37, 0.35, 0.33, 0.31, 0.27, 0.29, 0.27, 0.28, 
0.34, 0.38, 0.1, NaN, 0.12, 0.11, 0.09, 0.09, 0.05, 0.06, 0.09, 
0.09, 0.11, 0.11, 0.39, 0.41, 0.38, 0.35, 0.34, 0.32, 0.29, 0.33, 
0.31, 0.3, 0.34, 0.36, 0.1, NaN, 0.1, 0.1, 0.09, 0.08, 0.05, 
0.05, 0.08, 0.08, 0.1, 0.1, 0.32, 0.31, 0.33, 0.34, 0.36, 0.34, 
0.29, 0.33, 0.32, 0.31, 0.32, 0.33, 0.06, 0.06, 0.07, 0.06, 0.06, 
0.05, 0.03, 0.03, 0.04, 0.05, 0.06, 0.06, 0.4, 0.4, 0.41, 0.41, 
0.45, 0.47, 0.43, 0.4, 0.39, 0.38, 0.38, 0.4, 0.05, 0.05, 0.05, 
0.06, 0.05, 0.05, 0.04, 0.04, 0.05, 0.05, 0.06, 0.05, 0.35, 0.35, 
0.36, 0.33, 0.29, 0.28, 0.27, 0.26, 0.26, 0.28, 0.3, 0.36, 0.35, 
0.35, 0.36, 0.33, 0.29, 0.28, 0.27, 0.27, 0.27, 0.28, 0.3, 0.35, 
0.34, 0.35, 0.35, 0.34, 0.3, 0.29, 0.28, 0.28, 0.28, 0.29, 0.3, 
0.34, 0.28, 0.29, 0.3, 0.32, 0.31, 0.3, 0.29, 0.29, 0.29, 0.3, 
0.3, 0.29, 0.26, 0.27, 0.27, 0.29, 0.29, 0.29, 0.28, 0.28, 0.28, 
0.29, 0.29, 0.28, 0.38, 0.38, 0.39, 0.38, 0.31, 0.3, 0.29, 0.29, 
0.3, 0.31, 0.35, 0.39, 0.36, 0.36, 0.37, 0.37, 0.31, 0.31, 0.29, 
0.3, 0.3, 0.31, 0.33, 0.37, 0.37, 0.37, 0.37, 0.38, 0.32, 0.32, 
0.31, 0.31, 0.31, 0.32, 0.33, 0.37, 0.31, 0.32, 0.32, 0.34, 0.33, 
0.32, 0.31, 0.31, 0.32, 0.32, 0.31, 0.3, 0.27, 0.28, 0.28, 0.29, 
0.31, 0.3, 0.3, 0.29, 0.3, 0.3, 0.3, 0.28), type = rep(c("observed","modeled"), each=120)), class = "data.frame", row.names = c(NA, 
-240L))

# Create blue and red palettes
mypal.blue <- colorRampPalette(RColorBrewer::brewer.pal(6,"PuBu"))
mypal.red  <- colorRampPalette(RColorBrewer::brewer.pal(6,"YlOrRd"))

# Plot
ggplot(df1, aes(x=value, y=-depth, colour=interaction(as.factor(month),type))) +
  geom_path(size=1) + geom_point(size=0.7) +
  facet_wrap(~ site, nrow=3) +
  theme_bw(base_size=20) +
  scale_colour_manual(values=c(mypal.blue(12),mypal.red(12))) +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) + 
  theme(legend.title=element_blank()) + theme(legend.position = c(0.75, 0.13))

Однако легенда - полный беспорядок.

Я хотел бы создать две отдельные легенды, на основе этого примера.

  • один показывает оранжевый для наблюдаемого и синий для смоделированного
  • другой показывает фактические цветовые градиенты и месяцы (в идеале с первой буквой вместо цифр)

Как создавать такие легенды?

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Обновленный ответ

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

Со всеми этими линиями и цветами и сложной легендой сюжет кажется очень занятым, и его трудно интерпретировать, кроме того, что он показывает, что модель не очень хорошо вписывается в данные, поэтому, возможно, было бы лучше рассмотреть один из других вариантов. варианты в моем ответе или @ neilfws. Кроме того, поскольку заголовок легенды жестко запрограммирован вручную, он не связан с эстетическим отображением, и поэтому вам следует соблюдать осторожность, чтобы «Смоделированные» и «Наблюдаемые» находились в правильном порядке над клавишами легенды.

ggplot(df1, aes(x=value, y=-depth, colour=interaction(as.factor(month),type))) +
  geom_path(size=1) + geom_point(size=0.7) +
  facet_wrap(~ site, nrow=3) +
  theme_bw(base_size=20) +
  scale_colour_manual(values=c(mypal.blue(12),mypal.red(12)),
                      labels=rep(month.abb, 2)) +
  theme(panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(),
        legend.title=element_text(size=rel(0.6)),
        legend.text=element_text(size=rel(0.5)),
        legend.key.width=unit(1.1,"cm")) + 
  labs(colour="Modeled  Observed")

enter image description here

Оригинальный ответ

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

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

library(tidyverse)

ggplot(df1 %>% 
         mutate(month=factor(month.abb[month], levels=month.abb)), 
       aes(x=value, y=-depth, linetype=type, colour=month)) +
  geom_path(size=1) + geom_point(size=0.7) +
  facet_wrap(~ site, nrow=3) +
  theme_bw(base_size=20) +
  scale_colour_manual(values=mypal.red(12)) +
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) + 
  theme(legend.title=element_blank()) 

enter image description here

Для справки, вот что генерирует ваш оригинальный код (за исключением изменения положения легенды):

enter image description here

Другим вариантом будет фасетирование month в дополнение к type. Это занимает больше места, но позволяет легче увидеть как месячный тренд, так и разницу между моделируемым и наблюдаемым.

ggplot(df1 %>% 
         mutate(month=factor(month.abb[month], levels=month.abb)),
       aes(x=value, y=-depth, colour=type)) +
  geom_path(size=1) + geom_point(size=0.7) +
  facet_grid(month ~ site) +
  theme_classic() +
  theme(panel.background=element_rect(colour="grey50", fill=NA))

enter image description here

0 голосов
/ 11 мая 2018

Глядя на ваши данные, мне кажется, что то, что вы хотите визуализировать, можно выразить примерно так:

"Как наблюдаемые значения сравниваются с моделируемыми значениями на разных глубинах для каждого сайтачерез время? "

Так что я бы подошел к диаграмме по-другому: значение графика в зависимости от месяца, цвет по типу и использование фасетов для места и глубины.

library(tidyverse)
df1 %>% 
  mutate(Month = factor(month.abb[month], 
         levels = month.abb)) %>% 
  ggplot(aes(Month, value)) + 
    geom_point(aes(color = type)) + 
    facet_grid(depth~site) + 
    theme_bw()

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

enter image description here

...