Fcase à plusieurs sorties

0

La question

Assumer le tableau suivant:

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

Je sais que vous pouvez faire les choses suivantes:

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

et:

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

Je suis en train de les combiner en une seule, comme ceci:

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

Mais il me donne l'erreur suivante:

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

J'ai besoin d'aller à travers de multiples filtres il est donc logique d'utiliser fcase. Je peux toujours recourir à l'aide de la première solution pour chaque filtre comme ceci:

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

mais je me demande si il n'y a pas quelque chose de plus possible. Il y a aussi la solution de la création d'un tableau avec chaque combinaison de test1 et test2 et de fusion de ce tableau avec le tableau de données après avoir fait une fcase pour seulement test1 comme suit:

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)

Mais ce qui semble inefficace pour une grande et complexe datatable

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

La meilleure réponse

4

Avec 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 vous permettra de mettre votre fcase des conditions dans une liste et les valeurs d'une autre liste de listes imbriquées:

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

Ou avec le tests exemple:

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

Salut @jblood94, Grande réponse, à la fois élégant et très instructif. Merci pour le partage. Des acclamations.
lovalery

C'est exactement ce que je cherchais! Merci beaucoup
Wietse de Vries

Salut @jblood94, dans la même veine, savez-vous si il existe un moyen de mettre également les différents tests dans une liste et les valeurs d'une autre liste. Même si je sais que la syntaxe que je propose est faux, pour être clair, écrire quelque chose comme ceci: rbindlist(fcase(.(dummy < 5, dummy > 7), .(.("Yes", 1)), .(.("No", 0))), default = .(.("Maybe", NA))))] . Merci d'avance pour vos commentaires. Des acclamations.
lovalery

@lovalery j'ai ajouté quelques exemples le long des lignes de votre question-commentaire.
jblood94

Merci beaucoup @jblood94. Vos exemples m'amènent à vous poser une dernière question! À la suite de votre dernier exemple, j'ai essayé de manipuler l' cases comme vous avez géré l' tests mais R renvoie le message d'erreur suivant: Error in (function (..., default = NA) : Argument #1 must be logical. Voici ce que j'ai fait: cases <- data.table(Ncases = c("dummy < 5", "dummy <= 7", "dummy > 7"))puis cases[, val := .(.(.(. SD))), by = 1:nrow(cases)] et enfin data[, c("test1", "test2") := rbindlist(do.call(fcase, rbind(.(as.list(cases$val)), as.list(tests$val))))] Je vous remercie d'avance pour votre aide. Des acclamations.
lovalery

@lovalery fcase n'acceptent pas les cordes de l' when les arguments. Vous pourriez contourner en faisant Ncases un vecteur d'expression. Ce n'est pas en accord avec l'OP de la question, donc je préfère ne pas encore l'encombrement de ma réponse. Je suggère la création d'une nouvelle question et le référencement de celui-ci-peut-être que quelqu'un va trouver une meilleure façon que de ce que je pense.
jblood94

O. K. Merci beaucoup @jblood94 pour votre commentaire. Je vais essayer d'explorer le chemin que vous m'accordez et si j'échoue (ce qui est très probable!), Je vais poster une nouvelle question avec un lien vers celui-ci, comme vous le suggérez. Des acclamations.
lovalery

Dans d'autres langues

Cette page est dans d'autres langues

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