You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 07:45:49