Fcase do více výstupů

0

Otázka

Předpokládejme následující tabulce:

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

Vím, že můžete dělat následující věci:

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

a:

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

Snažím se kombinovat tyto do jednoho jako tak:

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

Ale mi to dává následující chyba:

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

Musím jít přes několik filtrů, takže to dává smysl použít fcase. Jsem vždy uchýlit k použití první řešení pro každý filtr jako tak:

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

ale já jsem přemýšlel, jestli tam není něco víc, je to možné. Tam je také řešením pro vytvoření tabulky s každou kombinací test1 a test2 a sloučení této tabulky s daty tabulka po tom fcase pouze test1 tak jako:

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)

Ale to se zdá neefektivní pro velké a složité datatable

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

Nejlepší odpověď

4

S 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 vám umožní dát vaše fcase podmínky do seznamu a hodnoty v jiném seznamu vnořených seznamů:

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

Nebo s tests příklad:

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

Ahoj @jblood94, Skvělá odpověď, a to jak elegantní a poučné. Díky za sdílení. Jásot.
lovalery

To je přesně to, co jsem hledal! Děkuji moc
Wietse de Vries

Ahoj @jblood94, ve stejném duchu, nevíte, jestli existuje způsob, jak dát také různé testy v seznamu a hodnoty v jiném seznamu. I když vím, že syntaxe navrhuji, je špatně, aby bylo jasno, napsat něco jako toto: rbindlist(fcase(.(dummy < 5, dummy > 7), .(.("Yes", 1)), .(.("No", 0))), default = .(.("Maybe", NA))))] . Děkuji vám předem za vaši zpětnou vazbu. Jásot.
lovalery

@lovalery jsem přidal pár příkladů v duchu vaší otázky-komentář.
jblood94

Děkuji moc @jblood94. Vaše příklady mě vedou k vám poslední otázku! Po své poslední příklad, snažil jsem se zvládnout cases jak jsi to vyřešil tests ale R vrátí následující chybová zpráva: Error in (function (..., default = NA) : Argument #1 must be logical. Tady je to, co jsem udělal: cases <- data.table(Ncases = c("dummy < 5", "dummy <= 7", "dummy > 7"))pak cases[, val := .(.(.(. SD))), by = 1:nrow(cases)] a konečně data[, c("test1", "test2") := rbindlist(do.call(fcase, rbind(.(as.list(cases$val)), as.list(tests$val))))] Děkuji vám předem za vaši pomoc. Jásot.
lovalery

@lovalery fcase nepřijme struny pro when argumenty. Můžete vyřešit to tím, že Ncases vektor výrazy. To nesedí s OP otázku, tak raději ne další nepořádek moje odpověď. Navrhuji vytvoření nové otázky a odkazující na tento jeden-možná, že někdo přijde s lepší způsob, než to, co jsem myslel.
jblood94

O. K. Děkuji moc @jblood94 za váš komentář. Pokusím se prozkoumat cestu, kterou jsi mi dala, a pokud se mi to nepodaří (což je velmi pravděpodobné!), Budu psát novou otázku s odkazem na to, jak navrhujete. Jásot.
lovalery

V jiných jazycích

Tato stránka je v jiných jazycích

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