Fcase a múltiples salidas

0

Pregunta

Supongamos la siguiente tabla:

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

Yo sé que tú puedes hacer las siguientes cosas:

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

y:

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

Estoy tratando de combinar estas en uno así:

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

Pero me da el siguiente error:

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

Necesito ir a través de múltiples filtros de modo que tiene sentido utilizar fcase. Siempre se puede recurrir al uso de la primera solución para cada filtro, así:

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

pero me pregunto si no hay algo más que sea posible. Hay también la solución de la creación de una tabla con cada combinación de test1 y test2 y la combinación de esta tabla con la tabla de datos después de hacer un fcase por sólo test1 así:

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)

Pero esto parece ineficiente para grandes y complejos datatable

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

Mejor respuesta

4

Con 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 te permitirá poner tu fcase condiciones en una lista y los valores de otra lista de listas anidadas:

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

O con el tests ejemplo:

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

Hola @jblood94, Gran respuesta, elegante y esclarecedor. Gracias por compartir. Saludos.
lovalery

Esto es exactamente lo que estaba buscando! Muchas gracias
Wietse de Vries

Hola @jblood94, en la misma vena, ¿sabes si hay una forma de poner también las diferentes pruebas en una lista y los valores en otra lista. Aunque sé que la sintaxis que yo estoy proponiendo es malo, para ser claros, escribir algo como esto: rbindlist(fcase(.(dummy < 5, dummy > 7), .(.("Yes", 1)), .(.("No", 0))), default = .(.("Maybe", NA))))] . Gracias de antemano por sus comentarios. Saludos.
lovalery

@lovalery he añadido un par de ejemplos a lo largo de las líneas de su pregunta-comentario.
jblood94

Muchas gracias @jblood94. Tus ejemplos me llevan a hacer una última pregunta! Después de su último ejemplo, me trató de manejar el cases como se maneja el tests pero R devuelve el siguiente mensaje de error: Error in (function (..., default = NA) : Argument #1 must be logical. Esto es lo que hice: cases <- data.table(Ncases = c("dummy < 5", "dummy <= 7", "dummy > 7")), a continuación, cases[, val := .(.(.(. SD))), by = 1:nrow(cases)] y, finalmente, data[, c("test1", "test2") := rbindlist(do.call(fcase, rbind(.(as.list(cases$val)), as.list(tests$val))))] Gracias de antemano por su ayuda. Saludos.
lovalery

@lovalery fcase no se aceptan cadenas para el when argumentos. Usted podría evitar que al hacer Ncases un vector de expresión. Esto no encaja con el OP pregunta, así que prefiero no seguir el desorden de mi respuesta. Sugiero crear una nueva pregunta y que hacen referencia a este uno, tal vez alguien va a venir para arriba con una manera mejor de lo que yo estoy pensando.
jblood94

O. K. muchas Gracias @jblood94 por tu comentario. Voy a tratar de explorar el camino que me dan y si no (que es muy probable!), Voy a publicar una nueva pregunta con un enlace a este, como usted sugiere. Saludos.
lovalery

En otros idiomas

Esta página está en otros idiomas

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