【问题标题】:ggplot2 - customize two-factor legendggplot2 - 自定义二因素图例
【发布时间】:2018-05-11 03:07:16
【问题描述】:

我正在使用 ggplot2 绘制两个地点的每月土壤湿度垂直剖面图,包括观测数据和建模数据。

我正在使用 interaction 为两个因子(monthtype)添加颜色。我还在用我需要的颜色创建两个不同的手动调色板。这是重现情节的方法:

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))

然而,传说是一团糟。

我想创建两个单独的图例,loosely based on this example

  • 橙色表示观察,蓝色表示建模
  • 另一个显示实际颜色渐变和月份(最好使用第一个字母而不是数字)

如何创造这样的传说?

【问题讨论】:

  • 不确定“实际颜色渐变”是什么意思?但听起来你想要 > 1 个变量映射到不同的色阶,这是行不通的。我会考虑您的数据中的分组,以及如何通过几何、形状、颜色和刻面最好地映射它们。
  • 原帖代码产生的图例颜色不错。我想这是需要组织的标签。我想将标签与例如1.modeled2.modeled3.modeled 等到 janfebmar 等,并创建一个单独的图例,仅显示 modeled 的蓝色标签项目和 @ 的红色或橙色标签项目987654333@。希望现在更清楚了!

标签: r ggplot2 colors legend


【解决方案1】:

更新答案

我突然想到,有一种相对简单的方法可以破解传说以非常接近您想要的。我们重新标记图例标签并添加标题。棘手的部分是您必须调整图例标题间距、图例键宽度和文本大小,以使标题在图例键上排列。

有了所有这些线条和颜色以及复杂的图例,除了表明模型与数据不太吻合之外,情节似乎非常繁忙且难以解释,所以也许考虑其中之一会更好我或@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")

原答案

AFAIK,在正常的 ggplot 工作流程中,无法为单一美学生成两个单独的图例。在这种情况下,这意味着您只能有一个颜色图例。也许你可以通过操纵底层的 ggplot grob 结构来破解两个不同的颜色图例。

另一种选择是使用两种不同的美学。下面的示例使用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()) 

作为参考,以下是您的原始代码产生的结果(减去图例位置的变化):

除了type之外,另一个选项是month。这会占用更多空间,但可以更轻松地查看月份趋势以及建模与观测之间的差异。

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))

【讨论】:

  • 感谢您的回答!您的第一个示例非常接近我的需要。绝对不是相同的对比,但我认为图例的清晰度是可以接受的权衡。
  • 我刚刚意识到,有一种相对简单(虽然很老套)的方法可以得到你最初想要的东西。请参阅我的更新答案。
  • 更新后的答案真的很神奇,感谢您的坚持!正是我想要的——ggplot2 是一个灵活得像地狱的工具。
【解决方案2】:

查看您的数据,在我看来,您想要可视化的内容可以这样表达:

“随着时间的推移,每个站点的不同深度的观测值与建模值相比如何?”

所以我会以不同的方式处理图表:绘制价值与月份的关系图,按类型划分颜色,并使用分面来表示站点和深度。

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 的建模值更接近于观察到的值,在较浅的深度更是如此。

【讨论】:

  • 非常感谢您的建议!情节看起来不错,但我认为有一件事让它更难看:季节性。在最初的方法中,季节性与线条的“分布”相结合:如果它们紧密组合,则土壤水分几乎没有季节性;如果它们被传播,那么土壤水分的季节性变化就会更大。
猜你喜欢
  • 2012-11-07
  • 1970-01-01
  • 2021-08-27
  • 1970-01-01
  • 2018-02-27
  • 1970-01-01
  • 2021-12-08
  • 2018-07-29
  • 1970-01-01
相关资源
最近更新 更多