[英]Using dplyr::if_else with purrr
我正在尝试在列表上使用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
原始通话有何不同?
另一种选择是在将值加在一起时,使用sum
的na.rm
参数忽略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)
我们可以使用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] NA
的length
1,但仍返回错误
v1 <- NA
if_else(is.na(v1), 0, v1[1] + v1[2])
错误:
false
必须是双rlang::last_error()
向量,而不是整数向量调用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的状况。 但是,如果目标是获得结果,则还有其他方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.