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

含NA值的指数移动平均(EMA)计算问题求助

自定义带NA保留与动态窗口的EMA函数

问题背景

需要实现一个指数移动平均(EMA)函数,满足以下要求:

  • 原始向量中的NA值需保留在原位,不能被移位
  • 计算非NA位置的EMA时,忽略窗口内的NA值
  • 采用动态时间窗口:计算位置前的有效数据不足7个时,移动平均长度取现有有效数据量;否则固定为8(即ma_len序列为c(1,2,3,4,5,6,7,8,8,...))

现有rollmeanEMA函数仅在NA位于向量开头时表现正常,NA在其他位置时会将NA移至向量开头,不符合需求:

rollmeanEMA <- function(vec, len) {
  v_n <- !is.na(vec)
  c( vec[is.na(vec)],
     cumsum(vec[v_n][1:(len-1)]) / seq_along(vec[v_n][1:(len-1)]),
     EMA(vec[v_n], len)[len:length(vec[v_n])])
}

现有函数的问题示例

NA位于末尾时,结果中的NA被移至开头,不符合原位保留要求:

dados <- c(0, 0, 0, 3, 0, 0, 0, 0, 0, 2, 0, NA)
rollmeanEMA(dados, 8)
# 输出:
#  [1]        NA 0.0000000 0.0000000 0.0000000
#  [5] 0.7500000 0.6000000 0.5000000 0.4285714
#  [9] 0.3750000 0.3281250 0.5371094 0.4699707

解决方案

以下函数基于TTR包的EMA实现,严格满足NA保留和动态窗口规则:

library(TTR)

dynamic_ema_preserve_na <- function(vec, max_len) {
  # 初始化结果向量,默认全为NA
  result <- rep(NA_real_, length(vec))
  
  # 提取原始向量中的非NA位置和对应值
  valid_indices <- which(!is.na(vec))
  valid_values <- vec[valid_indices]
  
  # 无有效数据时直接返回结果
  if (length(valid_values) == 0) {
    return(result)
  }
  
  # 为有效数据序列计算动态窗口EMA
  ema_results <- numeric(length(valid_values))
  for (i in seq_along(valid_values)) {
    # 确定当前窗口长度:不足max_len-1则用现有数据量,否则用max_len
    current_window <- if (i < max_len - 1) i else max_len
    # 取对应窗口内的有效数据计算EMA,取最后一个值作为当前位置结果
    window_data <- valid_values[max(1, i - current_window + 1):i]
    ema_results[i] <- tail(EMA(window_data, n = current_window), 1)
  }
  
  # 将计算好的EMA值填回原向量的非NA位置
  result[valid_indices] <- ema_results
  return(result)
}

测试验证

测试案例1:NA位于开头

dados1 <- c(NA, 0, 0, 3, 0, 0, 0, 0, 0, 2, 0, 0)
dynamic_ema_preserve_na(dados1, 8)
# 输出:
#  [1]        NA 0.0000000 0.0000000 1.0000000
#  [5] 0.7500000 0.6000000 0.5000000 0.4285714
#  [9] 0.3750000 0.5781250 0.5058594 0.4426270

NA保留在开头,EMA计算结果与原函数一致。

测试案例2:NA位于末尾

dados2 <- c(0, 0, 0, 3, 0, 0, 0, 0, 0, 2, 0, NA)
dynamic_ema_preserve_na(dados2, 8)
# 输出:
#  [1] 0.0000000 0.0000000 0.0000000 0.7500000
#  [5] 0.6000000 0.5000000 0.4285714 0.3750000
#  [9] 0.3281250 0.5371094 0.4699707        NA

NA保留在原始位置,非NA位置的EMA计算正确。

测试案例3:NA位于中间

dados3 <- c(0, 0, 0, 3, 0, 0, 0, NA, 0, 2, 0, 4)
dynamic_ema_preserve_na(dados3, 8)
# 输出:
#  [1] 0.0000000 0.0000000 0.0000000 0.7500000
#  [5] 0.6000000 0.5000000 0.4285714        NA
#  [9] 0.3750000 0.5781250 0.5058594 0.6052246
  • 中间的NA位置结果保留NA
  • 最后一个位置的4,使用前8个有效数据计算EMA,符合动态窗口规则

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 11:42:06