【问题标题】:Add new column with name of each element as a value添加以每个元素的名称作为值的新列
【发布时间】:2018-09-23 11:28:46
【问题描述】:

我在一个列表中有一堆数据框。我正在尝试向每个数据框添加一个新列,并将数据框的“名称”作为值。

我的示例数据:

library(tidyverse)

df_2018 <- data_frame(y1 = c(1, 2, 3),
                      y2 = c(4, 5, 6))
df_2017 <- data_frame(y1 = c(3, 2, 1),
                      y2 = c(6, 5, 4))

list <- list(df_2017 = df_2017, df_2018 = df_2018)

结果:

> list
$df_2017
# A tibble: 3 x 2
     y1    y2
  <dbl> <dbl>
1     3     6
2     2     5
3     1     4

$df_2018
# A tibble: 3 x 2
     y1    y2
  <dbl> <dbl>
1     1     4
2     2     5
3     3     6

期望的结果:

> list
$df_2017
# A tibble: 3 x 3
     y1    y2 year   
  <dbl> <dbl> <chr>  
1     3     6 df_2017
2     2     5 df_2017
3     1     4 df_2017

$df_2018
# A tibble: 3 x 3
     y1    y2 year   
  <dbl> <dbl> <chr>  
1     1     4 df_2018
2     2     5 df_2018
3     3     6 df_2018

我正在学习 purrr 的 map() 函数,所以如果你能用 purrr 显示答案,加分!

我正在考虑以下问题,但这不起作用:

map(list,
    add_column,
    ~ year = names(.x))

【问题讨论】:

    标签: r list purrr


    【解决方案1】:

    我会使用map2 和mutate 来做到这一点:

    library(dplyr)
    library(purrr)
    
    mlist <- list(df_2017 = df_2017, df_2018 = df_2018)
    
    map2(mlist, names(mlist), ~ mutate(.x, year = .y)) 
    
    $df_2017
      y1 y2    year
    1  3  6 df_2017
    2  2  5 df_2017
    3  1  4 df_2017
    
    $df_2018
      y1 y2    year
    1  1  4 df_2018
    2  2  5 df_2018
    3  3  6 df_2018
    

    【讨论】:

    • 或者更短一点:imap(list, ~ mutate(.x, year = .y))
    【解决方案2】:

    tidyverse 解决方案 :-)

    我们获取列表和列表名称,使用 purrr 中的 map2 和 tibble 中的 add_column 将所有内容放在一起。

    map2(list, names(list), function(x, y) add_column(x, year = y))
    
    $`df_2017`
    # A tibble: 3 x 3
         y1    y2 year   
      <dbl> <dbl> <chr>  
    1     3     6 df_2017
    2     2     5 df_2017
    3     1     4 df_2017
    
    $df_2018
    # A tibble: 3 x 3
         y1    y2 year   
      <dbl> <dbl> <chr>  
    1     1     4 df_2018
    2     2     5 df_2018
    3     3     6 df_2018
    

    【讨论】:

    • 或者更短一点:imap(list, ~ add_column(.x, year = .y))
    【解决方案3】:

    base解决方案使用lapply

    lst <- list(df_2017 = df_2017, df_2018 = df_2018) #I'm using lst as name instead of "list" as it is reserved in R
    temp <- lapply(seq_along(lst), function(x) rep(names(lst[x]), times = nrow(lst[[x]])))
    lapply(seq_along(lst), function(i) cbind(lst[[i]], year=temp[[i]]))
    #returns
    [[1]]
      y1 y2    year
    1  3  6 df_2017
    2  2  5 df_2017
    3  1  4 df_2017
    
    [[2]]
      y1 y2    year
    1  1  4 df_2018
    2  2  5 df_2018
    3  3  6 df_2018
    

    在@markus 之后,这里是另一个使用Map 的选项

    Map("[<-", lst, "year", value = names(lst))
    

    【讨论】:

    • 试试Map("[&lt;-", list, "year", value = names(list))
    • 优雅的@markus!我包括在引用你的答案中。
    猜你喜欢
    • 2019-10-29
    • 1970-01-01
    • 2014-04-09
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    • 2017-03-05
    • 2022-11-13
    相关资源
    最近更新 更多