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

如何计算河流温度时序中阈值上下的首次及持续达标日序?

问题与解决方案

问题需求

我有一个存储两条河流两年日温度时间序列的dataframe,需要针对每条河流和每一年,计算四个关键日序(doy,1月1日为1,12月31日为365):

  • 温度首次≥15℃的日序
  • 温度持续≥15℃的起始日序(持续指直到秋季不再出现低于15℃的情况)
  • 温度首次≤15℃的日序
  • 温度持续≤15℃的起始日序(持续指直到次年春季不再出现高于15℃的情况)

示例数据获取与预处理

以下是获取并预处理USGS水温数据的代码:

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

siteNumber <- c("01428500","01432805") # 美国地质调查局站点编号
parameterCd <- "00010" # 水温参数编码
statCd <- "00003" # 均值统计编码
startDate <- "2018-01-01"
endDate <- "2019-10-31"

dat <- readNWISdv(siteNumber, parameterCd, startDate, endDate, statCd=statCd) # 从USGS获取时间序列数据
dat <- dat[,c(2:4)]
colnames(dat)[3] <- "temperature"

# 可视化时间序列
ggplot(data = dat, aes(x = Date, y = temperature)) +
  geom_point() +
  theme_bw() +
  facet_wrap(~site_no)

# 添加年份和日序列(doy;1月1日=1,12月31日=365)
dat <- dat %>%
  mutate(year = year(Date),
         doy = yday(Date))

无效尝试代码

我曾尝试用filter()函数筛选,但无法得到目标结果:

dat %>%
  group_by(site_no,year) %>%
  filter(temperature >= 15 & temperature <= 15)

理想输出格式

期望得到如下结构的结果:

site_no year doy_firstabove15 doy_sustainedAbove15 doy_firstbelow15 doy_sustainedBelow15
1 01428500 2018              136                  144              253                  286
2 01428500 2019              140                  146              279                  289
3 01432805 2018              143                  143              272                  276
4 01432805 2019              140                  140              278                  278

解决方案代码

使用dplyr分组后结合逻辑筛选,可实现目标计算:

dat_result <- dat %>%
  group_by(site_no, year) %>%
  arrange(doy) %>% # 确保数据按日序升序排列
  mutate(
    above15 = temperature >= 15, # 标记温度≥15的日期
    below15 = temperature <= 15  # 标记温度≤15的日期
  ) %>%
  summarise(
    # 1. 当年首次温度≥15℃的日序
    doy_firstabove15 = first(doy[above15]),
    
    # 2. 持续≥15℃的起始日序:最后一次低温后的首个高温日(之后无低温)
    doy_sustainedAbove15 = {
      last_low_doy <- max(doy[!above15], na.rm = TRUE)
      if (is.infinite(last_low_doy)) first(doy) else first(doy[doy > last_low_doy & above15])
    },
    
    # 3. 当年首次温度≤15℃的日序(秋季降温首个达标日)
    doy_firstbelow15 = {
      last_high_doy <- max(doy[above15], na.rm = TRUE)
      if (is.infinite(last_high_doy)) first(doy) else first(doy[doy > last_high_doy & below15])
    },
    
    # 4. 持续≤15℃的起始日序:最后一次高温后的首个低温日(之后无高温)
    doy_sustainedBelow15 = {
      last_high_doy <- max(doy[above15], na.rm = TRUE)
      if (is.infinite(last_high_doy)) first(doy) else first(doy[doy > last_high_doy & below15])
    }
  ) %>%
  ungroup()

# 输出结果
print(dat_result)

代码逻辑说明

  • 先按站点和年份分组,确保数据按日序排序,保证时间顺序正确
  • 用above15和below15标记温度达标情况,简化后续筛选
  • doy_firstabove15直接取首个高温日的doy
  • doy_sustainedAbove15:找到当年最后一次低温日,取之后首个高温日,即为持续高温的起点
  • doy_firstbelow15和doy_sustainedBelow15:找到当年最后一次高温日,取之后首个低温日,分别对应秋季首次降温日和持续低温的起点

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:25:29