【问题标题】:Composite functions in mutate_atmutate_at 中的复合函数
【发布时间】:2019-11-04 20:28:46
【问题描述】:

我有一个小玩意:

df = tibble(one = list('a', 'b'), two = list(c('p1', 'p2', 'p3'), NA_character_), three = list(NA_character_, c('z1', 'z2', 'z3')))

df
# A tibble: 2 x 3
  one   two       three    
  <chr> <list>    <list>   
1 a     <chr [3]> <chr [1]>
2 b     <chr [1]> <chr [3]>

我想使用coalesce()twothree 列中的缺失值替换为one 列的值,然后将twothree 中的每个字符向量(按行)折叠成使用toString() 的单个字符串。我的预期输出如下所示:

df = tibble(one = c('a', 'b'), two = list('p1, p2, p3', 'b'), three = list('a', 'z1, z2, z3'))
df
# A tibble: 2 x 3
  one   two       three    
  <chr> <list>    <list>   
1 a     <chr [1]> <chr [1]>
2 b     <chr [1]> <chr [1]>

这是我最初尝试过的:

df %>% mutate_at(vars(two, three), funs(coalesce(., one) %>% map(., toString)))

我知道funs() 引用了它的论点,但我不明白为什么它不适用于管道。该文档还建议 funs 已被弃用,但我不确定用什么代替它。我想知道是否有人可以解释为什么上述方法不起作用,因为我完全不熟悉作用域动词的内部工作原理。

【问题讨论】:

    标签: r data-manipulation purrr dplyr


    【解决方案1】:

    我们可以使用map2,使用coalesce,然后使用toString

    library(dplyr)
    library(purrr)
    
    df1 <- df %>% 
            mutate_at(vars(two, three), ~map2(., one, ~toString(coalesce(.x, .y))))
    
    df1
    
    #  one   two       three    
    #  <chr> <list>    <list>   
    #1 a     <chr [1]> <chr [1]>
    #2 b     <chr [1]> <chr [1]>
    
    df1$two
    #[[1]]
    #[1] "p1, p2, p3"
    
    #[[2]]
    #[1] "b"
    
    df1$three
    #[[1]]
    #[1] "a"
    
    #[[2]]
    #[1] "z1, z2, z3"
    

    在上面的示例中,我们使用 lambda 样式表达式使用 ~ 将其用作函数,并且确实 funs 已被弃用并已替换为 list()this question 中的答案和 cmets 提供了对此的更多见解。

    【讨论】:

    • 谢谢@Ronak。您的解释和链接有助于弄清楚为什么不需要 funs
    【解决方案2】:

    有了tidyverse,我们就可以使用pmap

    library(tidyverse)
    out <- df %>% 
              mutate_at(vars(two, three),
                   list(~ pmap(list(., one), ~ list(...) %>% 
                            reduce(coalesce) %>%
                            toString)))
    
    out
    # A tibble: 2 x 3
    #  one   two       three    
    #  <chr> <list>    <list>   
    #1 a     <chr [1]> <chr [1]>
    #2 b     <chr [1]> <chr [1]>
    out$two
    #[[1]]
    #[1] "p1, p2, p3"
    
    #[[2]]
    #[1] "b"
    
    out$three
    #[[1]]
    #[1] "a"
    
    #[[2]]
    #[1] "z1, z2, z3"
    

    或者使用来自base RMap

    df[-1] <- lapply(df[-1], function(x) do.call(Map, 
         c(f = function(x, y) toString(coalesce(x, y)), list(x, df$one))))
    df
    # A tibble: 2 x 3
    #  one   two       three    
    #  <chr> <list>    <list>   
    #1 a     <chr [1]> <chr [1]>
    #2 b     <chr [1]> <chr [1]>
    df$two
    #[[1]]
    #[1] "p1, p2, p3"
    
    #[[2]]
    #[1] "b"
    
    df$three
    #[[1]]
    #[1] "a"
    
    #[[2]]
    #[1] "z1, z2, z3"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-23
      • 2019-09-25
      • 1970-01-01
      • 2019-12-12
      • 1970-01-01
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多