Fcase para várias saídas

0

Pergunta

Suponha a seguinte tabela:

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

Eu sei que você pode fazer as seguintes coisas:

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

e:

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

Eu estou tentando combiná-las em um assim:

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

Mas ele me dá o seguinte erro:

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

Eu preciso passar por vários filtros, de modo que não faz sentido usar fcase. Eu posso sempre recorrer ao uso a primeira solução para cada filtro, como por exemplo:

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)]

mas eu estou querendo saber se não há algo mais possível. Há também a solução de criar uma tabela com cada combinação de test1 e test2 e intercalar esta tabela com a tabela de dados após a realização de um fcase por apenas test1 assim:

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)

Mas isso parece ineficiente para uma grande e complexa datatable

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

Melhor resposta

4

Com 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 vai deixar você colocar o fcase condições para uma lista e os valores em outra lista de listas aninhadas:

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

Ou com o tests exemplo:

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

Oi @jblood94, Ótima resposta, elegante e esclarecedora. Obrigado por compartilhar. Cheers.
lovalery

Isso é exatamente o que eu estava procurando! Muito obrigado
Wietse de Vries

Oi @jblood94, na mesma veia, você sabe se existe uma maneira de colocar também os diferentes testes em uma lista e os valores em outra lista. Apesar de eu saber a sintaxe estou propondo é errado, ser claro, escrever algo como isto: rbindlist(fcase(.(dummy < 5, dummy > 7), .(.("Yes", 1)), .(.("No", 0))), default = .(.("Maybe", NA))))] . Obrigado pelo seu feedback. Cheers.
lovalery

@lovalery eu adicionei um par de exemplos ao longo das linhas da sua pergunta-comentário.
jblood94

Muito obrigado @jblood94. Seus exemplos levam-me fazer uma última pergunta! Seguindo o seu último exemplo, eu tentei lidar com a cases como você lidou com a tests mas R retorna a seguinte mensagem de erro: Error in (function (..., default = NA) : Argument #1 must be logical. Aqui está o que eu fiz: cases <- data.table(Ncases = c("dummy < 5", "dummy <= 7", "dummy > 7"))e , em seguida, cases[, val := .(.(.(. SD))), by = 1:nrow(cases)] e, finalmente, data[, c("test1", "test2") := rbindlist(do.call(fcase, rbind(.(as.list(cases$val)), as.list(tests$val))))] Obrigado antecipadamente por sua ajuda. Cheers.
lovalery

@lovalery fcase não aceita cadeias de caracteres para o when argumentos. Você pode contornar isso através de Ncases um vetor de expressões. Isso não se encaixa com o OP pergunta, então eu prefiro não mais a desordem de minha resposta. Eu sugiro a criação de uma nova pergunta e referenciar este--talvez alguém vai vir para cima com um jeito melhor do que o que eu estou pensando.
jblood94

O. K. muito Obrigado @jblood94 por seu comentário. Vou tentar explorar o caminho que você me dá e se eu falhar (o que é muito provável!), Vou postar uma nova pergunta com um link para este, como você sugere. Cheers.
lovalery

Em outros idiomas

Esta página está em outros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................