在data.table的lapply中组合rollapplyr与weighted.mean遇类型错误
问题原因分析
你猜的完全没错,这个错误确实和id=67只有1条数据直接相关。当分组的行数小于滚动窗口宽度(这里是3)时,rollapplyr返回的NA是逻辑类型(logical),而其他有足够数据的组返回的是数值类型(double)。data.table对列的类型一致性要求非常严格,不同组返回的同列类型必须完全统一,所以就抛出了类型不匹配的错误。
而你单独运行rollapplyr(ratio, ...)时没问题,是因为整个向量长度足够,即使前两个位置是NA,那也是数值型的NA,类型始终统一。但分组后单条数据的组,rollapplyr无法生成任何有效计算结果,返回的fill=NA会默认是逻辑型,这就和其他组的数值型结果产生了冲突。
解决方案
有两种简单的方法可以解决这个问题,核心都是保证所有组返回的结果类型统一为数值型:
方法1:强制转换结果为数值型
在rollapplyr的结果外层包一层as.numeric(),把逻辑型NA转成数值型NA,这样所有组的结果类型就完全一致了:
DT[, lapply(.SD, function(x) as.numeric(rollapplyr(x, width = 3, weighted.mean, w = c(0.2, 0.3, 0.5), align = 'right', fill = NA))), by = id, .SDcols = 'ratio']
方法2:先判断分组长度,针对性处理
可以先检查每组的行数,如果小于窗口宽度,直接返回对应长度的数值型NA;否则执行滚动计算,这种方式逻辑更清晰:
DT[, lapply(.SD, function(x) { if (length(x) < 3) { rep(NA_real_, length(x)) # 明确生成数值型NA } else { rollapplyr(x, width = 3, weighted.mean, w = c(0.2, 0.3, 0.5), align = 'right', fill = NA) } }), by = id, .SDcols = 'ratio']
验证结果
运行上面任意一段代码,都会得到符合预期的结果:
id=67的组会返回1个数值型NAid=39和id=58的组会正常生成滚动加权平均值
内容的提问来源于stack exchange,提问作者koteletje
相关产品推荐
相关产品推荐

