可以创建插图吗?

发布于 2024-10-20 19:19:32 字数 333 浏览 1 评论 0原文

我知道当您使用 par( Fig=c( ... ), new=T ) 时,您可以创建插图。但是,我想知道是否可以使用 ggplot2 库来创建“插图”图。

更新 1:我尝试将 par() 与 ggplot2 一起使用,但它不起作用。

更新 2:我使用 ggplot2 GoogleGroups 找到了一个可行的解决方案grid::viewport()

I know that when you use par( fig=c( ... ), new=T ), you can create inset graphs. However, I was wondering if it is possible to use ggplot2 library to create 'inset' graphs.

UPDATE 1: I tried using the par() with ggplot2, but it does not work.

UPDATE 2: I found a working solution at ggplot2 GoogleGroups using grid::viewport().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

梦旅人picnic 2024-10-27 19:19:32

本书的第 8.4 节解释了如何执行此操作。诀窍是使用grid包的viewport

#Any old plot
a_plot <- ggplot(cars, aes(speed, dist)) + geom_line()

#A viewport taking up a fraction of the plot area
vp <- viewport(width = 0.4, height = 0.4, x = 0.8, y = 0.2)

#Just draw the plot twice
png("test.png")
print(a_plot)
print(a_plot, vp = vp)
dev.off()

Section 8.4 of the book explains how to do this. The trick is to use the grid package's viewports.

#Any old plot
a_plot <- ggplot(cars, aes(speed, dist)) + geom_line()

#A viewport taking up a fraction of the plot area
vp <- viewport(width = 0.4, height = 0.4, x = 0.8, y = 0.2)

#Just draw the plot twice
png("test.png")
print(a_plot)
print(a_plot, vp = vp)
dev.off()
吹梦到西洲 2024-10-27 19:19:32

利用 ggplot2 和 Egg 的更简单的解决方案。最重要的是,该解决方案可与 ggsave 配合使用。

library(ggplot2)
library(egg)
plotx <- ggplot(mpg, aes(displ, hwy)) + geom_point()
plotx + 
  annotation_custom(
    ggplotGrob(plotx), 
    xmin = 5, xmax = 7, ymin = 30, ymax = 44
  )
ggsave(filename = "inset-plot.png")

Much simpler solution utilizing ggplot2 and egg. Most importantly this solution works with ggsave.

library(ggplot2)
library(egg)
plotx <- ggplot(mpg, aes(displ, hwy)) + geom_point()
plotx + 
  annotation_custom(
    ggplotGrob(plotx), 
    xmin = 5, xmax = 7, ymin = 30, ymax = 44
  )
ggsave(filename = "inset-plot.png")
小霸王臭丫头 2024-10-27 19:19:32

或者,可以使用 cowplot Claus O. Wilke 的 R 包(cowplotggplot2 的强大扩展)。作者在 this 中有一个关于在较大图形内绘制插图的示例简介小插图。以下是一些改编代码:

library(cowplot)

main.plot <- 
  ggplot(data = mpg, aes(x = cty, y = hwy, colour = factor(cyl))) + 
  geom_point(size = 2.5)

inset.plot <- main.plot + theme(legend.position = "none")

plot.with.inset <-
  ggdraw() +
  draw_plot(main.plot) +
  draw_plot(inset.plot, x = 0.07, y = .7, width = .3, height = .3)

# Can save the plot with ggsave()
ggsave(filename = "plot.with.inset.png", 
       plot = plot.with.inset,
       width = 17, 
       height = 12,
       units = "cm",
       dpi = 300)

在此处输入图像描述

Alternatively, can use the cowplot R package by Claus O. Wilke (cowplot is a powerful extension of ggplot2). The author has an example about plotting an inset inside a larger graph in this intro vignette. Here is some adapted code:

library(cowplot)

main.plot <- 
  ggplot(data = mpg, aes(x = cty, y = hwy, colour = factor(cyl))) + 
  geom_point(size = 2.5)

inset.plot <- main.plot + theme(legend.position = "none")

plot.with.inset <-
  ggdraw() +
  draw_plot(main.plot) +
  draw_plot(inset.plot, x = 0.07, y = .7, width = .3, height = .3)

# Can save the plot with ggsave()
ggsave(filename = "plot.with.inset.png", 
       plot = plot.with.inset,
       width = 17, 
       height = 12,
       units = "cm",
       dpi = 300)

enter image description here

子栖 2024-10-27 19:19:32

