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

在R的ggplot中实现潮汐渐变背景与每日微塑料浓度关联图

问题:在ggplot分面图中为4天数据添加潮汐渐变背景

我需要用R的ggplot绘制一幅包含4天分面(facet_wrap)的图表,用来对比每日各采样时间点的微塑料浓度和潮汐数据。要求高潮对应深色渐变背景,低潮对应浅色渐变背景。参考日食背景渐变示例尝试时,因为潮汐数据依赖海拔值,出现了“离散值提供给连续刻度”(或反之)的错误。我可以从网站获取潮汐数据,但时间和采样时间不匹配;也可以手动在采样数据框中为对应时间添加水位数据,现在想请教如何把这些离散海拔值转换成4天对应的连续渐变背景。

以下是我尝试的代码:

high_tide_Day2LA = data.frame(start = as.POSIXct("2022-08-02 14:00:00"),
                      end = as.POSIXct("2022-08-02 15:00:00") )
tide_Day2LA = data.frame(start = as.POSIXct("2022-08-02 09:30:00"),
                         end = as.POSIXct("2022-08-02 15:20:00") )

color_dat_tideDay2LA = data.frame(time = seq(tide_Day2LA$start, tide_Day2LA$end, by = "1 min"))

color_dat_tideDay2LA = mutate(color_dat_tideDay2LA,
                   color = 0,
                   color = replace(color, 
                                   time < high_tide_Day2LA$start, 
                                   seq(100, 0, length.out = sum(time < high_tide_Day2LA$start) ) ),
                   color = replace(color, 
                                   time > high_tide_Day2LA$end, 
                                   seq(0, 100, length.out = sum(time > high_tide_Day2LA$end)) ) )

ggplot()+
  #geom_segment(data = color_dat_tideDay2LA,
               #aes(x = time, xend = time,
                  # y = -Inf, yend = Inf, color = color),
               #show.legend = FALSE)+
    #scale_color_gradient(low="lightblue",high="darkblue")+
  geom_point(data=df, aes(x=Date_time, y=MPs.m.3, shape=Location, colour=Location))+
  geom_line(data=df_loc, aes(x=Date_time, y=MPs.m.3, colour=Location))+
  geom_line(data=df_loc1, aes(x=Date_time, y=MPs.m.3, colour=Location))+
  scale_colour_manual(values = c("red", "purple"))+
  scale_y_continuous(limits = c(min(df$MPs.m.3), max(df$MPs.m.3)))+
  theme(panel.spacing = unit(1, "lines"), panel.grid.minor.x = element_blank() )+
  labs(x = "Dates and time of field work campaign", y = "MPs concentration per sample (MPs/m^3)")+
  facet_wrap(vars(Day), scales = "free_x", nrow = 4)

解决方案

1. 构建全时段连续潮汐背景数据集

先为4天分别定义潮汐时段(低潮起始、高潮起止、低潮结束),再生成1分钟间隔的连续时间序列,对应计算潮汐强度值(0=低潮,100=高潮,中间线性渐变),最后合并成关联分面Day变量的总数据集。

library(dplyr)
library(ggplot2)
library(lubridate)

# 定义4天的潮汐参数(替换为你的实际时间)
tide_days <- list(
  Day1 = list(
    low_start = ymd_hms("2022-08-01 06:00:00"),
    high_start = ymd_hms("2022-08-01 12:00:00"),
    high_end = ymd_hms("2022-08-01 13:00:00"),
    low_end = ymd_hms("2022-08-01 18:00:00"),
    day_label = "Day1"
  ),
  Day2 = list(
    low_start = ymd_hms("2022-08-02 09:30:00"),
    high_start = ymd_hms("2022-08-02 14:00:00"),
    high_end = ymd_hms("2022-08-02 15:00:00"),
    low_end = ymd_hms("2022-08-02 15:20:00"),
    day_label = "Day2"
  ),
  Day3 = list(
    # 添加Day3的潮汐时间参数
    day_label = "Day3"
  ),
  Day4 = list(
    # 添加Day4的潮汐时间参数
    day_label = "Day4"
  )
)

# 批量生成单天潮汐背景数据的函数
build_tide_bg <- function(tide_info) {
  time_seq <- seq(tide_info$low_start, tide_info$low_end, by = "1 min")
  tide_intensity <- case_when(
    # 低潮到高潮:强度从0线性升到100
    time_seq < tide_info$high_start ~ seq(0, 100, length.out = sum(time_seq < tide_info$high_start)),
    # 高潮时段:强度保持100
    between(time_seq, tide_info$high_start, tide_info$high_end) ~ 100,
    # 高潮到低潮:强度从100线性降到0
    time_seq > tide_info$high_end ~ seq(100, 0, length.out = sum(time_seq > tide_info$high_end))
  )
  data.frame(
    Date_time = time_seq,
    tide_intensity = tide_intensity,
    Day = tide_info$day_label
  )
}

# 合并4天的背景数据
tide_bg_data <- bind_rows(lapply(tide_days, build_tide_bg))

2. 绘制分面图并添加渐变背景

用geom_tile绘制背景(比geom_segment更高效),将背景图层放在最底层,通过Day变量匹配分面,同时避免刻度冲突:

ggplot() +
  # 潮汐渐变背景(alpha调整透明度,避免遮盖数据)
  geom_tile(data = tide_bg_data, 
            aes(x = Date_time, y = Inf, height = Inf, fill = tide_intensity),
            alpha = 0.3, show.legend = FALSE) +
  scale_fill_gradient(low = "lightblue", high = "darkblue") +
  # 绘制微塑料浓度数据
  geom_point(data = df, aes(x = Date_time, y = MPs.m.3, shape = Location, colour = Location)) +
  geom_line(data = df_loc, aes(x = Date_time, y = MPs.m.3, colour = Location)) +
  geom_line(data = df_loc1, aes(x = Date_time, y = MPs.m.3, colour = Location)) +
  scale_colour_manual(values = c("red", "purple")) +
  scale_y_continuous(limits = c(min(df$MPs.m.3), max(df$MPs.m.3))) +
  theme(panel.spacing = unit(1, "lines"), panel.grid.minor.x = element_blank()) +
  labs(x = "野外采样日期与时间", y = "微塑料浓度 (MPs/m³)") +
  facet_wrap(vars(Day), scales = "free_x", nrow = 4)

3. 处理离散水位数据的方法

如果是手动添加的离散水位值,用approx函数插值成连续时间序列的强度值,避免离散/连续刻度错误:

# 示例:离散水位数据(时间+水位值,0=低潮,5=高潮)
discrete_tide <- data.frame(
  Date_time = ymd_hms(c("2022-08-02 09:30:00", "2022-08-02 14:00:00", "2022-08-02 15:00:00", "2022-08-02 15:20:00")),
  water_level = c(0, 5, 5, 0)
)

# 插值为1分钟间隔的连续数据
continuous_tide <- approx(discrete_tide$Date_time, discrete_tide$water_level, 
                          xout = seq(min(discrete_tide$Date_time), max(discrete_tide$Date_time), by = "1 min"))

# 转换为背景数据集(关联Day变量)
tide_bg_day2 <- data.frame(
  Date_time = continuous_tide$x,
  tide_intensity = continuous_tide$y, # 直接用水位值作为强度,或归一化到0-100
  Day = "Day2"
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 22:32:10