purrr ::可能功能可能无法与map2_chr函数一起使用

时间:2018-08-07 06:04:41

标签: r purrr

我怀疑这是purrr软件包中的错误,但请先检查一下StackOverflow中的逻辑。

在我看来possibly函数在map2_chr函数内部不起作用。我正在使用purrr 0.2.5版

考虑以下示例:

library(dplyr)
library(purrr)

lets <- tibble(posn = 2:0,
               lets_list = list(letters[1:5], letters[1:5], letters[1:5])) %>% 
  glimpse()

返回

Observations: 3
Variables: 2
$ posn      <int> 2, 1, 0
$ lets_list <list> [<"a", "b", "c", "d", "e">, <"a", "b", "c", "d", "e">, <"a", "b", "c", "d", "e">]

在此示例中,我想使用mutate创建另一列,以基于“ posn”中的值返回列表“ lets_list”中的元素。

lets %>% 
  mutate(lets_sel = map2_chr(lets_list, posn, ~.x[.y]))

此错误消息失败,因为第三行的posn = 0。

> lets %>% 
+   mutate(lets_sel = map2_chr(lets_list, posn, ~.x[.y]))
#    Error in mutate_impl(.data, dots) : 
#      Evaluation error: Result 3 is not a length 1 atomic vector.

possibly函数与map2_chr一起使用也会返回错误。

lets %>% 
  mutate(lets_sel = map2_chr(lets_list, posn, possibly(~.x[.y], NA_character_)))
# Error in mutate_impl(.data, dots) : 
#  Evaluation error: Result 3 is not a length 1 atomic vector.

但是,map2函数可以正常工作:

> lets %>% 
+   mutate(lets_sel = map2(lets_list, posn, possibly(~.x[.y], NA_character_)))
# A tibble: 3 x 3
   posn lets_list lets_sel 
  <int> <list>    <list>   
1     2 <chr [5]> <chr [1]>
2     1 <chr [5]> <chr [1]>
3     0 <chr [5]> <chr [0]>

一种解决方法是先使用map2然后再使用map_chr,但我怀疑这是一个错误。

> lets %>% 
+   mutate(lets_sel = map2(lets_list, posn, ~.x[.y]),
+          lets_sel = map_chr(lets_sel, possibly(~.x[1], NA_character_)))
    # A tibble: 3 x 3
       posn lets_list lets_sel
      <int> <list>    <chr>   
    1     2 <chr [5]> b       
    2     1 <chr [5]> a       
    3     0 <chr [5]> NA      

我在这里错过了什么吗? 谢谢。

2 个答案:

答案 0 :(得分:1)

好的,现在我认为这只是一个“功能”。最优雅的解决方案/解决方法是:

lets %>% 
  mutate(lets_sel = map2(lets_list, posn, ~.x[.y]) %>% 
           map_chr(., possibly(~.x[1], NA_character_)))

帮助屏幕上的任何地方都没有暗示可以map2系列功能安全地使用它。因此,我得出的结论是,这是“功能”,而不是“错误”。
谢谢。

答案 1 :(得分:0)

possibly()不起作用,因为使用0编制索引不会引发错误; 它只是返回一个长度为0的向量:

nth_letter <- function(n) letters[n]

possibly(nth_letter, "not returned")(0)
#> character(0)

nth_letter(0)
#> character(0)

在这种情况下,用NA替换无效索引可能会更容易 (例如,如果实际问题比较复杂,则使用dplyr::na_if()或普通的ifelse)来获得您想要的东西:

lets %>% 
  mutate(lets_sel = map2_chr(lets_list, na_if(posn, 0), ~ .x[.y]))
#> # A tibble: 3 x 3
#>    posn lets_list lets_sel
#>   <int> <list>    <chr>   
#> 1     2 <chr [5]> b       
#> 2     1 <chr [5]> a       
#> 3     0 <chr [5]> <NA>

reprex package(v0.2.0.9000)于2018-08-07创建。