如何基于另一列条件为data.table分配函数列?
为什么用
fcase给data.table添加函数列会报错?怎么解决? 报错原因
data.table::fcase是为原子向量(数值、字符、逻辑值这类基础类型的向量)设计的分支工具,它要求返回值能被打包成标准的R向量。但min、max这类函数属于语言对象,不是原子类型,没法直接放进普通向量里。当你把函数传给fcase时,它尝试按普通向量规则分配内存,自然就会报类型/长度不匹配的错误。
data.table专属解决方案
因为我们要创建的是列表列(每个元素是一个函数),得用能生成列表列的赋值方式:
方法1:用ifelse构造列表列
通过list()把函数包裹成列表元素,让ifelse返回列表列:
test3 <- data.table(n = c(1, 1, 2, 2)) test3[, func := ifelse(n == 1, list(min), list(max))]
方法2:分组赋值(适合大数据量)
利用data.table的快速子集赋值,分别给不同n值的行分配函数:
test3 <- data.table(n = c(1, 1, 2, 2)) test3[n == 1, func := list(list(min))] test3[n == 2, func := list(list(max))]
这里内层list(min)把函数转为单个列表元素,外层list()告诉data.table要赋值的是列表列的内容。
方法3:用set()底层赋值(性能最优)
如果追求极致性能,用data.table的set()函数直接修改列:
test3 <- data.table(n = c(1, 1, 2, 2)) set(test3, i = which(test3$n == 1), j = "func", value = list(min)) set(test3, i = which(test3$n == 2), j = "func", value = list(max))
验证调用
和你之前的示例一样,调用函数时需要用[[1]]取出列表元素里的函数:
test3[1, func][[1]](c(3,5,1)) # 返回1(min函数结果) test3[3, func][[1]](c(3,5,1)) # 返回5(max函数结果)
内容的提问来源于stack exchange,提问作者gabagool
相关产品推荐
相关产品推荐

