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

如何在R的data.table中基于前一行值实现土壤含水量滚动计算?

解决方案:分组递推计算土壤含水量

这类依赖前一行结果的迭代计算,用滚动窗口函数(rollapply/frollapply)确实不适用——因为滚动函数是基于固定窗口的历史值做聚合,无法传递递推的状态。下面用R中常用的data.table和dplyr结合purrr::accumulate来实现需求:

步骤1:构造示例数据(可替换为你的数据集)

library(data.table)
library(purrr)
library(dplyr)

# 模拟站点数据:a(100), b(200), c(150)三个站点,各5个时段
set.seed(123)
dt <- data.table(
  site = rep(c("a", "b", "c"), each = 5),
  capacity = rep(c(100, 200, 150), each = 5),
  prc = sample(5:30, 15, replace = TRUE),
  evpt = sample(10:25, 15, replace = TRUE)
)

# 先计算change列(按你的规则)
dt[, change := ifelse(prc >= evpt, prc - evpt, exp(-((evpt - prc)/capacity)))]

步骤2:按站点分组计算含水量(content)

方法1:data.table + purrr::accumulate

accumulate会逐行迭代,将上一步的计算结果作为下一步的输入,完美匹配你的递推需求:

dt[, content := accumulate(
  .x = seq_len(.N),
  .f = function(prev_val, idx) {
    if (idx == 1) {
      # 初始值为站点最大持水量
      return(capacity[1])
    }
    # 按规则更新含水量
    if (prc[idx] >= evpt[idx]) {
      min(prev_val + change[idx], capacity[1])
    } else {
      prev_val * change[idx]
    }
  },
  .init = NULL
), by = site]

方法2:dplyr + purrr::accumulate

如果你更熟悉tidyverse语法:

dt_tidy <- dt %>%
  as_tibble() %>%
  group_by(site, capacity) %>%
  mutate(
    content = accumulate(
      .x = 1:n(),
      .f = function(prev_val, idx) {
        if (idx == 1) {
          capacity
        } else {
          if (prc[idx] >= evpt[idx]) {
            min(prev_val + change[idx], capacity)
          } else {
            prev_val * change[idx]
          }
        }
      }
    )
  ) %>%
  ungroup()

关键说明

  • 为什么rollapply/frollapply失败?这类函数的核心是固定窗口内的聚合计算,比如计算滑动均值,它不会把当前行的计算结果传递给下一行作为输入,因此无法处理这种"状态依赖"的递推逻辑。
  • 确保每个站点的capacity在分组内是唯一值(你的数据应该已经满足),否则需要调整分组逻辑保证每个组对应一个站点的固定容量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 13:13:19