'ggplot2' >= 3.0.0 使得添加插图的新方法成为可能,因为现在包含列表作为成员列的 tibble 对象可以作为数据传递。列表列中的对象甚至可以是整个 ggplots...我的包“ggpmisc”的最新版本提供了 geom_plot()geom_table()geom_grob (),以及使用npc单位而不是本地数据单位来定位插图的版本。这些几何对象可以在每次调用时添加多个插图并遵守分面,而 annotation_custom() 则不然。我从帮助页面复制了示例,该页面添加了一个插图,其中包含主图的放大细节作为插图。

library(tibble)
library(ggpmisc)
p <-
  ggplot(data = mtcars, mapping = aes(wt, mpg)) +
  geom_point()

df <- tibble(x = 0.01, y = 0.01,
             plot = list(p +
                         coord_cartesian(xlim = c(3, 4),
                                         ylim = c(13, 16)) +
                         labs(x = NULL, y = NULL) +
                         theme_bw(10)))
p +
  expand_limits(x = 0, y = 0) +
  geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot))

ggplot 与 ggplot作为插图

或条形图作为插图,取自包小插图。

library(tibble)
library(ggpmisc)
p <- ggplot(mpg, aes(factor(cyl), hwy, fill = factor(cyl))) +
  stat_summary(geom = "col", fun.y = mean, width = 2/3) +
  labs(x = "Number of cylinders", y = NULL, title = "Means") +
  scale_fill_discrete(guide = FALSE)

data.tb <- tibble(x = 7, y = 44, 
                  plot = list(p +
                                theme_bw(8)))

ggplot(mpg, aes(displ, hwy, colour = factor(cyl))) +
  geom_plot(data = data.tb, aes(x, y, label = plot)) +
  geom_point() +
  labs(x = "Engine displacement (l)", y = "Fuel use efficiency (MPG)",
       colour = "Engine cylinders\n(number)") +
  theme_bw()

输入图像描述这里

下一个示例展示了如何将不同的插图添加到多面图中的不同面板。下一个示例使用根据世纪拆分后的相同示例数据。这一特定数据集一旦分割,就会在插图之一中增加一个缺失级别的问题。由于这些图是自行构建的,我们需要使用手动比例来确保颜色和填充在各图中保持一致。对于其他数据集,可能不需要这样做。

library(tibble)
library(ggpmisc)
my.mpg <- mpg
my.mpg$century <- factor(ifelse(my.mpg$year < 2000, "XX", "XXI"))
my.mpg$cyl.f <- factor(my.mpg$cyl)
my_scale_fill <- scale_fill_manual(guide = FALSE, 
                                   values = c("red", "orange", "darkgreen", "blue"),
                                   breaks = levels(my.mpg$cyl.f))

p1 <- ggplot(subset(my.mpg, century == "XX"),
             aes(factor(cyl), hwy, fill = cyl.f)) +
  stat_summary(geom = "col", fun = mean, width = 2/3) +
  labs(x = "Number of cylinders", y = NULL, title = "Means") +
  my_scale_fill

p2 <- ggplot(subset(my.mpg, century == "XXI"),
             aes(factor(cyl), hwy, fill = cyl.f)) +
  stat_summary(geom = "col", fun = mean, width = 2/3) +
  labs(x = "Number of cylinders", y = NULL, title = "Means") +
  my_scale_fill

data.tb <- tibble(x = c(7, 7), 
                  y = c(44, 44), 
                  century = factor(c("XX", "XXI")),
                  plot = list(p1, p2))

ggplot() +
  geom_plot(data = data.tb, aes(x, y, label = plot)) +
  geom_point(data = my.mpg, aes(displ, hwy, colour = cyl.f)) +
  labs(x = "Engine displacement (l)", y = "Fuel use efficiency (MPG)",
       colour = "Engine cylinders\n(number)") +
  scale_colour_manual(guide = FALSE, 
                    values = c("red", "orange", "darkgreen", "blue"),
                    breaks = levels(my.mpg$cyl.f)) +
  facet_wrap(~century, ncol = 1)

输入图像描述这里

'ggplot2' >= 3.0.0 makes possible new approaches for adding insets, as now tibble objects containing lists as member columns can be passed as data. The objects in the list column can be even whole ggplots... The latest version of my package 'ggpmisc' provides geom_plot(), geom_table() and geom_grob(), and also versions that use npc units instead of native data units for locating the insets. These geoms can add multiple insets per call and obey faceting, which annotation_custom() does not. I copy the example from the help page, which adds an inset with a zoom-in detail of the main plot as an inset.

