繁体   English   中英

在purrr中使用dplyr :: if_else

[英]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

原始通话有何不同?

另一种选择是在将值加在一起时,使用sumna.rm参数忽略NANULL值。 这样,我们可以跳过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

但是,一旦我们将其更改为NANULL ,它就成为问题,可能是由于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问题。 总而言之,如文档中所述, lengthtype应与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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM