在 R ggplot 的每个方面生成一个插图,同时保留原始方面内容的颜色

Apa*_*ura 9 r ggplot2 ggpmisc

我想生成一个图形,将图形的四个方面与每个方面的插图相结合,显示相应图的细节。这是我尝试过的事情之一:

    #create data frame

n_replicates <- c(rep(1:10,15),rep(seq(10,100,10),15),rep(seq(100,1000,100),15),rep(seq(1000,10000,1000),15))
sim_years <- rep(sort(rep((1:15),10)),4)
sd_data <- rep (NA,600)
for (i in 1:600) {
sd_data[i]<-rnorm(1,mean=exp(0.1 * sim_years[i]), sd= 1/n_replicates[i])
}
max_rep <- sort(rep(c(10,100,1000,10000),150))
data_frame <- cbind.data.frame(n_replicates,sim_years,sd_data,max_rep)


#do first basic plot
library(ggplot2)
plot1<-ggplot(data=data_frame, aes(x=sim_years,y=sd_data,group =n_replicates, col=n_replicates)) + 
  geom_line() + theme_bw() +
  labs(title ="",  x = "year", y = "sd")
plot1


#make four facets
my_breaks = c(2, 10, 100, 1000, 10000)
facet_names <- c(
  `10` = "2, 3, ..., 10 replicates",
  `100` = "10, 20, ..., 100 replicates",
  `1000` = "100, 200, ..., 1000 replicates",
  `10000` = "1000, 2000, ..., 10000 replicates"
)
plot2 <- plot1 + 
  facet_wrap( ~ max_rep, ncol=2, labeller = as_labeller(facet_names)) + 
  scale_colour_gradientn(name = "number of replicates", trans = "log",
                         breaks = my_breaks, labels = my_breaks, colours = rainbow(20))
plot2


#extract inlays (this is where it goes wrong I think)
library(ggpmisc)
library(tibble)
library(dplyr)
inset <- tibble(x = 0.01, y = 10.01,
                    plot = list(plot2 +
                                  facet_wrap( ~ max_rep, ncol=2, labeller = as_labeller(facet_names)) +
                                  coord_cartesian(xlim = c(13, 15),
                                                  ylim = c(3, 5)) +
                                  labs(x = NULL, y = NULL, color = NULL) +
                                  scale_colour_gradient(guide = FALSE) + 
                                  theme_bw(10)))

plot3 <- plot2 +
  expand_limits(x = 0, y = 0) +
  geom_plot_npc(data = inset, aes(npcx = x, npcy = y, label = plot)) + 
  annotate(geom = "rect", 
           xmin = 13, xmax = 15, ymin = 3, ymax = 5,
           linetype = "dotted", fill = NA, colour = "black") 

plot3
Run Code Online (Sandbox Code Playgroud)

这导致了以下图形: 情节3

如您所见,插图中的颜色是错误的,尽管我当然只想要相应的插图,但所有四种颜色都出现在每个方面。我在这里阅读了很多问题(甚至让我走到了这一步)以及 ggpmisc 用户指南中的一些示例,但不幸的是,我仍然对如何实现我想要的东西感到有些迷茫。除了可能通过手动提取四个插图然后将它们与 plot2 结合来完成。但我希望会有更好的方法来做到这一点。感谢您的帮助!

编辑:由于这个答案,现在更好的图形,但问题仍然部分未解决:

下面的代码做了很好的插入,但不幸的是颜色没有保留。在上面的版本中,每个插图都会重新呈现自己的彩虹色,而不是从它所属的刻面继承部分彩虹色阶。有谁知道为什么以及如何改变这一点?在评论中,我提出了另一个(坏)尝试来解决这个问题,它保留了颜色,但存在将所有四个插图放在每个方面的问题。

library(ggpmisc)
library(tibble)
library(dplyr)

# #extract inlays: good colours, but produces four insets.
# fourinsets <- tibble(#x = 0.01, y = 10.01,
#                      x = c(rep(0.01, 4)), 
#                      y = c(rep(10.01, 4)), 
#                     plot = list(plot2 +
#                                   facet_wrap( ~ max_rep, ncol=2) +
#                                   coord_cartesian(xlim = c(13, 15),
#                                                   ylim = c(3, 5)) +
#                                   labs(x = NULL, y = NULL, color = NULL) +
#                                   scale_colour_gradientn(name = "number of replicates", trans = "log", guide = FALSE,
#                                                          colours = rainbow(20)) +
#                                   theme(
#                                     strip.background = element_blank(),
#                                     strip.text.x = element_blank()
#                                   )
#                                 ))
# fourinsets$plot

