【问题标题】:Create new column of from list using each item's name使用每个项目的名称从列表中创建新列
【发布时间】:2019-09-03 13:42:50
【问题描述】:

我有一个数据框列表。我想使用purrr 遍历它们并进行一些分析。部分分析包括根据列表项的名称重命名变量。这使我可以正确地将文件合并到一个数据框中。我对如何实现这一点有点困惑。

    library(tidyverse)

# Get names of columns

df <- mtcars %>% 
  as_tibble() %>% 
  select(1:5)

mtcars_names <- df %>% 
  names()

# Split into many dataframes based on columns
mtcars_ls <- df %>% 
  gather(key, value) %>%
  split(.$key)


map2(mtcars_ls, mtcars_names, function(x, y){
  x %>% 
    rename(y = value)
})
#> $cyl
#> # A tibble: 32 x 2
#>    key       y
#>    <chr> <dbl>
#>  1 cyl       6
#>  2 cyl       6
#>  3 cyl       4
#>  4 cyl       6
#>  5 cyl       8
#>  6 cyl       6
#>  7 cyl       8
#>  8 cyl       4
#>  9 cyl       4
#> 10 cyl       6
#> # … with 22 more rows
#> 
#> $disp
#> # A tibble: 32 x 2
#>    key       y
#>    <chr> <dbl>
#>  1 disp   160 
#>  2 disp   160 
#>  3 disp   108 
#>  4 disp   258 
#>  5 disp   360 
#>  6 disp   225 
#>  7 disp   360 
#>  8 disp   147.
#>  9 disp   141.
#> 10 disp   168.
#> # … with 22 more rows
#> 
#> $drat
#> # A tibble: 32 x 2
#>    key       y
#>    <chr> <dbl>
#>  1 drat   3.9 
#>  2 drat   3.9 
#>  3 drat   3.85
#>  4 drat   3.08
#>  5 drat   3.15
#>  6 drat   2.76
#>  7 drat   3.21
#>  8 drat   3.69
#>  9 drat   3.92
#> 10 drat   3.92
#> # … with 22 more rows
#> 
#> $hp
#> # A tibble: 32 x 2
#>    key       y
#>    <chr> <dbl>
#>  1 hp      110
#>  2 hp      110
#>  3 hp       93
#>  4 hp      110
#>  5 hp      175
#>  6 hp      105
#>  7 hp      245
#>  8 hp       62
#>  9 hp       95
#> 10 hp      123
#> # … with 22 more rows
#> 
#> $mpg
#> # A tibble: 32 x 2
#>    key       y
#>    <chr> <dbl>
#>  1 mpg    21  
#>  2 mpg    21  
#>  3 mpg    22.8
#>  4 mpg    21.4
#>  5 mpg    18.7
#>  6 mpg    18.1
#>  7 mpg    14.3
#>  8 mpg    24.4
#>  9 mpg    22.8
#> 10 mpg    19.2
#> # … with 22 more rows
Created on 2019-09-03 by the reprex package (v0.3.0)

【问题讨论】:

  • (upvote) 我实际上在 15 分钟前问过自己这个问题,但从不同的角度
  • @PaulEndymion 实际上我也经常这样做——但从来没有想出一个简洁的方法来做到这一点。

标签: r dplyr purrr


【解决方案1】:

purrr 中实际上有一个不错的函数,称为imap,它似乎可以满足您的需要。它遍历列表的元素 (.x) 和名称 (.y):

df <- mtcars %>% 
  select(1:5)

# Split into many dataframes based on columns and create a named list
mtcars_ls <- df %>% 
  gather(key, value) %>%
  split(.$key) %>% 
  set_names(names(df))

imap(mtcars_ls, function(x,y) {
  x %>% 
    rename(!!quo_name(y) := value)
})

!!quo_name:= 允许对名称字符串进行整齐评估。为了更简单,您可以使用速记符号:

imap(mtcars_ls, ~ rename(.x, !!quo_name(.y) := value))

