r - data.table 错误 : lapply on . SD 在使用 get() 时对列重新排序。可能的解决方法?

标签 r data.table

我发现了 data.table 的奇怪行为.我想知道是否有办法避免它或解决方法。

在我的数据管理中,我经常使用 lapply.SD , 为列分配新值。要正确分配几列,lapply 的输出列的顺序必须保留。
我发现情况并非如此。

这里的正常行为

library(data.table)
plouf <- data.table(x = 1, y = 2, z = 3)
cols <- c("y","x")
plouf[,.SD,.SDcols = cols ,by = z]
plouf[,lapply(.SD,function(x){x}),.SDcols = cols ,by = z]
plouf[,lapply(.SD[x == 1],function(x){x}),.SDcols = cols ,by = z]

所有这些行给出:
   z y x
1: 3 2 1

例如,我需要将其重新分配给 c("y","x")。但如果我这样做:
plouf[,lapply(.SD[get("x") == 1],function(x){x}),.SDcols = c("y","x"),by = z]

   z x y
1: 3 1 2

这里 x 和 y 的顺序无缘无故改变了,它应该产生与上一个“工作”示例相同的结果。如果然后将错误的值分配给 c("y","x")如果我分配 lapply 的输出到新的列向量。好像是用geti .SD 的一部分触发此错误。

这对分配的影响示例:
plouf[, c(cols ) := lapply(.SD[get("x") == 1],function(x){x}),
      .SDcols = cols ,by = z][]
#    x y z
# 1: 2 1 3

有没有人有解决方法?我使用的代码看起来更像是:
 plouf[, c(cols ) := lapply(.SD[get("x") >= 1 & get("x") <= 3],function(x){mean}),
          .SDcols = cols ,by = z]

github 上的问题:https://github.com/Rdatatable/data.table/issues/4089

最佳答案

而不是子集.SD ,您可以在 lapply 函数中进行子集化。如果用于子集的逻辑向量作为第三个参数传递给 lapply,则不会在每次 lapply 传递时重新评估。

注意:我将函数更改为乘以 10,否则我根本无法判断代码是否在执行任何操作

plouf[, (cols) := lapply(.SD, function(x, i) 10*mean(x[i]), 
                         get("x") %between% c(1, 3)), 
      .SDcols = cols ,by = z][]

#     x  y z
# 1: 10 20 3

还有其他解决方法可以让您对 .SD 进行子集化,但我认为子集化 .SD按组比单独对每一列进行子集化要慢。
set.seed(0)
df <- rep(1:50000, sample(500:1000, 50000, T)) %>% 
        data.table(a = runif(length(.))
                  ,b = .)

library(microbenchmark)
microbenchmark(
  subSD = df[, lapply(.SD[a < .2], sum), b]
  , in_func = df[, lapply(.SD, function(x, i) sum(x[i]), a < .2), b]
  , times = 10L)

# Unit: milliseconds
#     expr      min         lq      mean     median        uq       max neval cld
#    subSD 19323.19 20398.3666 21289.345 20708.4346 22466.010 23738.467    10   b
#  in_func   972.64   987.7891  1016.252   995.4236  1038.069  1125.709    10  a 

编辑:更大的基准
set.seed(0)
rm(df)
df <- rep(1:5e5, sample(50:100, 5e5, T)) %>% 
        data.table(a = runif(length(.))
                  ,b = .)

library(microbenchmark)
microbenchmark(
  subSD = df[, lapply(.SD[a < .2], sum), b]
  , in_func = df[, lapply(.SD, function(x, i) sum(x[i]), a < .2), b]
  , times = 2L)

# Unit: seconds
#     expr        min         lq       mean     median        uq       max neval cld
#    subSD 207.111290 207.111290 214.147649 214.147649 221.18401 221.18401     2   b
#  in_func   3.560467   3.560467   3.651359   3.651359   3.74225   3.74225     2  a 

关于r - data.table 错误 : lapply on . SD 在使用 get() 时对列重新排序。可能的解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59176071/

相关文章:

r - split 和 data.table 的问题

r - data.table或dplyr-数据操作

r - 将多图 ggplots 与拼凑图和单个图例对齐

r - 将行名称更改为 R 的 data.frame 中的数字索引

r - 在 MacBookAir 上使用 file.choose() 选择多个文件不起作用

python - 简单数据操作 : R vs python

r - 在 R 中找到至少有三年数据的所有航类

r - 是否有一种合理的方式来考虑列表索引?

c - 如何从 C 创建一个新的 R 环境?

r - 使用 data.table 在每组数据前插入一行