library(purrr)
pp <- map(unique(data_frame$max_rep), function(x) {
  
  plot2$data <- plot2$data %>% filter(max_rep == x)
  plot2 + 
    coord_cartesian(xlim = c(12, 14),
                    ylim = c(3, 4)) +
    labs(x = NULL, y = NULL) +
    theme(
      strip.background = element_blank(),
      strip.text.x = element_blank(),
      legend.position = "none",
      axis.text=element_blank(),
      axis.ticks=element_blank()
    )
})
#pp[[2]]

inset_new <- tibble(x = c(rep(0.01, 4)), 
                    y = c(rep(10.01, 4)), 
                plot = pp, 
                max_rep = unique(data_frame$max_rep))

final_plot <- plot2 + 
  geom_plot_npc(data = inset_new, aes(npcx = x, npcy = y, label = plot, vp.width = 0.3, vp.height =0.6)) +
  annotate(geom = "rect", 
           xmin = 12, xmax = 14, ymin = 3, ymax = 4,
           linetype = "dotted", fill = NA, colour = "black") 


#final_plot

Run Code Online (Sandbox Code Playgroud)

final_plot 然后看起来像这样:

final_plot:错误颜色的好镶嵌

我希望这可以稍微澄清问题。任何想法都非常欢迎:)

Z.L*_*Lin 12

修改@user63230 的优秀答案:

pp <- map(unique(data_frame$max_rep), function(x) {  
  plot2 + 
    aes(alpha = ifelse(max_rep == x, 1, 0)) +
    coord_cartesian(xlim = c(12, 14),
                    ylim = c(3, 4)) +
    labs(x = NULL, y = NULL) +
    scale_alpha_identity() +
    facet_null() +
    theme(
      strip.background = element_blank(),
      strip.text.x = element_blank(),
      legend.position = "none",
      axis.text=element_blank(),
      axis.ticks=element_blank()
    )
})
Run Code Online (Sandbox Code Playgroud)

解释:

  1. 我们没有过滤传递到 plot2 的数据(这会影响颜色的映射),而是强加了一种新的美学alpha,其中属于其他重复编号的线条被分配为 0 以表示透明度;
  2. scale_alpha_identity()用于告诉 ggplot 将按原样使用alpha 映射:即 1 表示 100%,0 表示 0%。
  3. 添加facet_null()以覆盖 plot2 的现有facet_wrap,这将删除插图的构面。

阴谋

其他所有内容都与问题中的代码保持不变。


use*_*230 8

我认为这会让你开始,虽然它很难让插图的大小正确(当你包含一个图例时)。

#set up data
library(ggpmisc)
library(tibble)
library(dplyr)
library(ggplot2)

# create data frame
n_replicates <- c(rep(1:10, 15), rep(seq(10, 100, 10), 15), rep(seq(100, 
  1000, 100), 15), rep(seq(1000, 10000, 1000), 15))
sim_years <- rep(sort(rep((1:15), 10)), 4)
sd_data <- rep(NA, 600)
for (i in 1:600) {
  sd_data[i] <- rnorm(1, mean = exp(0.1 * sim_years[i]), sd = 1/n_replicates[i])
}
max_rep <- sort(rep(c(10, 100, 1000, 10000), 150))
data_frame <- cbind.data.frame(n_replicates, sim_years, sd_data, max_rep)

# make four facets
my_breaks = c(2, 10, 100, 1000, 10000)
facet_names <- c(`10` = "2, 3, ..., 10 replicates", `100` = "10, 20, ..., 100 replicates", 
  `1000` = "100, 200, ..., 1000 replicates", `10000` = "1000, 2000, ..., 10000 replicates")
Run Code Online (Sandbox Code Playgroud)

获取整体情节:

# overall facet plot
overall_plot <- ggplot(data = data_frame, aes(x = sim_years, y = sd_data, group = n_replicates, col = n_replicates)) + 
  geom_line() + 
  theme_bw() + 
  labs(title = "", x = "year", y = "sd") + 
  facet_wrap(~max_rep, ncol = 2, labeller = as_labeller(facet_names)) + 
  scale_colour_gradientn(name = "number of replicates", trans = "log", breaks = my_breaks, labels = my_breaks, colours = rainbow(20))

#plot
overall_plot
Run Code Online (Sandbox Code Playgroud)

这使:

在此处输入图片说明

然后从要提取每个图的整体图,请参见此处。我们可以map通过列表一次提取一个:

