我尝试在列表上使用 purrr::map_dbl
,如果列表元素为 NULL
,我希望有不同的行为。
x <- list(NULL, c(1, 2), c(3, 4))
purrr::map_dbl(x, function(y) { dplyr::if_else(is.null(y), 0, y[1] + y[2]) })
这没有按预期工作,而是给出错误:
Error:
false
must be length 1 (length ofcondition
), not 0
调试 if_else
调用时,我发现 y[1] + y[2]
的计算结果为 integer(0)
。为什么这不起作用?
以下所有内容都按我的预期工作:
> purrr::map_dbl(x, function(y) { dplyr::if_else(is.null(y), 0, y[1]) })
[1] 0 1 3
> purrr::map_dbl(x, function(y) { dplyr::if_else(is.null(y), 0, y[2]) })
[1] 0 2 4
> purrr::map_dbl(x, ~ dplyr::if_else(is.null(.x), 0, .x[1]))
[1] 0 1 3
> purrr::map_dbl(x, function(y) { base::ifelse(is.null(y), 0, y[1] + y[2]) })
[1] 0 3 7
> purrr::map_dbl(x, function(y) { if (is.null(y)) 0 else y[1] + y[2] })
[1] 0 3 7
与原始调用有何不同?
最佳答案
我们可以使用 browser()
轻松调试它
purrr::map_dbl(x, function(y) {
browser()
dplyr::if_else(is.null(y), 0, y[1] + y[2])
})
Called from: .f(.x[[i]], ...)
Browse[1]>
debug at #1: dplyr::if_else(is.null(y), 0, y[1] + y[2])
Browse[2]>
Error: `false` must be length 1 (length of `condition`), not 0
Call `rlang::last_error()` to see a backtrace
所以,这里是length
是问题所在。
根据?if_else
,要求所有参数具有相同的长度
Values to use for TRUE and FALSE values of condition. They must be either the same length as condition, or length 1. They must also be the same type: if_else() checks that they have the same type and same class. All other attributes are taken from true.
为了进一步深入研究这个问题,如果值不是NULL
,它仍然有效。
v1 <- 1
if_else(v1==1, 0, v1[1] + v1[2])
#[1] 0
但是,一旦我们将其更改为 NA
或NULL
,这成为一个问题,可能是由于 type
@CBraun 做了一个有趣的观察
NULL[1] + NULL[2]
#integer(0)
返回长度0,
if_else(is.na(v1), 0, integer(0))
Error:
false
must be length 1 (length ofcondition
), not 0 Callrlang::last_error()
to see a backtrace
但是,
不适用+不适用 #[1] 不适用
是 length
1,但仍然返回错误
v1 <- NA
if_else(is.na(v1), 0, v1[1] + v1[2])
Error:
false
must be a double vector, not an integer vector Callrlang::last_error()
to see a backtrace
如果我们使用正确的NA
已发送,有效
v1 <- NA_real_
if_else(is.na(v1), 0, v1[1] + v1[2])
#[1] 0
请注意,这里是 type
问题。总而言之,正如文档中提到的,length
和type
应匹配 if_else
底线:当值为 NULL
时,由于 +
的输出,行为很奇怪是 integer(0)
长度为0
在这种情况下我们可以使用 if/else
而不是if_else
purrr::map_dbl(x, ~ if(is.null(.x)) 0 else sum(.x))
#[1] 0 3 7
在这方面,请使用 sum
而不是单独调用参数 y[[1]]
, y[[2]]
因为这会导致长度不平衡
purrr::map_dbl(x, ~ ifelse(is.null(.x), 0, sum(.x)))
#[1] 0 3 7
请注意ifelse
还要求长度相同,尽管由于值的回收,它在这里起作用
A vector of the same length and attributes (including dimensions and "class") as test and data values from the values of yes or no.
purrr::map_dbl(x, ~ ifelse(is.null(.x), 0, .x[[1]] + .x[[2]]))
#[1] 0 3 7
注意:所有方法均用于检查 OP 的状况。但是,如果目标是获得结果,还有其他方法。
关于r - 将 dplyr::if_else 与 purrr 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56690964/