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

R新手求助:如何处理同列多变量并绘制带设备区分的水质时序图

解决思路:数据整理 + 时间序列绘图

第一步:数据清洗与整理

你的数据第一行是单位说明,需要先移除;然后把日期转为R能识别的格式,把数值列转为数值型(处理像<0.009这类特殊值),最后把两台设备的指标合并到同一结构里,方便后续绘图。

1.1 加载必要包

library(tidyverse)  # 包含数据处理工具dplyr和绘图工具ggplot2
library(lubridate)  # 简化日期格式转换

1.2 导入并清洗数据

先把你提供的数据集赋值给变量,再执行清洗步骤:

# 赋值你提供的数据集
df <- structure(list(Sample.Id = c(NA, "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "3", "3", "3", "3", "3", "3", "3", "3", "3"), Sampling..Date = c(NA, "08-Sep-14", "14-Oct-14", "02-Nov-14", "21-Nov-14", "03-Dec-14", "15-Dec-14", "11-Jan-15", "08-Feb-15", "01-Mar-15", "06-Apr-15", "03-Sep-14", "08-Sep-14", "14-Oct-14", "02-Nov-14", "21-Nov-14", "03-Dec-14", "15-Dec-14", "11-Jan-15", "26-Jan-15"), Tot.P = c("µg/ml", "0.002", "0.017", "0.035", "0.04", "0.059", "0.155", "0.021", "0.022", "0.025", "<0.009", "0.021", "0.003", "0.036", "0.141", "0.041", "0.044", "0.01", "0.023", "0.016"), DOC = c("µg/ml", NA, "12.3", "13.4", "12.5", "9.9", "14.7", "8.8", "8.3", "0.026", "7.5", "13.4", NA, "14.6", "16.6", "14.7", "12.6", "12.6", "10.6", "11.4"), Tot.N = c("µg/ml", NA, "3.63", "4.12", "3.98", "4.08", "3.38", "3.63", "4.88", "8.3", "2.74", "2.48", NA, "3.07", "3.38", "3.3", "3.43", "2.19", "2.77", "4.25"), DOC.1 = c("µg/ml", "13.6", NA, NA, NA, NA, NA, NA, NA, NA, NA, "14.44", "16.85", NA, NA, NA, NA, NA, NA, NA), Tot.P.1 = c("µg/ml", "0.053", NA, NA, NA, NA, NA, NA, NA, NA, NA, "0.08", "0.071", NA, NA, NA, NA, NA, NA, NA), Total.N = c("µg/ml", "3.363", NA, NA, NA, NA, NA, NA, NA, NA, NA, "2.645", "2.637", NA, NA, NA, NA, NA, NA, NA)), row.names = c(NA, 20L), class = "data.frame")

# 1. 移除第一行(单位说明行)
df_clean <- df[-1, ]

# 2. 转换日期格式:将字符型日期转为R可识别的Date类型
df_clean$Sampling..Date <- dmy(df_clean$Sampling..Date)

# 3. 处理特殊数值:去除"<"符号后转为数值型
convert_to_numeric <- function(x) {
  x <- gsub("<", "", x)
  as.numeric(x)
}

# 对所有指标列应用转换函数
df_clean <- df_clean %>%
  mutate(
    # 设备1的指标
    Tot.P = convert_to_numeric(Tot.P),
    DOC = convert_to_numeric(DOC),
    Tot.N = convert_to_numeric(Tot.N),
    # 设备2的指标(统一列名,方便后续合并)
    Tot.P.1 = convert_to_numeric(Tot.P.1),
    DOC.1 = convert_to_numeric(DOC.1),
    Total.N = convert_to_numeric(Total.N),
    # 站点ID转为因子,方便分组
    Sample.Id = as.factor(Sample.Id)
  )

1.3 重塑数据(宽转长)

把当前的宽格式数据转为长格式,让ggplot2能按指标、设备分组绘图:

# 整理设备1的数据
device1_data <- df_clean %>%
  select(Sample.Id, Sampling..Date, Tot.P, DOC, Tot.N) %>%
  pivot_longer(cols = c(Tot.P, DOC, Tot.N), 
               names_to = "Indicator", 
               values_to = "Value") %>%
  mutate(Device = "设备1") %>%
  drop_na(Value)  # 移除缺失值

# 整理设备2的数据(重命名列名和设备1统一)
device2_data <- df_clean %>%
  select(Sample.Id, Sampling..Date, Tot.P.1, DOC.1, Total.N) %>%
  rename(Tot.P = Tot.P.1, DOC = DOC.1, Tot.N = Total.N) %>%
  pivot_longer(cols = c(Tot.P, DOC, Tot.N), 
               names_to = "Indicator", 
               values_to = "Value") %>%
  mutate(Device = "设备2") %>%
  drop_na(Value)

# 合并两台设备的数据
final_data <- bind_rows(device1_data, device2_data)

第二步:提取设备时段(用于绘制阴影)

从整理好的数据中提取每个站点、设备的时间范围,用来绘制区分时段的阴影:

time_ranges <- final_data %>%
  group_by(Sample.Id, Device) %>%
  summarise(
    start_date = min(Sampling..Date),
    end_date = max(Sampling..Date)
  ) %>%
  ungroup()

第三步:绘制时间序列图(带设备时段阴影)

用ggplot2绘制分站点、分指标的时间序列图,同时用阴影区分不同设备的监测时段:

ggplot(final_data, aes(x = Sampling..Date, y = Value, color = Device)) +
  # 绘制设备时段阴影(透明度0.2避免遮挡数据)
  geom_rect(data = time_ranges, 
            aes(xmin = start_date, xmax = end_date, 
                ymin = -Inf, ymax = Inf, fill = Device),
            alpha = 0.2, inherit.aes = FALSE) +
  # 绘制数据点和折线
  geom_point(size = 2) +
  geom_line(alpha = 0.7) +
  # 按指标和站点分面展示,y轴自适应数据范围
  facet_grid(Indicator ~ Sample.Id, scales = "free_y") +
  # 设置图表标签
  labs(x = "采样日期", y = "浓度 (µg/ml)", color = "设备", fill = "设备") +
  # 优化样式:旋转x轴日期避免重叠
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

代码说明

  • geom_rect用来绘制阴影时段,inherit.aes = FALSE避免继承主图层的颜色映射;
  • facet_grid将不同指标(总磷/总氮/DOC)和站点分开显示,scales="free_y"让每个子图的y轴适配自身数据;
  • 旋转x轴日期是为了避免日期标签重叠,提升可读性。

额外提示

如果你的完整数据(2014-2022)包含更多站点和时段,只需替换初始的df数据集即可复用代码,程序会自动识别每个设备的时间范围并绘制对应阴影。

内容的提问来源于stack exchange,提问作者Forsaken_PhD

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 17:45:28