Fcase na viacero výstupov

0

Otázka

Predpokladajme nasledujúcej tabuľke:

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

Viem, že môžete urobiť nasledovné veci:

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

a:

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

Snažím sa spojiť ich do jednej, tak ako:

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

Ale to mi dáva nasledujúce chybové hlásenie:

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

Musím ísť cez viaceré filtre, tak to dáva zmysel používať fcase. Môžem vždy uchyľujú k používaniu prvé riešenie pre každý filter tak ako:

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 ja som premýšľal, či tam nie je niečo viac, ako je to možné. K dispozícii je tiež riešenie vytvorenie tabuľky s každú kombináciu test1 a test2 a zlúčiť táto tabuľka s údajmi tabuľka po tom, fcase len test1 tak ako:

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 sa zdá byť neefektívne pre veľké a komplexné datatable

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

Najlepšiu odpoveď

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 bude vám dať vaše fcase podmienky do zoznamu a hodnoty v inom zozname vnorené zoznamy:

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

Alebo s tests prí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, Skvelé prijatie, obe elegantné a poučné. Vďaka za zdieľanie. Na zdravie.
lovalery

To je presne to, čo som hľadal! Ďakujem vám veľmi pekne
Wietse de Vries

Ahoj @jblood94, v rovnakom duchu, neviete, či existuje spôsob, ako dať aj rôzne testy v zozname a hodnoty v inom zozname. Hoci viem, že syntax som navrhuje, je zle, aby bolo jasné, napísať niečo ako toto: rbindlist(fcase(.(dummy < 5, dummy > 7), .(.("Yes", 1)), .(.("No", 0))), default = .(.("Maybe", NA))))] . Vopred vám ďakujeme za vašu spätnú väzbu. Na zdravie.
lovalery

@lovalery som pridal pár príkladov pozdĺž línie na vašu otázku-komentár.
jblood94

Ďakujem @jblood94. Vaše príklady viedlo ma požiadať, aby ste ešte posledná otázka! Nasledujúce váš posledný príklad, som sa snažil zvládnuť cases ako si vybavoval tests ale R vráti nasledovné chybové hlásenie: Error in (function (..., default = NA) : Argument #1 must be logical. Tu je to, čo som robil: cases <- data.table(Ncases = c("dummy < 5", "dummy <= 7", "dummy > 7"))potom cases[, val := .(.(.(. SD))), by = 1:nrow(cases)] a nakoniec data[, c("test1", "test2") := rbindlist(do.call(fcase, rbind(.(as.list(cases$val)), as.list(tests$val))))] Vopred vám ďakujeme za vašu pomoc. Na zdravie.
lovalery

@lovalery fcase nebude akceptovať struny pre when tvrdenia. Mohli by ste obísť tým, že Ncases vektor výrazov. To nesedí s OP je otázka, tak by som radšej nie ďalšie neporiadok, moja odpoveď. Navrhujem vytvoriť novú otázku a odkazovanie na tento jeden-možno niekto príde s lepším spôsobom, ako to, čo si myslím.
jblood94

O. K. Ďakujem vám veľmi pekne @jblood94 za váš komentár. Budem sa snažiť preskúmať cesta ste mi dať a ak zlyhám, (čo je veľmi pravdepodobné!), Budem písať novú otázku s odkaz na tento jeden, ako si navrhnúť. Na zdravie.
lovalery

V iných jazykoch

Táto stránka je v iných jazykoch

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