首页 > 解决方案 > 在 lapply 语句中访问 .SD 属性

问题描述

当我使用 data.table 执行 .SD 操作时,我经常遇到在 lapply/.SD 语句中访问列名属性会很有用的情况。通常,当我需要执行涉及外部 data.table 列的 data.table 操作时,会出现此类情况。

例如,假设我有一个dt包含两列的 data.table。此外,我有 data.tablemult用作“乘法矩阵”,例如,它包含我希望与其中的列dt相乘的因子。

dt = data.table(Val1 = rep(1,5), Val2 = rep(2,5))
mult = data.table(Val1 = 5, Val2 = 10)

> dt
   Val1 Val2
1:    1    2
2:    1    2
3:    1    2
4:    1    2
5:    1    2

> mult
   Val1 Val2
1:    5   10

在这个基本示例中,我想将Val1Val2dt的相应乘法因子相乘mult。使用基数 R,可以使用以下语句应用sapply

mat = sapply(colnames(dt), function(x){
  dt[[x]] * mult[[x]]
})

> data.table(mat)
   Val1 Val2
1:    5   20
2:    5   20
3:    5   20
4:    5   20
5:    5   20

现在,这是可行的,因为sapply它应用于 的列名dt,而不是列本身。

假设我想使用 data.table/.SD 执行相同的操作。这里的问题是,考虑到我们遍历整个子集,而不是名称,我无法找到在 lapply 语句中访问“当前”列名的方法。因此,我无法mult从 lapply 语句中的表中索引和获取适当的乘法因子。

我想做的伪代码如下:

dt[, lapply(.SD, function(x){

 # name = name of the iterated xth column in .SD, i.e. first 'Val1' and then 'Val2' )
 # return(x*mult[[name]])  

}), .SDcols = c('Val1', 'Val2')]

我知道在 lapply 语句(即lapply(1:ncol(dt)){...})中使用表达索引可以使用变通方法,但我想了解使用 .SD 是否可行。

先感谢您。

标签: rdata.table

解决方案


您可以将该Map函数mult用作向量:

mult <- c(5, 10)
dt[, Map("*", .SD, mult), .SDcols = c("Val1", "Val2")]

更新

如果 mult 需要是 adata.table因为只使用列的子集,您可以使用它。这应该可以解决您的问题:设置的列.SDcols乘以 中的相应列mult,而无需考虑排序、尺寸等。

dt = data.table(Val1 = rep(1,5), Val2 = rep(2,5), Val3 = rep(3, 5))
mult = data.table(Val1 = 5, Val2 = 10, Val3 = 15)

dt[, Map("*", .SD, mult[, names(.SD), with = FALSE]), .SDcols = c("Val1", "Val3")]
#    Val1 Val3
# 1:    5   45
# 2:    5   45
# 3:    5   45
# 4:    5   45
# 5:    5   45

推荐阅读