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

如何基于R tidyverse计算离散时序曲线的山谷区域面积

解决方案

计算逻辑说明

和需求匹配的计算规则如下:

  • 首行数据、当日y值小于等于前一日y值(下降或持平)时,当日a值直接为0
  • 当日y值大于前一日时:
    1. 找到当前行左侧最近的、y值大于等于当日y值的行位置j
    2. 取j和当前行中间的所有日期区间,计算当日y值乘以区间天数,减去区间内所有y值的总和,得到的结果就是当日的a值
      该逻辑完全匹配给出的测试数据预期结果,计算结果的单位也符合回淹规模m²·天的业务定义。

基于tidyverse的实现代码

# 加载依赖包
library(tidyverse)
library(lubridate)

# 构造测试数据
dat <- tibble(
  d = seq.Date(ymd("2021-01-01"), ymd("2021-01-10"), by = "1 day"),
  y = c(100,95,90,70,50,55,60,75,85,90),
  expected_a = c(0,0,0,0,0,5,15,65,115,145)
)

# 线性时间复杂度的计算函数,适配18万行级别的大数据量
calc_reflood_area <- function(y) {
  n <- length(y)
  a <- numeric(n)
  # 单调栈存储左侧递减的y值对应行号和数值,保证查找最近符合要求的j的效率
  stack <- list()
  
  for (i in 1:n) {
    # 下降/持平/首行直接返回0
    if (i == 1 || y[i] <= y[i-1]) {
      a[i] <- 0
    } else {
      # 弹出栈内所有小于当前y值的元素
      while (length(stack) > 0 && stack[[length(stack)]][2] < y[i]) {
        stack <- stack[-length(stack)]
      }
      j <- stack[[length(stack)]][1]
      interval_sum <- sum(y[(j+1):(i-1)])
      a[i] <- y[i] * (i - j - 1) - interval_sum
    }
    # 维护单调栈的递减特性
    while (length(stack) > 0 && stack[[length(stack)]][2] <= y[i]) {
      stack <- stack[-length(stack)]
    }
    stack[[length(stack) + 1]] <- c(i, y[i])
  }
  return(a)
}

# 执行计算
dat <- dat %>%
  mutate(a = calc_reflood_area(y))

运行后得到的a列和测试数据给出的预期值完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 03:36:09