library(tibble)
library(ggpmisc)
p <-
  ggplot(data = mtcars, mapping = aes(wt, mpg)) +
  geom_point()

df <- tibble(x = 0.01, y = 0.01,
             plot = list(p +
                         coord_cartesian(xlim = c(3, 4),
                                         ylim = c(13, 16)) +
                         labs(x = NULL, y = NULL) +
                         theme_bw(10)))
p +
  expand_limits(x = 0, y = 0) +
  geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot))

ggplot with ggplot as inset

Or a barplot as inset, taken from the package vignette.

library(tibble)
library(ggpmisc)
p <- ggplot(mpg, aes(factor(cyl), hwy, fill = factor(cyl))) +
  stat_summary(geom = "col", fun.y = mean, width = 2/3) +
  labs(x = "Number of cylinders", y = NULL, title = "Means") +
  scale_fill_discrete(guide = FALSE)

data.tb <- tibble(x = 7, y = 44, 
                  plot = list(p +
                                theme_bw(8)))

ggplot(mpg, aes(displ, hwy, colour = factor(cyl))) +
  geom_plot(data = data.tb, aes(x, y, label = plot)) +
  geom_point() +
  labs(x = "Engine displacement (l)", y = "Fuel use efficiency (MPG)",
       colour = "Engine cylinders\n(number)") +
  theme_bw()

enter image description here

The next example shows how to add different inset plots to different panels in a faceted plot. The next example uses the same example data after splitting it according to the century. This particular data set once split adds the problem of one missing level in one of the inset plots. As these plots are built on their own we need to use manual scales to make sure the colors and fill are consistent across the plots. With other data sets this may not be needed.

library(tibble)
library(ggpmisc)
my.mpg <- mpg
my.mpg$century <- factor(ifelse(my.mpg$year < 2000, "XX", "XXI"))
my.mpg$cyl.f <- factor(my.mpg$cyl)
my_scale_fill <- scale_fill_manual(guide = FALSE, 
                                   values = c("red", "orange", "darkgreen", "blue"),
                                   breaks = levels(my.mpg$cyl.f))

p1 <- ggplot(subset(my.mpg, century == "XX"),
             aes(factor(cyl), hwy, fill = cyl.f)) +
  stat_summary(geom = "col", fun = mean, width = 2/3) +
  labs(x = "Number of cylinders", y = NULL, title = "Means") +
  my_scale_fill

p2 <- ggplot(subset(my.mpg, century == "XXI"),
             aes(factor(cyl), hwy, fill = cyl.f)) +
  stat_summary(geom = "col", fun = mean, width = 2/3) +
  labs(x = "Number of cylinders", y = NULL, title = "Means") +
  my_scale_fill

data.tb <- tibble(x = c(7, 7), 
                  y = c(44, 44), 
                  century = factor(c("XX", "XXI")),
                  plot = list(p1, p2))

ggplot() +
  geom_plot(data = data.tb, aes(x, y, label = plot)) +
  geom_point(data = my.mpg, aes(displ, hwy, colour = cyl.f)) +
  labs(x = "Engine displacement (l)", y = "Fuel use efficiency (MPG)",
       colour = "Engine cylinders\n(number)") +
  scale_colour_manual(guide = FALSE, 
                    values = c("red", "orange", "darkgreen", "blue"),
                    breaks = levels(my.mpg$cyl.f)) +
  facet_wrap(~century, ncol = 1)

enter image description here

红尘作伴 2024-10-27 19:19:32

