如果列表元素为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]) })
这无法正常工作,而是出现错误:
错误:
false
的长度必须为1(condition
的长度),而不是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
原始通话有何不同?
答案 0 :(得分:2)
一种替代方法是在将值加在一起时,使用na.rm
中的sum
参数忽略NA
或NULL
值。这样,我们可以跳过if else逻辑:
purrr::map_dbl(x, sum, na.rm = TRUE)
# [1] 0 3 7
这是Base R的等效项(如akrun所指出):
sapply(x, sum, na.rm = TRUE)
答案 1 :(得分:1)
我们可以使用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
,要求所有参数的长度都相同
用于条件的TRUE和FALSE值的值。它们的长度必须与条件相同,或者长度为1。它们还必须具有相同的类型:if_else()检查它们是否具有相同的类型和相同的类。所有其他属性均取自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))
错误:
false
的长度必须为1(condition
的长度),而不是0 致电rlang::last_error()
查看回溯
但是
NA + NA #[1]不适用
是length
1,但仍返回错误
v1 <- NA
if_else(is.na(v1), 0, v1[1] + v1[2])
错误:
false
必须是双精度向量,而不是整数向量 致电rlang::last_error()
查看回溯
如果我们使用正确的NA
派发产品,则可以使用
v1 <- NA_real_
if_else(is.na(v1), 0, v1[1] + v1[2])
#[1] 0
请注意,这里是type
问题。总而言之,如文档中所述,length
和type
应该与if_else
底线:当值为NULL
时,行为是奇怪的,因为+
的输出是长度为0的integer(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
也要求长度相同,尽管由于值的循环在这里可以使用
一个矢量,其长度和属性(包括尺寸和“类别”)与来自“是”或“否”值的测试和数据值相同。
purrr::map_dbl(x, ~ ifelse(is.null(.x), 0, .x[[1]] + .x[[2]]))
#[1] 0 3 7
注意:所有方法都用于检查OP的状况。但是,如果目标是获得结果,则还有其他方法。