如何在data.table上应用向量函数vsum以获得正确结果?
问题:向量求和函数在data.table上怎么正常用?
我写了一个对两个向量求和的函数:
vsum = \(s) s[1] + s[2]
它在data.frame里跑完全没问题:
> vsum(expand.grid(1:2,2:3)) Var1 1 3 2 4 3 4 4 5
但换成data.table调用就出问题了,结果完全不对:
> library(data.table) > vsum(CJ(1:2,2:3)) V1 V2 <int> <int> 1: 2 5
额外说明:我不想改成需要传两个变量的函数。
解决办法
为啥会错?因为data.table是按列存储的,你用s[1]取的是整个第一列,不是每行的第一个元素,所以函数实际是把两列各自求和,不是逐行加。下面几种方法不用改函数核心逻辑(或仅微调)就能搞定:
方法1:转成data.frame再传
直接把data.table转成data.frame格式传入函数,就和原来的用法完全一致:
vsum(as.data.frame(CJ(1:2,2:3)))
输出和data.frame里的结果相同:
Var1 1 3 2 4 3 4 4 5
方法2:用data.table的逐行操作调用
不用改函数,调用时借助.SD(当前行的数据集)和.I(行索引)实现逐行处理:
CJ(1:2,2:3)[, vsum(.SD), .I]
输出:
.I V1 1: 1 3 2: 2 4 3: 3 4 4: 4 5
方法3:微调函数适配两种类型
如果允许稍微修改函数,可以让它自动识别输入类型,同时兼容data.frame和data.table:
vsum = \(s) { if (is.data.table(s)) { rowSums(s[, 1:2]) } else { s[1] + s[2] } }
现在不管传哪种格式,都能输出正确的逐行求和结果:
> vsum(CJ(1:2,2:3)) [1] 3 4 4 5
内容的提问来源于stack exchange,提问作者Mohit
相关产品推荐
相关产品推荐