我更喜欢与 ggsave 一起使用的解决方案。经过大量谷歌搜索后,我最终得到了这个(这是定位和调整插入的绘图大小的通用公式。

library(tidyverse)

plot1 = qplot(1.00*mpg, 1.00*wt, data=mtcars)  # Make sure x and y values are floating values in plot 1
plot2 = qplot(hp, cyl, data=mtcars)
plot(plot1)

# Specify position of plot2 (in percentages of plot1)
# This is in the top left and 25% width and 25% height
xleft   = 0.05
xright  = 0.30
ybottom = 0.70
ytop    = 0.95 

# Calculate position in plot1 coordinates
# Extract x and y values from plot1
l1 = ggplot_build(plot1)
x1 = l1$layout$panel_ranges[[1]]$x.range[1]
x2 = l1$layout$panel_ranges[[1]]$x.range[2]
y1 = l1$layout$panel_ranges[[1]]$y.range[1]
y2 = l1$layout$panel_ranges[[1]]$y.range[2]
xdif = x2-x1
ydif = y2-y1
xmin  = x1 + (xleft*xdif)
xmax  = x1 + (xright*xdif)
ymin  = y1 + (ybottom*ydif)
ymax  = y1 + (ytop*ydif) 

# Get plot2 and make grob
g2 = ggplotGrob(plot2)
plot3 = plot1 + annotation_custom(grob = g2, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
plot(plot3)

ggsave(filename = "test.png", plot = plot3)

# Try and make a weird combination of plots
g1 <- ggplotGrob(plot1)
g2 <- ggplotGrob(plot2)
g3 <- ggplotGrob(plot3)

library(gridExtra)
library(grid)

t1 = arrangeGrob(g1,ncol=1, left = textGrob("A", y = 1, vjust=1, gp=gpar(fontsize=20)))
t2 = arrangeGrob(g2,ncol=1, left = textGrob("B", y = 1, vjust=1, gp=gpar(fontsize=20)))
t3 = arrangeGrob(g3,ncol=1, left = textGrob("C", y = 1, vjust=1, gp=gpar(fontsize=20)))

final = arrangeGrob(t1,t2,t3, layout_matrix = cbind(c(1,2), c(3,3)))
grid.arrange(final)

ggsave(filename = "test2.png", plot = final)

显示插图和相对复杂布局的图像

I prefer solutions that work with ggsave. After a lot of googling around I ended up with this (which is a general formula for positioning and sizing the plot that you insert.

library(tidyverse)

plot1 = qplot(1.00*mpg, 1.00*wt, data=mtcars)  # Make sure x and y values are floating values in plot 1
plot2 = qplot(hp, cyl, data=mtcars)
plot(plot1)

# Specify position of plot2 (in percentages of plot1)
# This is in the top left and 25% width and 25% height
xleft   = 0.05
xright  = 0.30
ybottom = 0.70
ytop    = 0.95 

# Calculate position in plot1 coordinates
# Extract x and y values from plot1
l1 = ggplot_build(plot1)
x1 = l1$layout$panel_ranges[[1]]$x.range[1]
x2 = l1$layout$panel_ranges[[1]]$x.range[2]
y1 = l1$layout$panel_ranges[[1]]$y.range[1]
y2 = l1$layout$panel_ranges[[1]]$y.range[2]
xdif = x2-x1
ydif = y2-y1
xmin  = x1 + (xleft*xdif)
xmax  = x1 + (xright*xdif)
ymin  = y1 + (ybottom*ydif)
ymax  = y1 + (ytop*ydif) 

# Get plot2 and make grob
g2 = ggplotGrob(plot2)
plot3 = plot1 + annotation_custom(grob = g2, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
plot(plot3)

ggsave(filename = "test.png", plot = plot3)

# Try and make a weird combination of plots
g1 <- ggplotGrob(plot1)
g2 <- ggplotGrob(plot2)
g3 <- ggplotGrob(plot3)

library(gridExtra)
library(grid)

t1 = arrangeGrob(g1,ncol=1, left = textGrob("A", y = 1, vjust=1, gp=gpar(fontsize=20)))
t2 = arrangeGrob(g2,ncol=1, left = textGrob("B", y = 1, vjust=1, gp=gpar(fontsize=20)))
t3 = arrangeGrob(g3,ncol=1, left = textGrob("C", y = 1, vjust=1, gp=gpar(fontsize=20)))

final = arrangeGrob(t1,t2,t3, layout_matrix = cbind(c(1,2), c(3,3)))
grid.arrange(final)

ggsave(filename = "test2.png", plot = final)

Image showing inset and relatively complex layout

唯憾梦倾城 2024-10-27 19:19:32

2019年,patchwork包登场,你可以用它来创建
插图
通过使用 inset_element() 函数轻松实现:

require(ggplot2)
require(patchwork)

gg1 = ggplot(iris, aes(Sepal.Length, Sepal.Width)) +
  geom_point()

gg2 = ggplot(iris, aes(Sepal.Length)) +
  geom_density()

gg1 +
  inset_element(gg2, left = 0.65, bottom = 0.75, right = 1, top = 1)

在此处输入图像描述

In 2019, the patchwork package entered the stage, with which you can create
insets
easily by using the inset_element() function:

require(ggplot2)
require(patchwork)

gg1 = ggplot(iris, aes(Sepal.Length, Sepal.Width)) +
  geom_point()

gg2 = ggplot(iris, aes(Sepal.Length)) +
  geom_density()

gg1 +
  inset_element(gg2, left = 0.65, bottom = 0.75, right = 1, top = 1)

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文