如何将单个数字乘以 data.table 中的混合格式列
How to multiply a single number by a mixed format column in data.table
我有以下 data.table,我希望将 a 列乘以 b 列,a 总是一个数字,b 列有时可能是一个向量:
library(data.table)
tt <- c(33,44)
dt <- data.table(a=list(1,2,3)
, b = list(11,22,tt))
dt[, t2 := sapply(b, function(x) x*a)]
我得到一个错误:Error in x * a : non-numeric argument to binary operator
因为 a 始终是单个数字,所以我预计第 3 行会起作用,即使 b 是一个向量。
我找到的解决方案是使用mapply:
dt[, t2 := mapply(function(x,y) x*y, a, b)]
为什么它不适用于 sapply/lapply?
dt$a[[1]] * dt$b
有效吗? (不。)虽然第一个参数是长度为 1 的向量,但第二个参数不是向量,它是 list
,并且 list
不进行算术运算。 sapply
仅迭代一个 list/vector 值,因此虽然 sapply(a, function(AA) AA * b)
似乎是一个好的开始,但 b
仍然反映出 list
因此无法完成。
您要做的是将 a[[1]]
乘以 b[[1]]
,然后将 a[[2]]
乘以 b[[2]]
,等等。这就是 Map
和 mapply
好好干。
关于它们之间关系的一些事情。
## equivalent
lapply(lst1, function(z) z + 1)
Map(function(z) z + 1, lst1)
## equivalent
sapply(lst1, function(z) z + 1)
mapply(function(z) z + 1, lst1)
这就是单向量处理。但是当你想同时迭代多个(两个或更多)vectors/lists,将它们“压缩”在一起时,有两种选择:
stopifnot(length(lst1) == length(lst2))
## equivalent
sapply(seq_along(lst1), function(ind) {
lst1[[ind]] * lst2[[ind]]
})
mapply(function(o1, o2) o1 * o2, lst1, lst2)
mapply(`*`, lst1, lst2)
了解它们的共性和差异:
sapply
和 mapply
将尽可能简化 return 值,因此他们可能 return 一个 vector
(如果 return 值为 1)、matrix
(如果 return 值为向量)或 list
(如果任何长度与其他长度不同)。您可以 force a list
with sapply(..., simplify=FALSE)
and mapply(..., SIMPLIFY=FALSE)
(case difference is important).
lapply
和Map
总是returnlist
s,不管以上条件;许多人发现这种输出一致性在编程意义上更 reliable/desirable(即 functions/packages)。
如果 vector/list 被命名,lapply
只会 return 一个命名的 list
,否则它只能在位置上索引;如果输入已命名或输入为 character
,所有其他人将自动命名 returned list
。 (可能还有更多 rules/exceptions,但这是一个开始。)
我有以下 data.table,我希望将 a 列乘以 b 列,a 总是一个数字,b 列有时可能是一个向量:
library(data.table)
tt <- c(33,44)
dt <- data.table(a=list(1,2,3)
, b = list(11,22,tt))
dt[, t2 := sapply(b, function(x) x*a)]
我得到一个错误:Error in x * a : non-numeric argument to binary operator
因为 a 始终是单个数字,所以我预计第 3 行会起作用,即使 b 是一个向量。
我找到的解决方案是使用mapply:
dt[, t2 := mapply(function(x,y) x*y, a, b)]
为什么它不适用于 sapply/lapply?
dt$a[[1]] * dt$b
有效吗? (不。)虽然第一个参数是长度为 1 的向量,但第二个参数不是向量,它是 list
,并且 list
不进行算术运算。 sapply
仅迭代一个 list/vector 值,因此虽然 sapply(a, function(AA) AA * b)
似乎是一个好的开始,但 b
仍然反映出 list
因此无法完成。
您要做的是将 a[[1]]
乘以 b[[1]]
,然后将 a[[2]]
乘以 b[[2]]
,等等。这就是 Map
和 mapply
好好干。
关于它们之间关系的一些事情。
## equivalent
lapply(lst1, function(z) z + 1)
Map(function(z) z + 1, lst1)
## equivalent
sapply(lst1, function(z) z + 1)
mapply(function(z) z + 1, lst1)
这就是单向量处理。但是当你想同时迭代多个(两个或更多)vectors/lists,将它们“压缩”在一起时,有两种选择:
stopifnot(length(lst1) == length(lst2))
## equivalent
sapply(seq_along(lst1), function(ind) {
lst1[[ind]] * lst2[[ind]]
})
mapply(function(o1, o2) o1 * o2, lst1, lst2)
mapply(`*`, lst1, lst2)
了解它们的共性和差异:
sapply
和mapply
将尽可能简化 return 值,因此他们可能 return 一个vector
(如果 return 值为 1)、matrix
(如果 return 值为向量)或list
(如果任何长度与其他长度不同)。您可以 force alist
withsapply(..., simplify=FALSE)
andmapply(..., SIMPLIFY=FALSE)
(case difference is important).lapply
和Map
总是returnlist
s,不管以上条件;许多人发现这种输出一致性在编程意义上更 reliable/desirable(即 functions/packages)。
如果 vector/list 被命名,lapply
只会 return 一个命名的list
,否则它只能在位置上索引;如果输入已命名或输入为character
,所有其他人将自动命名 returnedlist
。 (可能还有更多 rules/exceptions,但这是一个开始。)