如何在不补全缺失行的前提下高效计算含缺失数据的卷积(R语言)
高效计算非均匀时间点的储罐液体剩余量
我们需要模拟一个挥发性液体储罐:液体以固定速率蒸发,储罐不定期接收液体,目标是仅在每次添加液体时计算罐内当前的液体总量。
原方案通过tidyr::complete补全所有时间点后再做卷积,在数据量大时效率极低,且补全的空行无实际用途。以下是无需补全行的高效实现方案:
核心思路
我们只关心有液体添加的时间点,对于每个添加时间t_i,罐内剩余量等于所有历史添加量到t_i时刻的衰减值之和。这里用指数衰减模型,衰减公式为:衰减后量 = 初始添加量 * exp(-衰减率 * (当前时间 - 添加时间))
实现步骤
1. 预处理原始数据
首先将原始数据按时间排序,确保后续计算的时间顺序正确:
library(tidyverse) set.seed(123) original_data <- tibble( t = sample(50, 10, replace = FALSE), amount_incoming = runif(n = 10) ) %>% arrange(t) # 按时间升序排列,这是计算的基础
2. 定义衰减参数
这里沿用原方案的指数衰减率rate=1:
decay_rate <- 1
3. 高效计算剩余量
方法一:向量化矩阵运算(推荐,大数据量下更高效)
通过生成时间差矩阵,一次性计算所有历史添加量的衰减值,再按行求和得到每个时间点的剩余量:
# 生成时间差矩阵:每行对应一个当前时间,每列对应一个历史添加时间 time_diff_matrix <- outer(original_data$t, original_data$t, function(current_t, past_t) current_t - past_t) # 过滤掉时间差为负的情况(当前时间早于历史添加时间,无意义) time_diff_matrix[time_diff_matrix < 0] <- 0 # 计算所有历史添加量的衰减值,并按行求和 decayed_amounts <- original_data$amount_incoming * exp(-decay_rate * time_diff_matrix) amount_held <- rowSums(decayed_amounts) # 合并结果 convolved_data <- original_data %>% mutate(amount_held = amount_held)
方法二:逐行循环(小数据量下简洁直观)
用map_dbl遍历每个时间点,计算历史衰减量之和:
convolved_data <- original_data %>% mutate( amount_held = map_dbl(t, ~ sum(amount_incoming * exp(-decay_rate * (.x - t)))) )
方案优势
- 无需补全大量空行,避免了
complete函数带来的内存和时间开销; - 利用R的向量化运算(矩阵操作)替代循环,效率远高于补全行后做卷积的方案;
- 结果仅保留有实际意义的添加时间点,数据量更小。
内容的提问来源于stack exchange,提问作者Chechy Levas
相关产品推荐
相关产品推荐

