簡體   English   中英

R data.table 使用 ifelse 通過引用分配兩列

[英]R data.table assign two columns by reference using ifelse

我有以下 data.table

library(data.table)
x <- data.table(a = 1:3, b = 1:6) 

我想通過引用同時分配兩列,因為兩列使用相同類型的檢查。 通常我會這樣做:( 在 data.table 中使用:= 按組分配多個列

x[, c("col1", "col2") := list("Yes", b)]

但我需要一個ifelse結構。 所以我嘗試了:

x[, c("col1", "col2") := ifelse(a > 2, list("Yes", b), list("No", a))]

但這不起作用,我得到一個錯誤:

Supplied 2 columns to be assigned 6 items

我該如何解決?

你可以:

x[, c("col1", "col2") := .("No", a)] # Default value
x[a > 2, c("col1", "col2") := .("Yes", b)] # .() is short for list()

另一種可以更好地推廣到更復雜情況的選擇:

x[, test_a := a > 2]
update_table <- data.table(
  test_a = c(TRUE, FALSE),
  col1 = c('Yes', 'No'),
  col2 = c('a', 'b')
)
cols <- c('col1', 'col2')
x[, (cols) := update_table[.SD, on = 'test_a', .SD, .SDcols = cols]]

您可以嘗試使用if... else...下面的代碼,而不是ifelse()

x <- data.table(a = 1:3, b = 1:6)
x[,
  c("col1", "col2") :={
    if (a > 2) list("Yes", b) else list("No", a)
  },
  by = 1:nrow(x)
][]

這使

   a b col1 col2
1: 1 1   No    1
2: 2 2   No    2
3: 3 3  Yes    3
4: 1 4   No    1
5: 2 5   No    2
6: 3 6  Yes    6

我的實際數據包含一個更復雜的ifelse語句(超過 2 個案例),我解決該問題的方法是將分配拆分如下:

# Assign first col1
x[, col1 := ifelse(a > 2, "Yes", "No")]

# Based on col1 assign col2
col1_mapper = c("Yes" = "a", "No" = "b")
x[, col2 := get(col1_mapper[col1])]

另一種方法,如果您想以不同的方式指定返回值。 請注意,在基准測試中,沒有一個提議的解決方案能勝過ifelse方法的兩倍,因為檢查並不昂貴。 對於您的實際數據,您可以嘗試

mif <- function(x, ...){
  Vectorize(\(x, a, b) if(x) list(..3, b) else list(..4, a))(x, ..1, ..2) |>
    (\(.) list(unlist(.[1,], use.names = F), unlist(.[2,], use.names = F)))()
}

x <- data.table(a = 1:3, b = 1:6) 
x[, c("col1", "col2") := mif(a > 2, a, b, "Yes", "No")]
x

   a b col1 col2
1: 1 1   No    1
2: 2 2   No    2
3: 3 3  Yes    3
4: 1 4   No    1
5: 2 5   No    2
6: 3 6  Yes    6

暫無
暫無

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

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