ggplot:如何在 geom_rect 中获得与其他几何体不同的颜色的半透明填充?fill=alpha() 似乎不起作用

Chr*_*sen 6 plot alpha r ggplot2

我正在尝试想象 Covid-19 之前和之后的外科手术:

在此输入图像描述

正如你所看到的,我的geom_rect()颜色与geom_point().

我希望蓝色colorfillgeom_rect()半透明的,类似fill = alpha("#2C77BF", .5)). 但是,当使用下面的脚本时,alpha-部分不起作用。

geom_rect()如何获得与指定的颜色不同的半透明度geom_point()

ggplot(b,
       aes(x = cons_week, y = n, color = corona, fill = corona)) +
  geom_point(size = 5, shape = 21) +
  geom_smooth(se = F, method = lm, color = "black", show.legend = F) +
  geom_smooth(lty = 2, show.legend = F) + 
  geom_segment(aes(x = 167, xend = 167, y = 2.5, yend = 25), 
               color = "red", size = 1) +
  geom_rect(aes(xmin = 1, xmax = 30, 
                ymin = 0, ymax = 5),
            color = "#2C77BF", 
            fill = alpha("#2C77BF", .5)) +
  scale_color_manual(name = "",
                     values = c("#8B3A62", "#6DBCC3"),
                     labels = c("COVID-19", "Normal"),
                     guide = guide_legend(reverse=TRUE)) + 
  scale_fill_manual(name = "",
                    values = alpha(c("#8B3A62", "#6DBCC3"), .25),
                    labels = c("COVID-19", "Normal"),
                    guide = guide_legend(reverse=TRUE)) + 
  scale_x_continuous(name = "",
                     breaks = seq(0, 210, 12)) + 
  scale_y_continuous(name = "",
                     breaks = seq(0, 30, 5), limits = c(0, 30)) + 
  theme(axis.title.y = element_text(color = "grey20", 
                                    size = 17, 
                                    face="bold", 
                                    margin=ggplot2::margin(r=10)),
        axis.line = element_line(colour = "black"),
        axis.text.x = element_text(color = "white", size = 20),
        axis.ticks.x = element_blank(),
        panel.grid.major = element_line(colour = "grey90"),
        panel.grid.minor = element_line(colour = "grey90"),
        panel.border = element_blank(),
        panel.background = element_blank(),
        legend.position = "top",
        legend.key = element_rect(fill = "white"),
        legend.text=element_text(size=15))
Run Code Online (Sandbox Code Playgroud)

数据

