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

如何在R的data.table中实现分组及多条件EMA计算?

将dplyr分组计算EMA的代码改写为data.table版本

需求背景

刚接触data.table包,希望用它替代dplyr实现分组计算指数加权移动平均(EMA)——大数据集下data.table的运算效率更有优势。核心难点是如何替代dplyr中case_when()的多条件逻辑,针对不同cat值设置不同的EMA窗口参数。

原dplyr代码

library(tidyverse)
library(data.table)
library(TTR)
set.seed(0)

par <- rep(paste("Par", 1:5), each = 100)
cat <- rep(LETTERS[1:5], each = 100)
val <- rnorm(500, 100, 20)

df <- data.frame(par, cat, val)

new_df <- df %>%
  group_by(par, cat) %>%
  mutate(acute = EMA(val, n = 7, ratio = 2 / (1 + 7))) %>%
  mutate(chron = case_when(
    cat == "A" ~ EMA(val, n = 42, ratio = 2 / (1 + 42)),
    cat == "B" ~ EMA(val, n = 28, ratio = 2 / (1 + 28)),
    cat %in% c("C", "D", "E") ~ EMA(val, n = 14, ratio = 2 / (1 + 14))
  ))

data.table改写版本

library(data.table)
library(TTR)
set.seed(0)

# 生成数据并转为data.table
par <- rep(paste("Par", 1:5), each = 100)
cat <- rep(LETTERS[1:5], each = 100)
val <- rnorm(500, 100, 20)

dt <- data.table(par, cat, val)

# 分组计算EMA
dt[, {
  # 根据当前组的cat值确定chron对应的窗口参数n
  n_chron <- fcase(
    cat == "A", 42,
    cat == "B", 28,
    cat %in% c("C", "D", "E"), 14
  )[1] # 每个分组cat值一致,取第一个即可
  
  .(
    acute = EMA(val, n = 7, ratio = 2 / (1 + 7)),
    chron = EMA(val, n = n_chron, ratio = 2 / (1 + n_chron))
  )
}, by = .(par, cat)]

关键说明

  1. 分组逻辑:by = .(par, cat)等价于dplyr的group_by(par, cat),实现按par和cat的组合分组计算。
  2. 多条件替代:用data.table的fcase()替代dplyr的case_when(),语法规则一致,支持多分支条件判断。
  3. 效率优化:因为每个分组内的cat值完全相同,所以只需要计算一次n_chron并取第一个值即可,避免对组内每个元素重复执行条件判断,提升运算速度。
  4. 列更新方式:用{}包裹内部逻辑,先计算中间参数再生成结果列,代码更简洁易读,也符合data.table的高效编程习惯。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 03:33:16