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

如何在R中高效填充需依赖不同列前序行的数据框?

高效填充依赖前序行数据的计算表方法

我需要一种高效的方法来填充计算表,该表需借助不同列的前序行数据计算当前值。此前我曾提出类似问题但表述不清,现提供新的示例代码及当前使用的(速度较慢的)实现方式:

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


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

df

运行结果:

elevation inflow outflow storage stat
1          1      3     0.0     0.0  0.0
2          2      4     1.5     2.5  3.0
3          3      6     7.5     1.5  4.5
4          4      4     9.0    -0.5  9.0
5          5      3    10.5     1.5 13.5
6          6      5    16.5     2.0 15.0
7          7      6    19.5     1.5 18.0
8          8      7    22.5     2.5 22.5
9          9      8    28.5     2.0 27.0
10        10      9    33.0     3.0 33.0

优化方案

方案1:使用data.table快速迭代

data.table在处理逐行依赖计算时性能远优于基础R循环,尤其适合大数据集:

library(data.table)

dt = as.data.table(df)
dt[1, `:=`(outflow = 0, storage = 0, stat = 0)]

for(i in 2:nrow(dt)) {
  dt[i, outflow := dt[i-1, inflow]/2 + dt[i-1, stat] + dt[i-1, storage]]
  dt[i, storage := dt[i, inflow] - dt[i, outflow] + dt[i-1, stat]]
  dt[i, stat := dt[i-1, inflow] + dt[i-1, stat] - dt[i-1, storage]]
}

dt

方案2:数学简化+向量化运算

通过对递推公式推导,可以将循环转化为效率更高的向量化运算:

分析原始递推关系后,可简化得到以下表达式:

  • 第1行:outflow[1] = 0, storage[1] = 0, stat[1] = 0
  • 第i行(i≥2):
    • stat[i] = 2*stat[i-1] + inflow[i-1]/2
    • outflow[i] = stat[i]
    • storage[i] = inflow[i] + stat[i-1] - stat[i]

基于简化后的关系,用向量化方式实现:

# 初始化向量
n = nrow(df)
outflow = numeric(n)
storage = numeric(n)
stat = numeric(n)

outflow[1] = 0
storage[1] = 0
stat[1] = 0

# 简化循环计算
for(i in 2:n) {
  stat[i] = 2*stat[i-1] + df$inflow[i-1]/2
  outflow[i] = stat[i]
  storage[i] = df$inflow[i] + stat[i-1] - stat[i]
}

# 赋值回原数据框
df$outflow = outflow
df$storage = storage
df$stat = stat

df

也可以用purrr::accumulate实现无循环计算:

library(purrr)

# 用accumulate计算stat向量
stat_vec = accumulate(
  .x = df$inflow[-1],
  .f = function(prev_stat, inflow_prev) {
    2*prev_stat + inflow_prev/2
  },
  .init = 0
)

# 生成outflow和storage向量
outflow_vec = stat_vec
storage_vec = c(0, df$inflow[-1] + stat_vec[-length(stat_vec)] - stat_vec[-1])

# 赋值回数据框
df$outflow = outflow_vec
df$storage = storage_vec
df$stat = stat_vec

df

以上几种方式都能显著提升计算速度,其中数学简化后的向量化/累积运算效率最高,适合超大规模数据集;data.table方案则兼顾可读性和性能,代码改动成本低。

内容的提问来源于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:55:40