简体   繁体   English

打印存储在列表中的 ggplot 对象时不会保留方面标签

[英]Facet Labels not being retained when printing ggplot objects stored in a list

Here is the data that I will be using to give context to my question:以下是我将用于为我的问题提供上下文的数据:

library(dplyr)
library(tidyr)
library(ggplot2)

set.seed(1)
f1 <- sample(c(letters[1:3],NA),100, prob = c(rep((0.9/3),times = 3),0.1),replace = T)
f2 <- sample(c(letters[1:3],NA),100, prob = c(rep((0.8/3),times = 3),0.2),replace = T)
f3 <- sample(c(letters[1:3],NA),100, prob = c(rep((0.95/3),times = 3),0.01),replace = T)

sample_dat <- tibble(
  x1 = factor(f1, level=letters[1:3]),
  x2 = factor(f2, level=letters[1:3]),
  x3 = factor(f3, level=letters[1:3]),
  grpA = factor(sample(c("grp1","grp2"),100, prob=c(0.3, 0.7) ,replace=T), 
    levels = c("grp1", "grp2"))
  
)

sample_dat

here is a function that I created to prepare the data for plotting:这是我创建的一个函数,用于准备绘图数据:

plot_data_prepr <- function(dat, groupvar, mainvar){
  
  groupvar <- sym(groupvar)
  mainvar <- sym(mainvar)
  
  plot_data <- dat %>% 
    group_by(!!groupvar) %>% 
    count(!!mainvar, .drop = F) %>% drop_na() %>% 
    mutate(pct = n/sum(n),
         pct2 = ifelse(n == 0, 0.005, n/sum(n)),
         grp_tot = sum(n),
         pct_lab = paste0(format(pct*100, digits = 1),'%'),
         pct_pos = pct2 + .02)
  
  return(plot_data)
}

here is the application of the function to produce the data sets I will use for plotting这是函数的应用程序来生成我将用于绘图的数据集

plot_data_prepr(dat = sample_dat, groupvar = "grpA", mainvar = "x1")
plot_data_prepr(dat = sample_dat, groupvar = "grpA", mainvar = "x2")
plot_data_prepr(dat = sample_dat, groupvar = "grpA", mainvar = "x3")

here I use a for loop to plot the data and dynamically change the labels of the facets -- if one runs this in rstudio as an RMarkdown file, one can see that the plots are produced and the labels for the facets are each distinct as they should be given the different degrees of missingness and sampling densities for the 'grpA' variable.在这里,我使用 for 循环绘制数据并动态更改构面的标签——如果在 rstudio 中将其作为 RMarkdown 文件运行,则可以看到生成的图和构面的标签各不相同应该给出“grpA”变量的不同程度的缺失和采样密度。

plot_list <- vector('list', length = 0)

for (fct in names(sample_dat)[1:3]){
  
  mvar <- fct
  smvar <- sym(mvar)
  
  gvar <- "grpA"
  sgvar <- sym(gvar)
  
  
dd <- plot_data_prepr(dat = sample_dat, groupvar = gvar, mainvar = mvar)

pre_lookup <- dd %>% 
  select(!!sgvar, grp_tot) %>% 
  group_by(!!sgvar) %>% 
  summarise(lookup = mean(grp_tot))


lookup <- pre_lookup$lookup

  my_label <- function(x) {
    var <- names(x)[1]
    list(paste0(x[[var]], " (N = ", lookup, ")"))
  }
  
  
  plot <- ggplot(dd,
         mapping = aes(x=!!smvar, y = pct2, fill = !!smvar)) +
    geom_bar(stat = 'identity') +
    ylim(0,1.3) +
    geom_text(aes(x=!!smvar, label=pct_lab, y = pct_pos + .02)) +
    facet_grid(as.formula(paste0(".~", gvar)), labeller = my_label) +
    ggtitle(paste(gvar,"by",mvar))
  
  plot_list[[fct]] <- plot
  
  print(plot)

}

Here's my problem -- when I print the plots which are stored in the list, they all seem to retain the facet label from the last plot, instead of retaining the distinct facet-labels they displayed when they were originally generated.这是我的问题——当我打印存储在列表中的图时,它们似乎都保留了最后一个图中的刻面标签,而不是保留它们最初生成时显示的不同刻面标签。

for (name in names(sample_dat)[1:3]){
  print(plot_list[[name]])
}

Basically, I would like to be able to print the plots from the list when I need them and have them display their distinct facet labels as they had been displayed when the plots were originally produced.基本上,我希望能够在我需要它们时从列表中打印这些图,并让它们显示它们独特的方面标签,就像它们在最初制作这些图时所显示的那样。

Perhaps someone in the community could help me?也许社区中的某个人可以帮助我?

I would suggest you try to avoid the loop for the plots building.我建议你尽量避免情节建设的循环。 It uses to create that kind of issues as you have with labels or sometimes with data.它用于创建与标签或有时与数据有关的那种问题。 Here, I have packaged your loop in a function and stored the results in a list.在这里,我将您的循环打包在一个函数中,并将结果存储在一个列表中。 Also, you can use lapply() with the names of your data in order to directly create the list with the plots.此外,您可以将lapply()与您的数据名称一起使用,以便直接创建带有绘图的列表。 Here the code:这里的代码:

#Function for plot
myplotfun <- function(fct)
{
  mvar <- fct
  smvar <- sym(mvar)
  
  gvar <- "grpA"
  sgvar <- sym(gvar)
  
  
  dd <- plot_data_prepr(dat = sample_dat, groupvar = gvar, mainvar = mvar)
  
  pre_lookup <- dd %>% 
    select(!!sgvar, grp_tot) %>% 
    group_by(!!sgvar) %>% 
    summarise(lookup = mean(grp_tot))
  
  
  lookup <- pre_lookup$lookup
  
  
  my_label <- function(x) {
    var <- names(x)[1]
    list(paste0(x[[var]], " (N = ", lookup, ")"))
  }
  
  
  plot <- ggplot(dd,
                 mapping = aes(x=!!smvar, y = pct2, fill = !!smvar)) +
    geom_bar(stat = 'identity') +
    ylim(0,1.3) +
    geom_text(aes(x=!!smvar, label=pct_lab, y = pct_pos + .02)) +
    facet_grid(as.formula(paste0(".~", gvar)), labeller = my_label) +
    ggtitle(paste(gvar,"by",mvar))
  
  return(plot)
}

Now, we create a list:现在,我们创建一个列表:

#Create a list
plot_list <- lapply(names(sample_dat)[1:3],myplotfun)

Finally, the plots as you used in the last loop:最后,您在最后一个循环中使用的图:

#Loop
for (i in 1:length(plot_list)){
  plot(plot_list[[i]])
}

Outputs:输出:

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

The problem is your my_label function has a free variable lookup that's only resolved when you actually plot the function.问题是你的my_label函数有一个自由变量lookup ,只有在你实际绘制函数时才会解决。 After your for-loop runs, then you it only contains the last value in the loop.在 for 循环运行后,它只包含循环中的最后一个值。 To capture the current loop value, you can place it inside an enclosure.要捕获当前回路值,您可以将其放置在外壳内。 So you could change the my_label function to所以你可以将my_label函数更改为

  my_labeler <- function(lookup) {
    function(x) {
      var <- names(x)[1]
      list(paste0(x[[var]], " (N = ", lookup, ")"))
    }
  }

and then call facet_grid with然后调用facet_grid

  facet_grid(as.formula(paste0(".~", gvar)), labeller = my_labeler(lookup))

But I agree with @Duck that avoiding the for-loop in this case would be easier.但我同意@Duck 在这种情况下避免 for 循环会更容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM