Fcase到多个输出

0

的问题

假设以下表:

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

我知道你可以做以下事情:

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

并且:

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

我想把这些变成一个像这样:

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

但它给我下错误:

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

我需要经过多个过滤器,因此它是有道理的使用 fcase. 我总是可以诉诸使用第一种解决方案的每个过滤器像这样:

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

但我想知道如果没有更多的东西可能的。 还有个解决方案的创建表与每个组合 test1test2 合并本表的数据表后做一个 fcasetest1 像这样:

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)

但是,这似乎效率低下的一个大型和复杂的数据表

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

最好的答案

4

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 会让你把你的 fcase 条件成的列表的价值观在另一个列表中的嵌套清单:

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

tests 例如:

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

嗨@jblood94,伟大的回答,这两个优雅的和启发性。 谢谢你的分享。 欢呼声。
lovalery

这正是我要找的人! 非常感谢你
Wietse de Vries

嗨@jblood94,在同样的精神,你知道,如果有一种方法投入也在不同的测试,在一个列表的价值观在另一个列表。 即使我知道的语法,我提议是错误的,是明确的,写东西,像这样: rbindlist(fcase(.(dummy < 5, dummy > 7), .(.("Yes", 1)), .(.("No", 0))), default = .(.("Maybe", NA))))] . 谢谢你提前对于你的反馈意见。 欢呼声。
lovalery

@lovalery我加了几个例子沿线的你的问题-的评论。
jblood94

谢谢你这么多@jblood94. 你的实例导致我问你最后一个问题! 以下你的最后一个例子中,我试图处理 cases 如你所处理的 tests 但R返回的以下错误信息: Error in (function (..., default = NA) : Argument #1 must be logical. 这是我做了什么: cases <- data.table(Ncases = c("dummy < 5", "dummy <= 7", "dummy > 7"))然后 cases[, val := .(.(.(. SD))), by = 1:nrow(cases)] 并最终 data[, c("test1", "test2") := rbindlist(do.call(fcase, rbind(.(as.list(cases$val)), as.list(tests$val))))] 谢谢你提前对你有所帮助。 欢呼声。
lovalery

@lovalery fcase 不会接受的字符串 when 参数。 你可以工作围绕的是,通过使 Ncases 一矢量的表达方式。 这不适合与运的问题,所以我宁愿不再进一步的混乱我的答案。 我建议创建一个新的问题和引用这个也许有人会想出了一个更好的方式比我在想什么。
jblood94

O.K.非常感谢你@jblood94对于你的评论。 我会尝试,以探索的道路,你给我如果我失败(这是非常可能!), 我会发布一个新的问题与一个链接到这个作为你的建议。 欢呼声。
lovalery

其他语言

此页面有其他语言版本

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