如何在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)]
关键说明
- 分组逻辑:
by = .(par, cat)等价于dplyr的group_by(par, cat),实现按par和cat的组合分组计算。 - 多条件替代:用data.table的
fcase()替代dplyr的case_when(),语法规则一致,支持多分支条件判断。 - 效率优化:因为每个分组内的cat值完全相同,所以只需要计算一次
n_chron并取第一个值即可,避免对组内每个元素重复执行条件判断,提升运算速度。 - 列更新方式:用
{}包裹内部逻辑,先计算中间参数再生成结果列,代码更简洁易读,也符合data.table的高效编程习惯。
内容的提问来源于stack exchange,提问作者user13973103
相关产品推荐
相关产品推荐

