可以强制不出现的元素显示在 ggplot 图例中吗?
Possible to force non-occurring elements to show in ggplot legend?
我正在绘制一个研究区域内最多三种可选物种丰度的叶绿体。这个玩具代码的行为符合预期并且几乎符合我的要求:
library(dplyr)
library(ggplot2)
square <- expand.grid(X=0:10, Y=0:10)
sq2 <- square[rep(row.names(square), 2),] %>%
arrange(X,Y) %>%
mutate(SPEC = rep(c('red','blue'),len=n())) %>%
mutate(POP = ifelse(SPEC %in% 'red', X, Y)) %>%
group_by(X,Y) %>%
mutate(CLR = rgb(X/10,0,Y/10)) %>% ungroup()
ggplot(sq2, aes(x=X, y=Y, fill=CLR)) + geom_tile() +
scale_fill_identity("Species", guide="legend",
labels=c('red','blue'), breaks=c('#FF0000','#0000FF'))
制作这个:
修改后的版本正确地绘制了真实地图,适当地混合了 RGB 以显示每个地图单元的物种比例。但考虑到这种混合,真实数据不一定包括 breaks
中列出的具体值,在这种情况下,该物种的图例中不会出现任何条目。如果将示例的最后一行更改为
labels=c('red','blue','green'), breaks=c('#FF0000','#0000FF','#00FF00'))
您得到与所示相同的图例,仅显示 'red' 和 'blue',因为其中没有绿色。搜索每个 max(Species) 的数据并将其分配给图例是可能的,但不会为仅以低比例出现的物种制作好的图例键。图例需要显示存在的实体的想法,而不是它们已证实的存在——图例中的三种颜色,即使只检测到一个物种。
我认为 scale_fill_manual()
或 override.aes
论点可能对我有帮助,但我无法进行任何组合。
编辑:
第四集 -- 新的死胡同
(感谢@r2evans 修复了我遗漏的包。)
我想我可以通过在名为 spCLR
的处理管道中将另一列变异到 df 中来欺骗图例,以表示对每个条目的物种进行编码的颜色('#FF0000',例如)(冗余信息,但美好的)。现在我的真实版本中的绘图调用是:
df %>% [everything] %>%
ggplot(aes(x = X, y = Y, height = WIDTH, width = WIDTH, fill = CLR)) +
geom_tile() +
scale_fill_identity("Species", guide="legend",
labels=spCODE, breaks=spCLR)
但这给出了错误:Error in check_breaks_labels(breaks, labels) : object 'spCLR' not found
。 这看起来很奇怪,因为 spCLR
确实在管道修改的 df 中,并且在提供给 ggplot 函数的所有值中 spCODE
是原始 df 中唯一存在的值 - 所以如果存在某种范围问题,我不明白。 [重新编辑——我发现标签和中断都不想查看 df$anything。无论如何。]
我假设 (对吗?) 有一些方法可以使这个工作 [?],但它仍然不会使图例显示 'red','blue' 和 'green' 在我的玩具示例中——这是我最初的问题的真正含义——因为其中仍然没有实际的绿色数据。所以重申一下,有没有什么办法可以强制 ggplot2 图例显示您想要谈论的内容,而不仅仅是数据中存在的内容?
我从热图用例中假设您没有其他需要在图表中进行颜色映射。在这种情况下,一个可能的解决方法是单独保留填充比例,并创建一个带有颜色美学映射的不可见几何图层来生成所需的图例:
ggplot(sq2, aes(x=X, y=Y)) +
geom_tile(aes(fill = CLR)) + # move fill mapping here so new point layer doesn't inherit it
scale_fill_identity() + # scale_*_identity has guide set to FALSE by default
# add invisible layer with colour (not fill) mapping, within x/y coordinates within
# same range as geom_tile layer above
geom_point(data = . %>%
slice(1:3) %>%
# optional: list colours in the desired label order
mutate(col = forcats::fct_inorder(c("red", "blue", "green"))),
aes(colour = col),
alpha = 0) +
# add colour scale with alpha set to 1 (overriding alpha = 0 above),
# also make the shape square & larger to mimic the default legend keys
# associated with fill scale
scale_color_manual(name = "Species",
values = c("red" = '#FF0000', "blue" = '#0000FF', "green" = '#00FF00'),
guide = guide_legend(override.aes = list(alpha = 1, shape = 15, size = 5)))
我后来才发现我的问题几乎与 this 重复。那里接受的答案(来自@joran)对此不起作用,但第二个答案(来自@Axeman)可以。所以我去这里的方式是最后一行应该是
labels=c('red','blue','green'), limits=c('#FF0000','#0000FF','#00FF00'))
调用 limits()
而不是 breaks()
,现在我的示例和我的真实版本可以正常工作。
我不得不说我花了很多时间在 ggplot2 reference 中四处挖掘,却从未怀疑 limits() 是 breaks() 的正确替代品——在那篇文章中明确提到参考页面,而 limits() 没有出现。 ?limits() 页面提供的信息很少,我找不到任何东西来说明两者之间的区别:when this rather than that。
我正在绘制一个研究区域内最多三种可选物种丰度的叶绿体。这个玩具代码的行为符合预期并且几乎符合我的要求:
library(dplyr)
library(ggplot2)
square <- expand.grid(X=0:10, Y=0:10)
sq2 <- square[rep(row.names(square), 2),] %>%
arrange(X,Y) %>%
mutate(SPEC = rep(c('red','blue'),len=n())) %>%
mutate(POP = ifelse(SPEC %in% 'red', X, Y)) %>%
group_by(X,Y) %>%
mutate(CLR = rgb(X/10,0,Y/10)) %>% ungroup()
ggplot(sq2, aes(x=X, y=Y, fill=CLR)) + geom_tile() +
scale_fill_identity("Species", guide="legend",
labels=c('red','blue'), breaks=c('#FF0000','#0000FF'))
制作这个:
修改后的版本正确地绘制了真实地图,适当地混合了 RGB 以显示每个地图单元的物种比例。但考虑到这种混合,真实数据不一定包括 breaks
中列出的具体值,在这种情况下,该物种的图例中不会出现任何条目。如果将示例的最后一行更改为
labels=c('red','blue','green'), breaks=c('#FF0000','#0000FF','#00FF00'))
您得到与所示相同的图例,仅显示 'red' 和 'blue',因为其中没有绿色。搜索每个 max(Species) 的数据并将其分配给图例是可能的,但不会为仅以低比例出现的物种制作好的图例键。图例需要显示存在的实体的想法,而不是它们已证实的存在——图例中的三种颜色,即使只检测到一个物种。
我认为 scale_fill_manual()
或 override.aes
论点可能对我有帮助,但我无法进行任何组合。
编辑:
第四集 -- 新的死胡同
(感谢@r2evans 修复了我遗漏的包。)
我想我可以通过在名为 spCLR
的处理管道中将另一列变异到 df 中来欺骗图例,以表示对每个条目的物种进行编码的颜色('#FF0000',例如)(冗余信息,但美好的)。现在我的真实版本中的绘图调用是:
df %>% [everything] %>%
ggplot(aes(x = X, y = Y, height = WIDTH, width = WIDTH, fill = CLR)) +
geom_tile() +
scale_fill_identity("Species", guide="legend",
labels=spCODE, breaks=spCLR)
但这给出了错误:Error in check_breaks_labels(breaks, labels) : object 'spCLR' not found
。 这看起来很奇怪,因为 [重新编辑——我发现标签和中断都不想查看 df$anything。无论如何。]spCLR
确实在管道修改的 df 中,并且在提供给 ggplot 函数的所有值中 spCODE
是原始 df 中唯一存在的值 - 所以如果存在某种范围问题,我不明白。
我假设 (对吗?) 有一些方法可以使这个工作 [?],但它仍然不会使图例显示 'red','blue' 和 'green' 在我的玩具示例中——这是我最初的问题的真正含义——因为其中仍然没有实际的绿色数据。所以重申一下,有没有什么办法可以强制 ggplot2 图例显示您想要谈论的内容,而不仅仅是数据中存在的内容?
我从热图用例中假设您没有其他需要在图表中进行颜色映射。在这种情况下,一个可能的解决方法是单独保留填充比例,并创建一个带有颜色美学映射的不可见几何图层来生成所需的图例:
ggplot(sq2, aes(x=X, y=Y)) +
geom_tile(aes(fill = CLR)) + # move fill mapping here so new point layer doesn't inherit it
scale_fill_identity() + # scale_*_identity has guide set to FALSE by default
# add invisible layer with colour (not fill) mapping, within x/y coordinates within
# same range as geom_tile layer above
geom_point(data = . %>%
slice(1:3) %>%
# optional: list colours in the desired label order
mutate(col = forcats::fct_inorder(c("red", "blue", "green"))),
aes(colour = col),
alpha = 0) +
# add colour scale with alpha set to 1 (overriding alpha = 0 above),
# also make the shape square & larger to mimic the default legend keys
# associated with fill scale
scale_color_manual(name = "Species",
values = c("red" = '#FF0000', "blue" = '#0000FF', "green" = '#00FF00'),
guide = guide_legend(override.aes = list(alpha = 1, shape = 15, size = 5)))
我后来才发现我的问题几乎与 this 重复。那里接受的答案(来自@joran)对此不起作用,但第二个答案(来自@Axeman)可以。所以我去这里的方式是最后一行应该是
labels=c('red','blue','green'), limits=c('#FF0000','#0000FF','#00FF00'))
调用 limits()
而不是 breaks()
,现在我的示例和我的真实版本可以正常工作。
我不得不说我花了很多时间在 ggplot2 reference 中四处挖掘,却从未怀疑 limits() 是 breaks() 的正确替代品——在那篇文章中明确提到参考页面,而 limits() 没有出现。 ?limits() 页面提供的信息很少,我找不到任何东西来说明两者之间的区别:when this rather than that。