簡體   English   中英

Data.table 以列列表為條件

[英]Data.table conditional on list of columns

我的代碼示例如下。 我認為它可能比我能更好地解釋事情。 我明白為什么這不起作用 - R 對列名執行 boolean 操作,而不是列中的值,但我不確定如何使其工作。

DT = data.table( a = 1:5,
                 b = 6:10,
                 a_valid = c(0,1,1,0,0),
                 b_valid = c(1,1,0,0,0)
)

# This works
DT[a_valid == 0, a := NA]

numeric_columns <- c('a', 'b')
binary_columns <- c('a_valid', 'b_valid')

# This doesn't.
DT[binary_columns == 0, numeric_columns := NA]

你可以使用一個循環:

for (i in seq_along(numeric_columns)) {
  DT[get(binary_columns[i]) == 0, (numeric_columns[i]) := NA]
}

使用set()應該稍微快一點:

for (i in seq_along(numeric_columns)) {
  set(
    DT, 
    i = which(DT[[binary_columns[i]]] == 0), 
    j = numeric_columns[i], 
    value = NA_integer_
  )
}

或者切換到基本 R 一會兒:

setDF(DT)
DT[numeric_columns][DT[binary_columns] == 0] <- NA
setDT(DT)

我會在@sindri_baldur 解決方案中添加使用lapply的可能性:

lapply(seq_along(numeric_columns), function(i) DT[get(binary_columns[i]) == 0, (numeric_columns[i]) := NA])

它將避免for循環的開銷。

一些基准可以幫助選擇最佳解決方案

library(data.table)

DT = data.table(a = 1:1e5,
                b = 1:1e5 + 1e5,
                a_valid = sample(c(0,1), size = 1e5, replace = TRUE),
                b_valid = sample(c(0,1), size = 1e5, replace = TRUE)
)
numeric_columns <- c('a', 'b')
binary_columns <- c('a_valid', 'b_valid')

dt2 <- copy(DT)
dt3 <- copy(DT)
dt4 <- copy(DT)
microbenchmark::microbenchmark(
  for (i in seq_along(numeric_columns)) {
    dt2[get(binary_columns[i]) == 0, (numeric_columns[i]) := NA]
  },
  lapply(seq_along(numeric_columns), function(i) dt3[get(binary_columns[i]) == 0, (numeric_columns[i]) := NA]),
  for(j in 1:2) {
    i1 <- which(dt4[[j]] == 0)
    set(
      dt4, 
      i = which(dt4[[binary_columns[i]]] == 0), 
      j = numeric_columns[i], 
      value = NA_integer_
    )
  }  
)

#       min        lq      mean    median        uq       max neval
#  9.962940 10.104035 11.278033 10.226006 10.555132  22.10373   100
#  4.453995  4.535093  7.726525  4.659652  4.830672 234.04730   100
# 11.781060 11.913439 13.056660 12.021012 12.365140  26.84604   100

在這種情況下,獲勝者是lapply解決方案。 如果您在兩列以上需要這種東西,那么set解決方案可能會更好

暫無
暫無

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

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