打印存储在列表中的 ggplot 对象时不保留 Facet 标签
Facet Labels not being retained when printing ggplot objects stored in a list
这是我将用来为我的问题提供上下文的数据:
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
这是我创建的用于准备绘图数据的函数:
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)
}
这里是生成数据集的函数应用程序,我将用于绘图
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")
这里我使用 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)
}
这是我的问题 -- 当我打印存储在列表中的图时,
他们似乎都保留了上一个图中的刻面标签,而不是保留
它们最初生成时显示的不同面标签。
for (name in names(sample_dat)[1:3]){
print(plot_list[[name]])
}
基本上,我希望能够打印列表中的图
当我需要它们并让它们显示不同的面标签时
因为它们是最初制作地块时显示的。
也许社区中有人可以帮助我?
我建议你尽量避免地块建筑的循环。它用于创建标签或有时数据时遇到的那种问题。在这里,我将您的循环打包在一个函数中,并将结果存储在一个列表中。此外,您可以将 lapply()
与数据名称一起使用,以便直接创建包含图表的列表。这里的代码:
#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)
}
现在,我们创建一个列表:
#Create a list
plot_list <- lapply(names(sample_dat)[1:3],myplotfun)
最后,您在上一个循环中使用的图:
#Loop
for (i in 1:length(plot_list)){
plot(plot_list[[i]])
}
输出:
问题是您的 my_label
函数有一个自由变量 lookup
只有当您实际绘制函数时才会解决。 for-loop 运行后,它只包含循环中的最后一个值。要捕获当前循环值,您可以将其放置在外壳内。因此,您可以将 my_label
函数更改为
my_labeler <- function(lookup) {
function(x) {
var <- names(x)[1]
list(paste0(x[[var]], " (N = ", lookup, ")"))
}
}
然后用
调用facet_grid
facet_grid(as.formula(paste0(".~", gvar)), labeller = my_labeler(lookup))
但我同意@Duck 的观点,在这种情况下避免 for-loop 会更容易。
这是我将用来为我的问题提供上下文的数据:
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
这是我创建的用于准备绘图数据的函数:
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)
}
这里是生成数据集的函数应用程序,我将用于绘图
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")
这里我使用 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)
}
这是我的问题 -- 当我打印存储在列表中的图时, 他们似乎都保留了上一个图中的刻面标签,而不是保留 它们最初生成时显示的不同面标签。
for (name in names(sample_dat)[1:3]){
print(plot_list[[name]])
}
基本上,我希望能够打印列表中的图 当我需要它们并让它们显示不同的面标签时 因为它们是最初制作地块时显示的。
也许社区中有人可以帮助我?
我建议你尽量避免地块建筑的循环。它用于创建标签或有时数据时遇到的那种问题。在这里,我将您的循环打包在一个函数中,并将结果存储在一个列表中。此外,您可以将 lapply()
与数据名称一起使用,以便直接创建包含图表的列表。这里的代码:
#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)
}
现在,我们创建一个列表:
#Create a list
plot_list <- lapply(names(sample_dat)[1:3],myplotfun)
最后,您在上一个循环中使用的图:
#Loop
for (i in 1:length(plot_list)){
plot(plot_list[[i]])
}
输出:
问题是您的 my_label
函数有一个自由变量 lookup
只有当您实际绘制函数时才会解决。 for-loop 运行后,它只包含循环中的最后一个值。要捕获当前循环值,您可以将其放置在外壳内。因此,您可以将 my_label
函数更改为
my_labeler <- function(lookup) {
function(x) {
var <- names(x)[1]
list(paste0(x[[var]], " (N = ", lookup, ")"))
}
}
然后用
调用facet_grid
facet_grid(as.formula(paste0(".~", gvar)), labeller = my_labeler(lookup))
但我同意@Duck 的观点,在这种情况下避免 for-loop 会更容易。