簡體   English   中英

使用lapply和get時的data.table列順序

[英]data.table column order when using lapply and get

有人可以幫助我理解為什么下面的兩個版本的lapply操作使用和不使用get()不會產生相同的結果? 使用get()時,結果列會混淆。

dt <- data.table(v1 = c(1,2), v2 = c(3,4), type = c('A', 'B'))

   v1 v2 type
1:  1  3    A
2:  2  4    B

col_in <- c('v2', 'v1')
col_out <- paste0(col_in, '.new')

訪問'鍵入'硬編碼方式

dt[, (col_out) := lapply(.SD, function(x){x * min(x[type == 'A'])}), .SDcols = col_in]

產生預期的結果:

   v1 v2 type v2.new v1.new
1:  1  3    A      9      1
2:  2  4    B     12      2

但是,當通過get()訪問'type'時

dt[, (col_out) := lapply(.SD, function(x){x * min(x[get('type') == 'A'])}), .SDcols = col_in]

v1.new的預期值在v2.new ,反之亦然:

   v1 v2 type v2.new v1.new
1:  1  3    A      1      9
2:  2  4    B      2     12

注意:這是一個最小的玩具示例,我從一個我正在嘗試實施的更復雜的操作中提煉出來。 'type'變量的名稱作為輸入參數給出。

有趣! 感謝分享! 似乎使用get需要一些內部排序(bug?)。

避免這種情況的兩種方法:

  1. 將類型=='A'部分移到dt [,lapply(...)]之外

     referenceRows <- which(dt[,type == 'A']) referenceRows <- which(dt[,get('type') == 'A']) dt[, lapply(.SD, function(x){x * min(x[referenceRows])}), .SDcols = col_in] v1 v2 type v2.new v1.new 1: 1 3 A 9 1 2: 2 4 B 12 2 
  2. 首先創建新列,然后使用setnames確保為新列分配正確的列名稱。 最后用cbind將這兩個部分綁定在一起:

     dtNew <- dt[, lapply(.SD, function(x){x * min(x[type == 'A'])}), .SDcols = col_in] setnames(dtNew, col_in, col_out) cbind(dt, dtNew) v1 v2 type v2.new v1.new 1: 1 3 A 9 1 2: 2 4 B 12 2 

相同的結果(雖然排序不同):

    dtNew <- dt[, lapply(.SD, function(x){x * min(x[get('type') == 'A'])}), .SDcols = col_in]
    setnames(dtNew, col_in, col_out)
    cbind(dt, dtNew)


       v1 v2 type v1.new v2.new
    1:  1  3    A      1      9
    2:  2  4    B      2     12

另一種方法是在語言上使用稱為計算的酷R特性(與data.table無關),而不是使用substitute函數get並生成所需的j參數作為語言對象。
這在分組時也適用。

library(data.table)
dt <- data.table(v1 = c(1,2), v2 = c(3,4), type = c('A', 'B'))
col_in <- c('v2', 'v1')
col_out <- paste0(col_in, '.new')

col_where <- 'type'
qj <- substitute(.col_out := lapply(.SD, function(x){x * min(x[.col_where == 'A'])}),
                 list(.col_out=col_out, .col_where=as.name(col_where)))
print(qj)
#`:=`(c("v2.new", "v1.new"), lapply(.SD, function(x) {
#    x * min(x[type == "A"])
#}))

dt[, eval(qj), .SDcols = col_in][]
#      v1    v2   type v2.new v1.new
#   <num> <num> <char>  <num>  <num>
#1:     1     3      A      9      1
#2:     2     4      B     12      2

更多關於R語言定義中的這個很好的功能:語言計算章節

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM