使用列表中每个项目的名称创建新列

4

我有一个数据框的列表。我想用 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)

1
(点赞)其实我15分钟前也问过自己这个问题,但是从不同的角度思考。 - Paul Endymion
@PaulEndymion 我也经常这样做 - 不过从来没有找到简洁的方法。 - elliot
3个回答

3

实际上,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
#....

1
这里有一个解决方案,可以逐个生成您的代码,并将其作为文本进行评估:
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包 (v0.3.0)于2019年9月3日创建的。


我强烈建议不要这样做。 - Shinobi_Atobe
@Shinobi_Atobe,您能否告诉我们原因呢?这样我就知道以后要避免什么了。 - Max Teflon
阅读和理解正在发生的事情很困难,已经存在的函数可以完成相同的任务,将字符串解析为函数名称是学习R语言的不良方式,特别是在非标准评估的世界中。 - Shinobi_Atobe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接