R语言:如何循环绘制筛选数据并结合facet_grid分面展示?
问题描述
- 作为R语言新手,现有如下数据框:
# 数据结构 df <- structure(list(Time = c(0, 0, 0), Node = 1:3, Depth = c(0, -10, -20), Head = c(-1000, -1000, -1000), Moisture = c(0.166, 0.166, 0.166), HeadF = c(-1000, -1000, -1000), MoistureF = c(0.004983, 0.004983, 0.004983), Flux = c(-0.00133, -0.00133, -0.00133), FluxF = c(-0.00122, -0.00122, -0.00122), Sink = c(0, 0, 0 ), Transf = c(0, 0, 0), TranS = c(0, 0, 0), Temp = c(20, 20, 20), ConcF = c(0, 0, 0), ConcM = c(0, 0, 0)), row.names = c(NA, 3L), class = "data.frame")
- 需求:筛选
Depth为-20、-40、-60、-80、-100的数据分别绘图,标题随深度动态变化,并用facet_grid将图并排展示。已能绘制单张TranS vs Time图(颜色映射Transf,使用scale_color_viridis)。 - 尝试的代码及报错:
plot_d20 <- plot_node %>% filter(plot_node$Depth == -20) plot_d40 <- plot_node %>% filter(plot_node$Depth == -40) plot_d60 <- plot_node %>% filter(plot_node$Depth == -60) plot_d80 <- plot_node %>% filter(plot_node$Depth == -80) plot_d100 <- plot_node %>% filter(plot_node$Depth == -100) depth_plot <- c(plot_d20,plot_d40,plot_d60,plot_d80,plot_d100) for (p in depth_plot){ ggpS<-ggplot(p, aes(Time, TranS, color=Transf) ) + geom_point(alpha = 1)+ scale_color_viridis(option = "D")+ scale_x_continuous(limits = c(0,1400), breaks = seq(0,1400,200))+ ggtitle('Solute Mass Transfer for depth = 20mm') ggpS }
报错信息:data must be a data frame, or another object coercible by fortify(), not a numeric vector。
- 疑问:如何设置动态标题;颜色已用于
Transf,如何区分其他分组。
解决方案
错误原因
用c()合并多个数据框时,R会将数据框拆解为单个数值向量,循环时p变成了数值向量而非数据框,导致ggplot报错。
正确实现步骤
1. 筛选目标深度数据
无需拆分数据框,直接筛选出需要的Depth值:
library(tidyverse) # 假设原始数据框为plot_node target_depths <- c(-20, -40, -60, -80, -100) filtered_data <- plot_node %>% filter(Depth %in% target_depths)
2. 用facet实现并排展示+动态标题
使用facet_wrap配合自定义标签器,自动生成动态标题:
# 自定义标签函数,将Depth转为友好的标题文本 depth_label <- function(x) { paste0("Solute Mass Transfer\nDepth = ", abs(x), "mm") } # 绘制图形 ggplot(filtered_data, aes(x = Time, y = TranS, color = Transf)) + geom_point(alpha = 1) + scale_color_viridis(option = "D") + scale_x_continuous(limits = c(0, 1400), breaks = seq(0, 1400, 200)) + facet_wrap(~Depth, labeller = labeller(Depth = depth_label)) + theme_bw() + theme(strip.text = element_text(size = 10, face = "bold")) # 调整标题样式
3. 若需单独绘制每张图(可选)
如果需要单独导出每张图,用purrr::map循环处理每个深度:
# 按Depth拆分数据为列表 depth_data_list <- filtered_data %>% group_split(Depth) # 循环生成每张图 plots <- map(depth_data_list, function(data) { current_depth <- abs(unique(data$Depth)) ggplot(data, aes(x = Time, y = TranS, color = Transf)) + geom_point(alpha = 1) + scale_color_viridis(option = "D") + scale_x_continuous(limits = c(0, 1400), breaks = seq(0, 1400, 200)) + ggtitle(paste0("Solute Mass Transfer for Depth = ", current_depth, "mm")) + theme_bw() }) # 查看所有图 walk(plots, print)
4. 分组区分方案(解决颜色占用问题)
如果需要在图中区分其他分组(如Node),可通过以下方式补充映射:
- 用**形状(shape)**映射分组变量:
aes(..., shape = factor(Node)) - 用**大小(size)**映射分组变量:
aes(..., size = Node) - 用点的填充色(fill)(需选择带填充的形状,如shape=21-25):
aes(..., fill = factor(Node))+geom_point(shape=21, color="black")
示例代码:
ggplot(filtered_data, aes(x = Time, y = TranS, color = Transf, shape = factor(Node))) + geom_point(alpha = 1, size = 2) + scale_color_viridis(option = "D") + scale_shape_manual(values = c(16, 17, 18)) + # 自定义形状 facet_wrap(~Depth, labeller = labeller(Depth = depth_label)) + theme_bw()
内容的提问来源于stack exchange,提问作者Muru
相关产品推荐
相关产品推荐