pp <- map(unique(data_frame$max_rep), function(x) {
  
  overall_plot$data <- overall_plot$data %>% filter(max_rep == x)
  overall_plot + # coord_cartesian(xlim = c(13, 15), ylim = c(3, 5)) +
  labs(x = NULL, y = NULL) + 
  theme_bw(10) + 
  theme(legend.position = "none")
  
})
Run Code Online (Sandbox Code Playgroud)

如果我们查看其中一个(我已经删除了图例),例如

pp[[1]]
#pp[[2]]
#pp[[3]]
#pp[[4]]
Run Code Online (Sandbox Code Playgroud)

给出:

在此处输入图片说明

然后我们想将这些插入图添加到数据框中,以便每个图都有自己的行:

inset <- tibble(x = c(rep(0.01, 4)), 
                y = c(rep(10.01, 4)), 
                plot = pp, 
                max_rep = unique(data_frame$max_rep))
Run Code Online (Sandbox Code Playgroud)

然后将其合并到整体情节中:

overall_plot + 
  expand_limits(x = 0, y = 0) + 
  geom_plot_npc(data = inset, aes(npcx = x, npcy = y, label = plot, vp.width = 0.8, vp.height = 0.8))
Run Code Online (Sandbox Code Playgroud)

给出:

在此处输入图片说明


teu*_*and 3

这是基于 Z. Lin 的答案的解决方案,但用于ggforce::facet_wrap_paginate()进行过滤并保持色阶一致。

首先,我们可以制作包含所有数据且没有分面的“根”图。

library(ggpmisc)
library(tibble)
library(dplyr)

n_replicates <- c(rep(1:10,15),rep(seq(10,100,10),15),rep(seq(100,1000,100),15),rep(seq(1000,10000,1000),15))
sim_years <- rep(sort(rep((1:15),10)),4)
sd_data <- rep (NA,600)
for (i in 1:600) {
  sd_data[i]<-rnorm(1,mean=exp(0.1 * sim_years[i]), sd= 1/n_replicates[i])
}
max_rep <- sort(rep(c(10,100,1000,10000),150))
data_frame <- cbind.data.frame(n_replicates,sim_years,sd_data,max_rep)


my_breaks = c(2, 10, 100, 1000, 10000)
facet_names <- c(
  `10` = "2, 3, ..., 10 replicates",
  `100` = "10, 20, ..., 100 replicates",
  `1000` = "100, 200, ..., 1000 replicates",
  `10000` = "1000, 2000, ..., 10000 replicates"
)

base <- ggplot(data=data_frame, 
                aes(x=sim_years,y=sd_data,group =n_replicates, col=n_replicates)) + 
  geom_line() + 
  theme_bw() +
  scale_colour_gradientn(
    name = "number of replicates",
    trans = "log10", breaks = my_breaks,
    labels = my_breaks, colours = rainbow(20)
  ) +
  labs(title ="",  x = "year", y = "sd")
Run Code Online (Sandbox Code Playgroud)

接下来,主要情节将只是带有 的根情节facet_wrap()

main <- base + facet_wrap(~ max_rep, ncol = 2, labeller = as_labeller(facet_names))
Run Code Online (Sandbox Code Playgroud)

然后新的部分是使用facet_wrap_paginatewithnrow = 1ncol = 1for every max_rep,我们将使用它作为插图。好处是,它可以进行过滤,并且使色标与根图保持一致。

nmax_rep <- length(unique(data_frame$max_rep))

insets <- lapply(seq_len(nmax_rep), function(i) {
  base + ggforce::facet_wrap_paginate(~ max_rep, nrow = 1, ncol = 1, page = i) +
    coord_cartesian(xlim = c(12, 14), ylim = c(3, 4)) +
    guides(colour = "none", x = "none", y = "none") +
    theme(strip.background = element_blank(),
          strip.text = element_blank(),
          axis.title = element_blank(),
          plot.background = element_blank())
})
insets <- tibble(x = rep(0.01, nmax_rep),
                 y = rep(10.01, nmax_rep),
                 plot = insets,
                 max_rep = unique(data_frame$max_rep))

main +
  geom_plot_npc(data = insets, 
                aes(npcx = x, npcy = y, label = plot,
                    vp.width = 0.3, vp.height = 0.6)) +
  annotate(geom = "rect", 
           xmin = 12, xmax = 14, ymin = 3, ymax = 4,
           linetype = "dotted", fill = NA, colour = "black") 
Run Code Online (Sandbox Code Playgroud)

由reprex 包(v0.3.0)于 2020 年 12 月 15 日创建