b <- structure(list(corona = structure(c(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, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("C19", "Normal"
), class = "factor"), cons_week = c(185, 176, 190, 201, 184, 
170, 202, 179, 203, 178, 206, 208, 209, 193, 181, 168, 191, 171, 
192, 195, 186, 175, 187, 174, 207, 169, 205, 197, 200, 173, 204, 
199, 189, 180, 194, 188, 182, 177, 196, 183, 124, 111, 75, 148, 
27, 158, 1, 62, 11, 56, 57, 154, 141, 51, 112, 159, 116, 8, 126, 
121, 38, 9, 78, 122, 32, 63, 94, 129, 76, 43, 44, 103, 84, 89, 
92, 37, 67, 19, 73, 142), n = c(17L, 9L, 16L, 15L, 12L, 9L, 15L, 
17L, 11L, 12L, 15L, 14L, 12L, 15L, 13L, 11L, 17L, 14L, 15L, 11L, 
19L, 14L, 16L, 15L, 14L, 13L, 20L, 18L, 9L, 20L, 20L, 18L, 15L, 
10L, 13L, 14L, 21L, 13L, 23L, 18L, 14L, 7L, 14L, 13L, 12L, 14L, 
14L, 16L, 19L, 10L, 14L, 11L, 18L, 12L, 18L, 8L, 10L, 15L, 19L, 
21L, 17L, 11L, 10L, 11L, 14L, 18L, 15L, 13L, 17L, 18L, 15L, 14L, 
17L, 9L, 16L, 15L, 17L, 17L, 13L, 12L)), row.names = c(NA, -80L
), groups = structure(list(corona = structure(1:2, .Label = c("C19", 
"Normal"), class = "factor"), .rows = structure(list(1:40, 41:80), ptype = integer(0), class = c("vctrs_list_of", 
"vctrs_vctr", "list"))), row.names = c(NA, -2L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))
Run Code Online (Sandbox Code Playgroud)

che*_*123 11

@brunosm的答案是解决这个问题的方法。根据r2evans的建议,我提供了一个答案,该答案更能说明为什么 alpha在与 一起使用时似乎不起作用的原因geom_rect()。事实上,您实际上仍然可以使用geom_rect(),尽管annotate()这是更好的选择。

答案就在于geom_rect()和之间的内在区别annotate(geom="rect"...。这是geoms根据你的绘制东西data=,而annotate()不是。

实际上,通过演示最容易看出。您已经发布过,当您使用下面的代码时,您会得到一个实心框。请注意,p在这种情况下是您的整个绘图代码,不含以下geom_rect()部分:

p <- # your plot code entirely, but leave out geom_rect()
p + geom_rect(
  aes(xmin = 1, xmax = 30, ymin = 0, ymax = 5),
  color = "#2C77BF", fill = alpha("#2C77BF", .5))
Run Code Online (Sandbox Code Playgroud)

该代码为您提供了一个纯蓝色矩形,并且看起来 alpha 不起作用。事实上,情况并非如此,alpha 的设置效果很好。我们来看下面的反例。我将做相同的绘图,但这次仅将数据集中的第一个观察值传递bgeom_rect(). 注意不同的结果:

p + geom_rect(data=b[1,],
  aes(xmin = 1, xmax = 30, ymin = 0, ymax = 5),
  color = "#2C77BF", fill = alpha("#2C77BF", .5))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

它按预期工作!这是因为由于geom_rect()是 a geom,因此它的绘制方法基于源数据,在本例中是b完整的。这意味着对于 中的每个观察bgeom_rect()都绘制一个 alpha 0.5 的矩形。最后,您得到的黑色矩形是过度绘制的结果- 就您的数据集而言,它是在彼此之上绘制 80 个 alpha = 0.5 的矩形的结果。

为了获得更多说明,请注意当我将两个观察结果传递b给时会发生什么geom_rect()

p + geom_rect(data=b[1:2,],
  aes(xmin = 1, xmax = 30, ymin = 0, ymax = 5),
  color = "#2C77BF", fill = alpha("#2C77BF", .5))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我们的矩形现在有点暗,因为ggplot在同一位置绘制了两个矩形。

这里的底线是annotate()data=源从图片中剔除。这意味着您无法注释随数据变化的内容,但如果遇到这种情况,您将使用geom_rect().

我想如果你真的想用这种方式来做到这一点geom_rect(),那么使用...来做到这一点没有真正的问题geom_rect(data=b[1,],.........这可能不是正确的方法。:)


bru*_*osm 6

您使用了错误的功能。使用 annotate() 代替 geom_rect(),并将 alpha 参数放入其中。您也不需要 aes()。

(...) +
annotate(geom = "rect", xmin = 1, xmax = 30, 
                ymin = 0, ymax = 5,
            color = "#2C77BF", 
            fill = "#2C77BF", alpha = 0.5) +
(...)

Run Code Online (Sandbox Code Playgroud)

  • @r2evans @brunosm 你得到一个实心蓝色矩形的原因是由于过度绘制。是的,在这里使用 `geom_rect()` 是不正确的,因为它采用了 `xmin`、`xmax` 美学并使用它们*为数据集中的每一行*绘制了一个 `rect`!如果为“geom_rect()”设置“data=b[1,]”,您可以看到发生了什么。它显示“正确”的矩形,因为它只绘制一次。`data=b[1:2,]` 绘制了一个不太透明的矩形,因为它绘制了两次......等等。默认情况下,`geom_rect()` 使用所有 80 个观测值并绘制相同的浅色矩形... 80 次。:) (2认同)
  • @chemdork123,虽然brunosm的答案当然是合适的并且修复了*症状*,但我建议您的评论是为什么geom的alpha与其他geom的颜色表现不同的真正答案。无论它是否被接受,我认为都值得将其形式化为一个答案,如果没有其他原因,只是将其从评论中分解出来,变成更明显的东西。 (2认同)