r - 将 dplyr::if_else 与 purrr 一起使用

标签 r

我尝试在列表上使用 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 of condition), 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

但是,一旦我们将其更改为 NANULL ,这成为一个问题,可能是由于 type

@CBraun 做了一个有趣的观察

NULL[1] + NULL[2]
#integer(0)

返回长度0,

if_else(is.na(v1), 0, integer(0))

Error: false must be length 1 (length of condition), not 0 Call rlang::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 Call rlang::last_error() to see a backtrace

如果我们使用正确的NA已发送,有效

v1 <- NA_real_
if_else(is.na(v1), 0, v1[1] + v1[2])
#[1] 0

请注意,这里是 type问题。总而言之,正如文档中提到的,lengthtype应匹配 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/

相关文章:

css - 使用 bootstrap 和 R 导航栏中的 Logo

右 |数据帧到 "plain text"

r - 如何使 RStudio 演示自成一体?

r - 在 R 中查找 "near duplicates"字符串

r - 更多 MLE 麻烦

r - ggplot2 - y 轴标题上的两行或多行

r - 只保留小时 : minute:second from a "POSIXlt" "POSIXt" object

r - 优化网络邻接矩阵创建功能

r - 使用 DT 包的数据表中的排序因素

r - 默认情况下覆盖 [.data.frame 以删除未使用的因子水平