【讨论】:

    【解决方案2】:

    也许你可以使用rename_at

    library(purrr)
    library(dplyr)
    
    map2(mtcars_ls, mtcars_names, function(x, y){
        x %>% rename_at(vars(value), ~y) %>% head
    })
    
    #$cyl
    # A tibble: 6 x 2
    #  key     mpg
    #  <chr> <dbl>
    #1 cyl       6
    #2 cyl       6
    #3 cyl       4
    #4 cyl       6
    #5 cyl       8
    #6 cyl       6
    
    #$disp
    # A tibble: 6 x 2
    #  key     cyl
    #  <chr>  <dbl>
    #1 disp    160
    #2 disp    160
    #3 disp    108
    #4 disp    258
    #5 disp    360
    #6 disp    225
    #....
    

    【讨论】:

      【解决方案3】:

      这是一个解决方案,将您的代码逐个生成为文本,然后对其进行评估:

      library(tidyverse)
      
      
      # Get names of columns
      
      df <- mtcars %>% 
        as_tibble() %>% 
        select(1:5)
      
      mtcars_names <- df %>% 
        names()
      
      # Split into many dataframes based on columns
      mtcars_ls <- df %>% 
        gather(key, value) %>%
        split(.$key)
      
      
      map2(mtcars_ls, mtcars_names, function(x, y){
        eval(parse(text = paste0('rename(x,',y,' = value)')))
      })
      #> $cyl
      #> # A tibble: 32 x 2
      #>    key     mpg
      #>    <chr> <dbl>
      #>  1 cyl       6
      #>  2 cyl       6
      #>  3 cyl       4
      #>  4 cyl       6
      #>  5 cyl       8
      #>  6 cyl       6
      #>  7 cyl       8
      #>  8 cyl       4
      #>  9 cyl       4
      #> 10 cyl       6
      #> # … with 22 more rows
      #> 
      #> $disp
      #> # A tibble: 32 x 2
      #>    key     cyl
      #>    <chr> <dbl>
      #>  1 disp   160 
      #>  2 disp   160 
      #>  3 disp   108 
      #>  4 disp   258 
      #>  5 disp   360 
      #>  6 disp   225 
      #>  7 disp   360 
      #>  8 disp   147.
      #>  9 disp   141.
      #> 10 disp   168.
      #> # … with 22 more rows
      #> 
      #> $drat
      #> # A tibble: 32 x 2
      #>    key    disp
      #>    <chr> <dbl>
      #>  1 drat   3.9 
      #>  2 drat   3.9 
      #>  3 drat   3.85
      #>  4 drat   3.08
      #>  5 drat   3.15
      #>  6 drat   2.76
      #>  7 drat   3.21
      #>  8 drat   3.69
      #>  9 drat   3.92
      #> 10 drat   3.92
      #> # … with 22 more rows
      #> 
      #> $hp
      #> # A tibble: 32 x 2
      #>    key      hp
      #>    <chr> <dbl>
      #>  1 hp      110
      #>  2 hp      110
      #>  3 hp       93
      #>  4 hp      110
      #>  5 hp      175
      #>  6 hp      105
      #>  7 hp      245
      #>  8 hp       62
      #>  9 hp       95
      #> 10 hp      123
      #> # … with 22 more rows
      #> 
      #> $mpg
      #> # A tibble: 32 x 2
      #>    key    drat
      #>    <chr> <dbl>
      #>  1 mpg    21  
      #>  2 mpg    21  
      #>  3 mpg    22.8
      #>  4 mpg    21.4
      #>  5 mpg    18.7
      #>  6 mpg    18.1
      #>  7 mpg    14.3
      #>  8 mpg    24.4
      #>  9 mpg    22.8
      #> 10 mpg    19.2
      #> # … with 22 more rows
      

      reprex package (v0.3.0) 于 2019 年 9 月 3 日创建

      【讨论】:

      • 我强烈建议不要这样做
      • @Shinobi_Atobe 你能告诉我们为什么吗?这样我就知道将来要避免什么。
      • 很难阅读和理解正在发生的事情,有预先存在的函数可以做同样的事情,将字符串解析为函数名是学习 R 的一种不好的方式,尤其是在 R非标准评价
      猜你喜欢
      • 2023-03-29
      • 2014-04-10
      • 1970-01-01
      • 1970-01-01
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      • 2020-09-24
      • 1970-01-01
      相关资源
      最近更新 更多