在 ggplot2 中跨多个图创建线
Create line across multiple plots in ggplot2
我想结合 patchwork 包创建一条横跨两个地块的水平线。
library(ggplot2)
library(patchwork)
# Annotation after plot
p1 <- ggplot(mtcars, aes(x=disp,y=mpg))+
geom_point()
p2 <- ggplot(mtcars, aes(x=hp,y=mpg))+
geom_point()
# Want line across plots at y (mpg) of 15
p3 <- (p1+p2)+annotate("segment",x=-Inf,xend=Inf,y=15,yend=15)
p3
此方法仅将线穿过最后一个图 (p2)。
尝试在每个图上添加注释。
# Annotation with each plot
p1 <- ggplot(mtcars, aes(x=disp,y=mpg))+
geom_point()+
annotate("segment",x=-Inf,xend=Inf,y=15,yend=15)
p2 <- ggplot(mtcars, aes(x=hp,y=mpg))+
geom_point()+
annotate("segment",x=-Inf,xend=Inf,y=15,yend=15)
p1+p2
此方法将线放在每个图上,但不在图之间。
我想要这样的东西:
您可以使用 grid.draw
绘制线条,该线条绘制在绘图 window:
中的任何其他内容之上
library(grid)
p3
grid.draw(linesGrob(x = unit(c(0.06, 0.98), "npc"), y = unit(c(0.277, 0.277), "npc")))
但是,这里有一些注意事项。线条的确切定位由您决定,尽管如果这是您要经常做的事情,定位可以通过编程方式完成,但一次性调整 x 和 y 值以获得线条会更快在你想要的地方,就像我在不到一分钟的时间里所做的那样。
第二个注意事项是该行位于 npc space 中,而 ggplot 使用固定间距和灵活间距的组合。这样做的结果是,无论何时调整绘图大小时,线都会相对于绘图移动。同样,这可以通过编程方式修复。如果你真的想打开那罐蠕虫,你可以在我对
的回答中看到一个类似点的解决方案
我喜欢@Allan 的回答,但这是使用 facet_wrap
.
的替代方法
首先,我们需要将数据旋转更长的时间,以使其处于可以使用的形式 facet_wrap
。然后黑客开始。首先,我们需要使用 strip.position = 'bottom'
将小平面条标签移动到下方。然后我们可以使用 coord_cartesian(clip = 'off')
关闭裁剪,以便可以在图形区域之外绘制线条。接下来我们修复 xlim
以便当您尝试在图形区域外绘制线段时图形绘制区域不会改变。
最后,大黑客,你用新数据绘制 geom_segment
,这样它只在一个方面绘制。您在调用 geom_segment
中创建了一个新的 data.frame
,其中包含的数据使其在最后一个要呈现的面板中绘制,因此该行位于顶部。
最后,只是 theme()
中的一些更改,因此条带背景为空白,并且放置在轴刻度之外。
library(ggplot2)
library(dplyr)
library(tidyr)
ggplot(pivot_longer(mtcars, -mpg) %>% filter(name %in% c("disp", "hp")),
aes(x=value, y=mpg, group=name)) +
geom_point() +
facet_wrap(.~name, strip.position = "bottom") +
geom_segment(data = data.frame(mpg = 15, name = "hp"),
x=-650, xend=525, y=15, yend=15) +
coord_cartesian(clip = 'off', xlim = c(0,500)) +
theme(aspect.ratio = 1,
strip.background = element_blank(),
strip.placement = "outside") +
labs(x = "")
我想结合 patchwork 包创建一条横跨两个地块的水平线。
library(ggplot2)
library(patchwork)
# Annotation after plot
p1 <- ggplot(mtcars, aes(x=disp,y=mpg))+
geom_point()
p2 <- ggplot(mtcars, aes(x=hp,y=mpg))+
geom_point()
# Want line across plots at y (mpg) of 15
p3 <- (p1+p2)+annotate("segment",x=-Inf,xend=Inf,y=15,yend=15)
p3
此方法仅将线穿过最后一个图 (p2)。
尝试在每个图上添加注释。
# Annotation with each plot
p1 <- ggplot(mtcars, aes(x=disp,y=mpg))+
geom_point()+
annotate("segment",x=-Inf,xend=Inf,y=15,yend=15)
p2 <- ggplot(mtcars, aes(x=hp,y=mpg))+
geom_point()+
annotate("segment",x=-Inf,xend=Inf,y=15,yend=15)
p1+p2
此方法将线放在每个图上,但不在图之间。
我想要这样的东西:
您可以使用 grid.draw
绘制线条,该线条绘制在绘图 window:
library(grid)
p3
grid.draw(linesGrob(x = unit(c(0.06, 0.98), "npc"), y = unit(c(0.277, 0.277), "npc")))
但是,这里有一些注意事项。线条的确切定位由您决定,尽管如果这是您要经常做的事情,定位可以通过编程方式完成,但一次性调整 x 和 y 值以获得线条会更快在你想要的地方,就像我在不到一分钟的时间里所做的那样。
第二个注意事项是该行位于 npc space 中,而 ggplot 使用固定间距和灵活间距的组合。这样做的结果是,无论何时调整绘图大小时,线都会相对于绘图移动。同样,这可以通过编程方式修复。如果你真的想打开那罐蠕虫,你可以在我对
我喜欢@Allan 的回答,但这是使用 facet_wrap
.
首先,我们需要将数据旋转更长的时间,以使其处于可以使用的形式 facet_wrap
。然后黑客开始。首先,我们需要使用 strip.position = 'bottom'
将小平面条标签移动到下方。然后我们可以使用 coord_cartesian(clip = 'off')
关闭裁剪,以便可以在图形区域之外绘制线条。接下来我们修复 xlim
以便当您尝试在图形区域外绘制线段时图形绘制区域不会改变。
最后,大黑客,你用新数据绘制 geom_segment
,这样它只在一个方面绘制。您在调用 geom_segment
中创建了一个新的 data.frame
,其中包含的数据使其在最后一个要呈现的面板中绘制,因此该行位于顶部。
最后,只是 theme()
中的一些更改,因此条带背景为空白,并且放置在轴刻度之外。
library(ggplot2)
library(dplyr)
library(tidyr)
ggplot(pivot_longer(mtcars, -mpg) %>% filter(name %in% c("disp", "hp")),
aes(x=value, y=mpg, group=name)) +
geom_point() +
facet_wrap(.~name, strip.position = "bottom") +
geom_segment(data = data.frame(mpg = 15, name = "hp"),
x=-650, xend=525, y=15, yend=15) +
coord_cartesian(clip = 'off', xlim = c(0,500)) +
theme(aspect.ratio = 1,
strip.background = element_blank(),
strip.placement = "outside") +
labs(x = "")