【问题标题】:How to subset a list containing several lists in R, based on the column name, and merge into a single list/dataframe?如何根据列名对包含 R 中多个列表的列表进行子集化,并合并到单个列表/数据框中?
【发布时间】:2018-05-30 14:14:01
【问题描述】:

我有几个具有相同列名的列表。我正在尝试编写一个函数,从所有列表中按列名作为子集,合并到一个数据框并添加新的列名。例如:

list1<- list(a= c(1:6),
      b= c(4:9),
      c= c(3:8))
list2<- list(a= c(12:17),
      b= c(10:15),
      c= c(11:16))
list3<- list(a= c(2:7),
      b= c(14:19),
      c= c(9:14))
all<- list (list1, list2, list3)
new_column_names<- c("Block1", "Block2", "Block3")

我想对所有列表“a”进行子集化,并以 new_column_names 作为列名合并到一个数据框中。有什么建议么?谢谢!

【问题讨论】:

  • 好像有一些错别字。我猜你的意思是list1 &lt;- list(...) 而不是list1 &lt;- c(...)
  • 谢谢@mt1022!我纠正了错误。

标签: r list subset


【解决方案1】:

如果你想要一个data.frame,你必须首先使向量a 长度相等。然后cbind结果。

res <- lapply(all, `[[`, "a")
n <- max(sapply(res, length))
res <- lapply(res, function(x) if(length(x) < n) c(x, rep(NA, n - length(x))) else x)
res <- do.call(cbind, res)
res <- as.data.frame(res)
res <- setNames(res, new_column_names)
res
#  Block1 Block2 Block3
#1      1     12      2
#2      2     13      3
#3      3     14      4
#4      4     15      5
#5      5     16      6
#6     NA     17      7

【讨论】:

    【解决方案2】:

    您不能将它们转换为常规的 data.frame,因为这些 a-vector 具有不同的长度,而 data.frame 要求所有列的长度相同。

    相反,您可以使用以下方法将它们转换为长格式的 data.frame:

    stack(setNames(lapply(all, `[[`, "a"), new_column_names))
    #    values    ind
    # 1       1 Block1
    # 2       2 Block1
    # 3       3 Block1
    # 4       4 Block1
    # 5       5 Block1
    # 6      12 Block2
    # 7      13 Block2
    # 8      14 Block2
    # 9      15 Block2
    # 10     16 Block2
    # 11     17 Block2
    # 12      2 Block3
    # 13      3 Block3
    # 14      4 Block3
    # 15      5 Block3
    # 16      6 Block3
    # 17      7 Block3
    

    【讨论】:

    • 对不起,我的意思是有相同的行号。还有其他想法吗?
    • @AdelaIliescu 这是什么意思?请更准确。此外,您应该在问题中提供所需的结果
    【解决方案3】:

    你可以试试

    library(tidyverse)
    all %>% 
      flatten() %>%
      keep(names(.) =="a") %>%
      set_names(new_column_names) %>% 
      map(~tibble(a=.x, n=seq_along(.x))) %>% 
      bind_rows(.id = "ind") 
    # A tibble: 17 x 3
       ind        a     n
       <chr>  <int> <int>
     1 Block1     1     1
     2 Block1     2     2
     3 Block1     3     3
     4 Block1     4     4
     5 Block1     5     5
     6 Block2    12     1
     7 Block2    13     2
     8 Block2    14     3
     9 Block2    15     4
    10 Block2    16     5
    11 Block2    17     6
    12 Block3     2     1
    13 Block3     3     2
    14 Block3     4     3
    15 Block3     5     4
    16 Block3     6     5
    17 Block3     7     6
    

    然后你可以传播例如获取data.frame

    .Last.value %>% 
      spread(ind, a)
    # A tibble: 6 x 4
          n Block1 Block2 Block3
      <int>  <int>  <int>  <int>
    1     1      1     12      2
    2     2      2     13      3
    3     3      3     14      4
    4     4      4     15      5
    5     5      5     16      6
    6     6     NA     17      7
    

    【讨论】:

      【解决方案4】:

      这是一个使用tidyverse的修改选项

      library(tidyverse)
      map(all, ~ as_tibble(.x) %>%
                     select(a)) %>%
            set_names(new_column_names) %>% 
            bind_rows(.id = 'ind')
      # A tibble: 18 x 2
      #   ind        a
      #   <chr>  <int>
      # 1 Block1     1
      # 2 Block1     2
      # 3 Block1     3
      # 4 Block1     4
      # 5 Block1     5
      # 6 Block1     6
      # 7 Block2    12
      # 8 Block2    13
      # 9 Block2    14
      #10 Block2    15
      #11 Block2    16
      #12 Block2    17
      #13 Block3     2
      #14 Block3     3
      #15 Block3     4
      #16 Block3     5
      #17 Block3     6
      #18 Block3     7
      

      或使用map2

      map2_df(all, new_column_names,
                       ~ as_tibble(.x) %>% 
                              mutate(ind = .y) %>%
                              select(ind, a))
      

      【讨论】:

        【解决方案5】:

        在基地R:

        as.data.frame(setNames(lapply(all,`[[`,"a"),new_column_names))
        #   Block1 Block2 Block3
        # 1      1     12      2
        # 2      2     13      3
        # 3      3     14      4
        # 4      4     15      5
        # 5      5     16      6
        # 6      6     17      7
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-12-15
          • 2018-05-20
          • 1970-01-01
          • 2022-11-18
          • 2019-11-08
          • 2020-08-19
          • 2017-07-21
          • 1970-01-01
          相关资源
          最近更新 更多