R语言中使用for循环处理嵌套数据框实现按塘系自动绘图的问题
问题原因
- 你在循环中直接对
comp_nested[2](即所有系统的嵌套数据列)整体执行unnest,每次循环都拿到了全量数据集,没有筛选当前迭代对应的单个塘系数据 - 绘图函数重复定义在循环内部,没有必要也会影响执行效率
- 现有代码没有自动存储每个塘系的绘图结果,只会展示最后一次循环生成的图表
解决方案
方案1:修改原有的for循环逻辑
首先把绘图函数提取到循环外部,每次迭代只展开当前塘系的嵌套数据:
# 先定义通用绘图函数 scatter_fun <- function(df, x_var, y_var = "Depth_in") { ggplot(df, aes(x = .data[[x_var]], y = .data[[y_var]], color = Season, shape = Pond)) + geom_point(size = 0.5) + scale_y_reverse() + theme( axis.text = element_text(size = 10), panel.background = element_rect(fill = "white", color = "black"), legend.key = element_rect(fill = "white"), legend.title = element_text(size = 10), legend.text = element_text(size = 10) ) + guides( size = "none", color = guide_legend(override.aes = list(size = 2)), shape = guide_legend(override.aes = list(size = 2)) ) + # 自动添加当前塘系的标题 ggtitle(unique(df$System)) } # 循环遍历每个塘系 for (sys_name in comp_nested$System) { # 只筛选当前塘系的嵌套数据,再展开 current_data <- comp_nested %>% filter(System == sys_name) %>% unnest(data) # 绘制当前塘系的氨氮散点图 p <- scatter_fun(current_data, x_var = "Ammonia_N") # 展示图片 print(p) # 如果需要批量保存可以取消下面的注释,自动按塘系命名存图 # ggsave(paste0(sys_name, "_Ammonia_N_depth.png"), p, width = 7, height = 5, dpi = 300) }
方案2:更适配tidyverse嵌套数据的写法(无需for循环)
直接用purrr::map遍历嵌套数据列,批量生成所有塘系的图表,存在列表里方便后续调用:
library(purrr) # 批量生成所有塘系的图表,存在plot列中 comp_nested <- comp_nested %>% mutate( # 生成氨氮的深度散点图 Ammonia_plot = map(data, ~scatter_fun(.x, x_var = "Ammonia_N")) # 如果要批量生成所有数值指标的图,可以用下一行的写法,替换掉上面的Ammonia_plot行 # all_plots = map(data, ~map(names(select(.x, where(is.numeric), -Depth_in)), function(var) scatter_fun(.x, x_var = var))) ) # 查看第一个塘系的图 comp_nested$Ammonia_plot[[1]] # 批量保存所有塘系的图 walk2(comp_nested$Ammonia_plot, comp_nested$System, ~ggsave(paste0(.y, "_Ammonia_N_depth.png"), .x, width =7, height=5, dpi=300))
扩展说明
如果需要为所有数值型测量指标批量生成对应图表,只需要把scatter_fun的x_var参数改为遍历所有数值列即可,无需重复写绘图逻辑。
内容的提问来源于stack exchange,提问作者Rachel Tenney
相关产品推荐
相关产品推荐

