如何通过循环索引调用变量并批量生成ggplot图表?
Solution
First, fix the initial data setup by defining n (your sample code was missing this):
n <- 100 d <- data.frame( school = rep(LETTERS[1:4], times = c(25, 25, 25, 25)), student = rep(1:25, times = 4), week = rep(seq(from = 1, to = 25, by = 5), each = 25), # Adjusted to match school/student counts crit1fl = sample(0:1, n, replace = TRUE), crit2fl = sample(0:1, n, replace = TRUE), crit3fl = sample(0:1, n, replace = TRUE) )
Working Loop for Batch Plotting
Use the .data pronoun to reference string variable names correctly, and store/print all plots:
library(tidyverse) library(scales) # Define list of criteria variables critvars <- paste0("crit", 1:3, "fl") # Create a list to store plots (optional but useful) plot_list <- list() for (varname in critvars) { # Calculate proportions for current criteria d2 <- d %>% count(school, week, .data[[varname]]) %>% group_by(school, week) %>% mutate(prop = n / sum(n)) %>% ungroup() # Generate plot current_plot <- d2 %>% ggplot(aes(x = as.factor(week), y = n, fill = .data[[varname]])) + geom_bar(position = "fill", stat = "identity") + facet_wrap(~school) + geom_text( aes(label = percent(prop)), position = position_fill(vjust = 1.5), color = "white", data = d2 %>% filter(.data[[varname]] == 1) ) + labs( title = paste("Proportion meeting", varname), y = "Proportion", x = "Week" ) + scale_fill_discrete(name = varname) # Update legend title # Print plot to display it print(current_plot) # Store plot in list for later use plot_list[[varname]] <- current_plot # Optional: Save plot to file # ggsave(paste0(varname, "_plot.png"), current_plot, width = 10, height = 6) }
Key Fixes Explained
Correct Variable Reference:
- Your original
{{ varname }}didn't work becausevarnameis a string, and{{ }}expects a bare variable name. Using.data[[varname]]lets you access columns directly by string, which is perfect for loops with dynamic variable names.
- Your original
Display/Store All Plots:
- You were overwriting the
gvariable each iteration, so only the last plot was retained. By printing each plot inside the loop and storing them in a list (plot_list), you'll see all plots and can access them later.
- You were overwriting the
Dynamic Filter for
geom_text:- Replaced the hardcoded
crit1fl == 'Y'with.data[[varname]] == 1(matching your 0/1 variable values) to filter the text data correctly for each criteria.
- Replaced the hardcoded
Clearer Plot Labels:
- Updated the title and legend name to include the current criteria variable, making each plot's purpose obvious.
Alternative: Using Symbol Conversion
If you prefer tidy evaluation with symbols instead of .data, you can convert the string to a symbol with sym() and unquote it with !!:
for (varname in critvars) { crit_sym <- sym(varname) d2 <- d %>% count(school, week, !!crit_sym) %>% group_by(school, week) %>% mutate(prop = n / sum(n)) %>% ungroup() current_plot <- d2 %>% ggplot(aes(x = as.factor(week), y = n, fill = !!crit_sym)) + geom_bar(position = "fill", stat = "identity") + facet_wrap(~school) + geom_text( aes(label = percent(prop)), position = position_fill(vjust = 1.5), color = "white", data = d2 %>% filter(!!crit_sym == 1) ) + labs( title = paste("Proportion meeting", varname), y = "Proportion", x = "Week" ) + scale_fill_discrete(name = varname) print(current_plot) plot_list[[varname]] <- current_plot }
This achieves the same result—choose whichever syntax you find more readable.
内容的提问来源于stack exchange,提问作者glor
相关产品推荐
相关产品推荐

