【问题标题】:Preventing purrr::map error when function returns NULL防止函数返回 NULL 时出现 purrr::map 错误
【发布时间】:2021-03-24 20:54:56
【问题描述】:

我想在这样的数据集上使用 map_chr 函数

library(purrr)
library(dplyr)

f <- function(x) if(x == "a") NULL else "blah"
f("a") # returns NULL

# make tibble
mytib <- tibble(test = c("a", "b"))

# naive map_chr
mytib %>% mutate(getf = map_chr(test, f))

# with .default
mytib %>% mutate(getf = map_chr(test, f, .default = NA_character_))

如您所见,map_chr 失败并显示错误消息Error: Problem with `mutate()` input `getf`. x unused argument (.default = NA)

其他地方描述的可能和 na_if 的尝试对我也不起作用。

如何让 map_chr 遍历参数并将 NULL 值保留为 NA_character_ 或其他值?

【问题讨论】:

  • 您需要mytib %&gt;% mutate(getf = map(test, f)) 并返回一个列表列NULL 没有任何长度。您可以将f 定义为f &lt;- function(x) if(x == "a") NA_character_ else "blah",或者可以使用ifelsecase_when 进行矢量化
  • 有没有办法直接进入一个字符列?
  • 这取决于你为什么指定NULL return 而不是NA_character_ 然后map_chr 工作正常
  • 所以如果函数f被定义为返回NULL,我必须编写一个返回NA的包装器?
  • 或类似mytib %&gt;% mutate(getf = map_chr(test, ~ {tmp &lt;- f(.x); replace(tmp, is.null(tmp), NA_character_)}))

标签: r purrr


【解决方案1】:

最好将f定义为返回NA_character_

 f <- function(x) if(x == "a") NA_character_ else "blah"

然后 OP 的调用按预期工作

或者不用循环,而是创建一个向量化函数

f <- function(x) case_when(x != 'a' ~ 'blah')

然后调用为

mytib %>% 
       mutate(getf = f(test))

如果f 已经定义为返回NULL,则使用另一个选项,然后与NA 连接并提取第一个元素。 NULL 没有任何length,因此与NA 连接仅返回NA

c(NULL, NA_character_)
#[1] NA

mytib %>% 
   mutate(getf = map_chr(test, ~ c(f(.x), NA_character_)[1]))
# A tibble: 2 x 2
#  test  getf 
#  <chr> <chr>
#1 a     <NA> 
#2 b     blah 

[1] 索引是提取那些有实际值 'blah' 返回的情况,因此我们只选择第一个元素,即 'blah' 并且对于具有if 条件的那些情况是TRUE,它将无论如何只返回 NA_character_

【讨论】:

  • 第二个解决方案是一个绝妙的技巧!我希望map_chr 有一个内置的解决方案。
  • @TeaTree 有一个map_if 选项,但也需要一个谓词函数
【解决方案2】:

purrr::map_chr() 将尝试将列表输出转换为 character 向量,如果您尝试将 NULL 对象转换为字符,则会得到如下结果:

as.character(NULL)
#> character(0)

这是一个长度为 0 的向量。此外,NULL 不是此函数的有效对象类型。另一方面,如果尝试将 NA_character_ 转换为 character.,这就是你得到的。

as.character(NA_character_)
#> NA

你可以试试这个:

library(purrr)

f <- function(x) if(x == "a") NA_character_ else "blah"

# make tibble
mytib <- tibble(test = c("a", "b"))

# naive map_chr
mytib %>% mutate(getf = map_chr(test, f))
## A tibble: 2 x 2
#  test  getf 
#  <chr> <chr>
#1 a     NA   
#2 b     blah

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-28
    • 2021-09-03
    • 1970-01-01
    • 2018-11-16
    • 1970-01-01
    • 1970-01-01
    • 2019-10-10
    • 2013-10-24
    相关资源
    最近更新 更多