Fcase для нескольких выходов

0

Вопрос

Предположим, что в следующей таблице:

data <- data.table(dummy=1:10)

Я знаю, что вы можете делать следующие вещи:

data[dummy < 5, c("test1", "test2") := list("Yes", 1)]

и:

data[, test1 := fcase(dummy < 5, "Yes")]
data[, test2 := fcase(dummy < 5, 1)]

Я пытаюсь объединить их в одно, вот так:

data[, c("test1", "test2") := fcase(dummy < 5, list("Yes", 1))]

Но это дает мне следующую ошибку:

Error in fcase(dummy < 5, list("Yes", 1)) : 
  Length of output value #2 must either be 1 or length of logical condition.

Мне нужно пройти через несколько фильтров, поэтому имеет смысл использовать fcase. Я всегда могу прибегнуть к использованию первого решения для каждого фильтра, например:

data[dummy < 5, c("test1", "test2") := list("Yes", 1)]
data[dummy > 7, c("test1", "test2") := list("No", 0)]
data[between(dummy, 5, 7), c("test1", "test2") := list("Maybe", NA)]

но мне интересно, нет ли чего-то более возможного. Существует также решение создания таблицы с каждой комбинацией test1 и test2 и объедините эту таблицу с таблицей данных после выполнения fcase только для test1 вот так:

tests <- data.table(test1 = c("Yes", "No", "Maybe"),
                    test2 = c(1, 0, NA))

data[, test1 := fcase(dummy < 5, "Yes",
                      dummy > 7, "No",
                      between(dummy, 5, 7), NA_character_)]
merge(data, tests, by = "test1", all.x = T, sort = F)

Но это кажется неэффективным для большой и сложной базы данных

case data.table r
2021-11-17 16:48:12
1

Лучший ответ

4

С rbindlist:

data[, c("test1", "test2") := rbindlist(fcase(dummy < 5, .(.("Yes", 1)),
                                              dummy > 7, .(.("No", 0)),
                                              default = .(.("Maybe", NA))))]
data
#>     dummy test1 test2
#>  1:     1   Yes     1
#>  2:     2   Yes     1
#>  3:     3   Yes     1
#>  4:     4   Yes     1
#>  5:     5 Maybe    NA
#>  6:     6 Maybe    NA
#>  7:     7 Maybe    NA
#>  8:     8    No     0
#>  9:     9    No     0
#> 10:    10    No     0

do.call позволит вам поставить fcase условия в список и значения в другом списке вложенных списков:

data[, c("test1", "test2") := rbindlist(do.call(fcase, rbind(.(dummy < 5, dummy <= 7, dummy > 7),
                                                             .(.(.("Yes", 1)), .(.("Maybe", NA)), .(.("No", 0))))))]

Или с помощью tests пример:

tests <- data.table(test1 = c("Yes", "Maybe", "No"),
                    test2 = c(1, NA, 0))
tests[, val := .(.(.(.SD))), by = 1:nrow(tests)]
data[, c("test1", "test2") := rbindlist(do.call(fcase, rbind(.(dummy < 5, dummy <= 7, dummy > 7), tests$val)))]
2021-11-22 13:23:13

Привет @jblood94, Отличный ответ, элегантный и поучительный. Спасибо, что поделились. Ваше здоровье.
lovalery

Это именно то, что я искал! Большое спасибо
Wietse de Vries

Привет @jblood94, в том же духе, не знаете ли вы, есть ли способ поместить также различные тесты в список и значения в другой список. Несмотря на то, что я знаю, что синтаксис, который я предлагаю, неправильный, для ясности напишите что-нибудь вроде этого: rbindlist(fcase(.(dummy < 5, dummy > 7), .(.("Yes", 1)), .(.("No", 0))), default = .(.("Maybe", NA))))] . Заранее благодарим вас за ваши отзывы. Ваше здоровье.
lovalery

@lovalery Я добавил пару примеров в соответствии с вашим вопросом-комментарием.
jblood94

Большое вам спасибо @jblood94. Ваши примеры заставляют меня задать вам последний вопрос! Следуя вашему последнему примеру, я попытался справиться с cases как вы справлялись с tests но R возвращает следующее сообщение об ошибке: Error in (function (..., default = NA) : Argument #1 must be logical. Вот что я сделал: cases <- data.table(Ncases = c("dummy < 5", "dummy <= 7", "dummy > 7")), тогда cases[, val := .(.(.(. SD))), by = 1:nrow(cases)] и, наконец, data[, c("test1", "test2") := rbindlist(do.call(fcase, rbind(.(as.list(cases$val)), as.list(tests$val))))] Заранее благодарю вас за вашу помощь. Ваше здоровье.
lovalery

@lovalery fcase не будет принимать строки для when аргументы. Вы могли бы обойти это, сделав Ncases вектор выражений. Это не соответствует вопросу ОП, поэтому я бы предпочел не загромождать свой ответ еще больше. Я предлагаю создать новый вопрос и сослаться на этот-может быть, кто-нибудь придумает лучший способ, чем то, о чем я думаю.
jblood94

О'Кей Большое спасибо @jblood94 за ваш комментарий. Я попытаюсь изучить путь, который вы мне укажете, и если я потерплю неудачу (что очень вероятно!), я опубликую новый вопрос со ссылкой на этот, как вы предлагаете. Ваше здоровье.
lovalery

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................