将图像背景添加到 ggplot barplot,以便图像仅在条形图内可见
Add image background to ggplot barplot so that image is only visible inside of bars
我想在 R 中使用 ggplot2 创建一个条形图,这样条形图是透明的,从而使背景图像可见,而图的其余部分是不透明的并覆盖背景图像。
我可以将图像添加到背景中,如下所示,但我找不到只在条形图内显示背景图像的方法。从本质上讲,我希望创建与我在这里所拥有的相反的东西。
library(ggplot2)
library(jpeg)
library(grid)
library(scales)
montage <- readJPEG("AcanthMontage.jpg")
mont <- rasterGrob(montage,
width = unit(1,"npc"),
height = unit(1,"npc"))
montplot <- ggplot(frequencyDF, aes(x=depth, y= perLiter)) +
annotation_custom(mont, -Inf, Inf, -Inf, Inf) +
scale_fill_continuous(guide = FALSE) +
geom_bar(stat = "identity", color="black", fill="white", alpha=0.5) +
coord_flip() +
scale_y_continuous(limits= c(0,1.25), expand = c(0, 0)) +
scale_x_continuous(limits= c(-1000,0), expand = c(0,0)) +
theme_bw() +
theme(text=element_text(size=16)) +
xlab("Depth (m)") +
ylab("Cells per Liter")
montplot
相当有趣的问题。我和 @r2evans 一样担心这会产生令人困惑的情节,这可能会传达错误的解释和条形图内的模式。
如果这是一个图像编辑问题,您正在寻找一个蒙版 - 其中的条形图是过滤背景图像的蒙版。包 raster
有这个功能,但我不确定如何将它与 ggplot2 结合使用。
ggplot2 使用 grid
包将元素渲染到图形设备上(即屏幕、window、pdf 等)。在这里,您可以将 rasterGrob
与每个栏的视口组合起来以创建遮罩效果。第一站是从您的 ggplot2 对象渲染一个 ggplotGrob
对象(有效 ggplotGrob(p)
,其中 p <- ggplot(...) + ...
)。
有关视口的详细信息,请参阅Zhou 2010 and Murell 2018
这让我想起了一个类似的问题 ,其中公认的解决方案使用 geom_ribbon()
来提供掩蔽层。
以类似的方式进行,因为在这种情况下蒙版需要围绕单个条,我们希望创建一个多边形层来优雅地处理孔。最后我检查了一下,geom_polygon
并没有那么好,但是 ggpolypath 包中的 geom_polypath
确实如此。
可重现示例,使用 R 徽标作为示例图像和内置数据框:
library(ggplot2)
library(grid)
library(jpeg)
montage <- readJPEG(system.file("img", "Rlogo.jpg", package="jpeg"))
mont <- rasterGrob(montage, width = unit(1,"npc"),
height = unit(1,"npc"))
p <- ggplot(mpg, aes(x = class)) +
annotation_custom(mont, -Inf, Inf, -Inf, Inf) +
geom_bar(color = "black", fill = NA) +
coord_flip() +
theme_bw()
p
为掩蔽层创建坐标数据框:
library(dplyr)
library(tidyr)
# convert the xmin/xmax/ymin/ymax values for each bar into
# x/y coordinates for a hole in a large polygon,
# then add coordinates for the large polygon
new.data <- layer_data(p, 2L) %>%
select(ymin, ymax, xmin, xmax) %>%
mutate(group = seq(1, n())) %>%
group_by(group) %>%
summarise(coords = list(data.frame(x = c(xmin, xmax, xmax, xmin),
y = c(ymin, ymin, ymax, ymax),
order = seq(1, 4)))) %>%
ungroup() %>%
unnest() %>%
rbind(data.frame(group = 0,
x = c(-Inf, Inf, Inf, -Inf),
y = c(-Inf, -Inf, Inf, Inf),
order = seq(1, 4)))
> new.data
# A tibble: 32 x 4
group x y order
<dbl> <dbl> <dbl> <int>
1 1 0.55 0 1
2 1 1.45 0 2
3 1 1.45 5 3
4 1 0.55 5 4
5 2 1.55 0 1
6 2 2.45 0 2
7 2 2.45 47 3
8 2 1.55 47 4
9 3 2.55 0 1
10 3 3.45 0 2
# ... with 22 more rows
添加遮罩层:
library(ggpolypath)
p +
geom_polypath(data = new.data,
aes(x = x, y = y, group = group),
inherit.aes = FALSE,
rule = "evenodd",
fill = "white", color = "black")
p.s。古老的格言 "just because you can, doesn't mean you should" 可能适用于此...
我想在 R 中使用 ggplot2 创建一个条形图,这样条形图是透明的,从而使背景图像可见,而图的其余部分是不透明的并覆盖背景图像。
我可以将图像添加到背景中,如下所示,但我找不到只在条形图内显示背景图像的方法。从本质上讲,我希望创建与我在这里所拥有的相反的东西。
library(ggplot2)
library(jpeg)
library(grid)
library(scales)
montage <- readJPEG("AcanthMontage.jpg")
mont <- rasterGrob(montage,
width = unit(1,"npc"),
height = unit(1,"npc"))
montplot <- ggplot(frequencyDF, aes(x=depth, y= perLiter)) +
annotation_custom(mont, -Inf, Inf, -Inf, Inf) +
scale_fill_continuous(guide = FALSE) +
geom_bar(stat = "identity", color="black", fill="white", alpha=0.5) +
coord_flip() +
scale_y_continuous(limits= c(0,1.25), expand = c(0, 0)) +
scale_x_continuous(limits= c(-1000,0), expand = c(0,0)) +
theme_bw() +
theme(text=element_text(size=16)) +
xlab("Depth (m)") +
ylab("Cells per Liter")
montplot
相当有趣的问题。我和 @r2evans 一样担心这会产生令人困惑的情节,这可能会传达错误的解释和条形图内的模式。
如果这是一个图像编辑问题,您正在寻找一个蒙版 - 其中的条形图是过滤背景图像的蒙版。包 raster
有这个功能,但我不确定如何将它与 ggplot2 结合使用。
ggplot2 使用 grid
包将元素渲染到图形设备上(即屏幕、window、pdf 等)。在这里,您可以将 rasterGrob
与每个栏的视口组合起来以创建遮罩效果。第一站是从您的 ggplot2 对象渲染一个 ggplotGrob
对象(有效 ggplotGrob(p)
,其中 p <- ggplot(...) + ...
)。
有关视口的详细信息,请参阅Zhou 2010 and Murell 2018
这让我想起了一个类似的问题 geom_ribbon()
来提供掩蔽层。
以类似的方式进行,因为在这种情况下蒙版需要围绕单个条,我们希望创建一个多边形层来优雅地处理孔。最后我检查了一下,geom_polygon
并没有那么好,但是 ggpolypath 包中的 geom_polypath
确实如此。
可重现示例,使用 R 徽标作为示例图像和内置数据框:
library(ggplot2)
library(grid)
library(jpeg)
montage <- readJPEG(system.file("img", "Rlogo.jpg", package="jpeg"))
mont <- rasterGrob(montage, width = unit(1,"npc"),
height = unit(1,"npc"))
p <- ggplot(mpg, aes(x = class)) +
annotation_custom(mont, -Inf, Inf, -Inf, Inf) +
geom_bar(color = "black", fill = NA) +
coord_flip() +
theme_bw()
p
为掩蔽层创建坐标数据框:
library(dplyr)
library(tidyr)
# convert the xmin/xmax/ymin/ymax values for each bar into
# x/y coordinates for a hole in a large polygon,
# then add coordinates for the large polygon
new.data <- layer_data(p, 2L) %>%
select(ymin, ymax, xmin, xmax) %>%
mutate(group = seq(1, n())) %>%
group_by(group) %>%
summarise(coords = list(data.frame(x = c(xmin, xmax, xmax, xmin),
y = c(ymin, ymin, ymax, ymax),
order = seq(1, 4)))) %>%
ungroup() %>%
unnest() %>%
rbind(data.frame(group = 0,
x = c(-Inf, Inf, Inf, -Inf),
y = c(-Inf, -Inf, Inf, Inf),
order = seq(1, 4)))
> new.data
# A tibble: 32 x 4
group x y order
<dbl> <dbl> <dbl> <int>
1 1 0.55 0 1
2 1 1.45 0 2
3 1 1.45 5 3
4 1 0.55 5 4
5 2 1.55 0 1
6 2 2.45 0 2
7 2 2.45 47 3
8 2 1.55 47 4
9 3 2.55 0 1
10 3 3.45 0 2
# ... with 22 more rows
添加遮罩层:
library(ggpolypath)
p +
geom_polypath(data = new.data,
aes(x = x, y = y, group = group),
inherit.aes = FALSE,
rule = "evenodd",
fill = "white", color = "black")
p.s。古老的格言 "just because you can, doesn't mean you should" 可能适用于此...