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

如何高效计算需依赖前置行数据的数值?

高效填充依赖前置行数据的计算表

我需要一种高效的方法来填充计算表,该表需借助前置行的数据来获取当前行的数值。以下是我当前使用的低效实现代码示例:

df = data.frame(elevation = seq(1,10),
      inflow = c(3,4,6,4,3,5,6,7,8,9),
      outflow = NA,
      storage = NA)

for(i in 1:nrow(df)) {
  
  if (i == 1) {
    
    df$outflow[i] = 0
    df$storage[i] = 0
    
  } else {
    
    df$outflow[i] = df$inflow[i-1]/2 - df$storage[i-1]
    df$storage[i] = df$inflow[i] - df$outflow[i] + df$storage[i-1]
    
  }
  
}

df
#    elevation inflow outflow storage
# 1          1      3     0.0     0.0
# 2          2      4     1.5     2.5
# 3          3      6    -0.5     9.0
# 4          4      4    -6.0    19.0
# 5          5      3   -17.0    39.0
# 6          6      5   -37.5    81.5
# 7          7      6   -79.0   166.5
# 8          8      7  -163.5   337.0
# 9          9      8  -333.5   678.5
# 10        10      9  -674.5  1362.0

优化方案:推导递推公式 + 向量化/累积计算

原循环里的两个变量存在依赖关系,可以先推导storage的独立递推公式,避免嵌套计算:

将outflow[i] = inflow[i-1]/2 - storage[i-1]代入storage[i]的表达式:

storage[i] = inflow[i] - (inflow[i-1]/2 - storage[i-1]) + storage[i-1]
= inflow[i] - inflow[i-1]/2 + 2*storage[i-1]

基于这个公式,我们可以用两种高效方式实现:

方法1:基础R简化循环

只针对storage做循环,再批量计算outflow,减少数据框的修改次数:

df = data.frame(elevation = seq(1,10),
                inflow = c(3,4,6,4,3,5,6,7,8,9),
                outflow = NA,
                storage = NA)

# 初始化第一行
df$outflow[1] <- 0
df$storage[1] <- 0

# 用推导后的公式计算storage
for(i in 2:nrow(df)){
  df$storage[i] <- df$inflow[i] - df$inflow[i-1]/2 + 2*df$storage[i-1]
}

# 批量计算outflow
df$outflow[-1] <- df$inflow[-nrow(df)]/2 - df$storage[-nrow(df)]

df

方法2:用purrr::accumulate实现无循环计算

accumulate是底层优化的累积计算函数,比R原生for循环效率高很多,尤其适合大数据量场景:

library(purrr)
library(dplyr)

df = data.frame(elevation = seq(1,10),
                inflow = c(3,4,6,4,3,5,6,7,8,9))

df <- df %>%
  mutate(
    # 累积计算storage序列
    storage = accumulate(
      .x = 2:n(),
      .f = function(prev_storage, i) inflow[i] - inflow[i-1]/2 + 2*prev_storage,
      .init = 0
    ),
    # 批量计算outflow
    outflow = c(0, inflow[-n()]/2 - storage[-length(storage)])
  )

df

两种方法都能得到和原循环完全一致的结果,但效率提升明显——尤其是accumulate实现,避免了R循环的逐行开销,数据量越大优势越显著。

内容的提问来源于stack exchange,提问作者Vinicius B. de S. Moreira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:32:55