【问题标题】:assigning id values from values, not names, with purrr::map_dfr使用 purrr::map_dfr 从值而不是名称中分配 id 值
【发布时间】:2021-06-06 18:57:26
【问题描述】:

我认为这个问题与Using map_dfr and .id for list names and list of list names 有关,但不完全相同...

我经常将map_dfr 用于我想使用每个参数的,而不是它的名称,作为.id 变量的情况。这是一个愚蠢的例子:我正在计算mtcars$mpg 的二、四、六次方的平均值:

library(tidyverse)
list(2,4,6) %>% map_dfr(~tibble(x=mean(mtcars$mpg^.)), .id="name")
##   name           x
##   <chr>      <dbl>
## 1 1           439.
## 2 2        262350.
## 3 3     198039783.

我希望 name 变量为 2、4、6 而不是 1、2、3。我可以通过在管道中包含 setNames(.data) 来解决这个问题:

list(2,4,6) %>% 
   setNames(.data) %>% 
   map_dfr(~tibble(x=mean(mtcars$mpg^.)), .id="name")

但我想知道我是否缺少更惯用的方法?


关于使用~ tible(name=., ...) 之类的建议:很好,但稍微对于映射函数已经返回小标题的情况不太方便,因为我们必须添加一个否则不必要的@987654331 @调用:

list(2, 4, 6) %>%   
    map_dfr(~ tibble(name=., 
       broom::tidy(lm(mpg~cyl, data=mtcars, offset=rep(., nrow(mtcars))))))

【问题讨论】:

  • 为什么不只是list(2, 4, 6) %&gt;% map_dfr(~ tibble(x = mean(mtcars$mpg^.x), names = .x))
  • 可行(您可以将其作为答案发布,我至少会赞成)但我的示例可能太简单了:在很多情况下,返回的对象已经是一个 tibble 而我没有不想添加另一个tibble() 语句...
  • 我不确定你的目标到底是什么,但对于更新后的问题,你可以直接list(2, 4, 6) %&gt;% map_dfr(~ broom::tidy(lm(mpg~cyl, data=mtcars, offset=rep(., nrow(mtcars)))) %&gt;% mutate(names = .x))
  • 很公平。然后names 列将是最后一列,虽然...(lots of discussion 关于我们如何/是否可以轻松地使mutate 在开头/左侧添加变量...)

标签: r purrr


【解决方案1】:

好的,我想我在发布前不久发现了这个(所以我会回答)。 This answer 指出tibble::lst() 是一个自命名列表函数,所以只要我们使用tibble::lst(2,4,6) 而不是list(2,4,6),它就可以工作,例如

lst(2,4,6) %>% map_dfr(~tibble(x=mean(mtcars$mpg^.)), .id="name")

【讨论】:

    【解决方案2】:

    这也可以:

    library(tidyverse)
    
    #@ben Bolker answer.
    lst(2,4,6) %>% map_dfr(~tibble(x=mean(mtcars$mpg^.)), .id="power")
    #> # A tibble: 3 x 2
    #>   power          x
    #>   <chr>      <dbl>
    #> 1 2           439.
    #> 2 4        262350.
    #> 3 6     198039783.
    
    list(2, 4, 6) %>% map_df(~ tibble(power = as.character(.x) , x = mean(mtcars$mpg^.)))
    #> # A tibble: 3 x 2
    #>   power          x
    #>   <chr>      <dbl>
    #> 1 2           439.
    #> 2 4        262350.
    #> 3 6     198039783.
    
    #another option
    seq(2, 6, 2) %>%  map2_df(rerun(length(.), mtcars$mpg), ~ c(x = as.character(.x), mean = round(mean(.y^.x), 0)))
    #> # A tibble: 3 x 2
    #>   x     mean     
    #>   <chr> <chr>    
    #> 1 2     439      
    #> 2 4     262350   
    #> 3 6     198039783
    

    reprex package (v2.0.0) 于 2021-06-06 创建

    【讨论】:

      【解决方案3】:

      这也是可能的,但它不是我的首选,只有map 就足够了:

      library(purrr)
      
      list(2, 4, 6) %>%
        pmap_dfr(~ tibble(power = c(...), x = map_dbl(c(...), ~ mean(mtcars$mpg ^ .x))))
      
      # A tibble: 3 x 2
        power          x
        <dbl>      <dbl>
      1     2       439.
      2     4    262350.
      3     6 198039783.
      

      【讨论】:

      • 适用于我给出的简单示例(应该预先包含更复杂的示例......)
      • 是的,有可能根本不是最好的。如果之前不会发布类似的,这将是我的第一选择:list(2, 4, 6) %&gt;% map_dfr(~ tibble(name = .x, x = mean(mtcars$mpg^.x)))。但最好看看原始数据集的一部分。
      猜你喜欢
      • 2018-09-14
      • 2020-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-03
      相关资源
      最近更新 更多