【问题标题】:tidyverse: binding list elements efficientlytidyverse:有效地绑定列表元素
【发布时间】:2020-12-31 11:35:40
【问题描述】:

我想从下面给出的列表中绑定相同行数的 data.frames。

df1 <- data.frame(A1 = 1:10, B1 = 11:20)
df2 <- data.frame(A1 = 1:10, C1 = 21:30)
df3 <- data.frame(A2 = 1:15, B2 = 11:25, C2 = 31:45)
df4 <- data.frame(A2 = 1:15, D2 = 11:25, E2 = 51:65)
df5 <- 5

ls <- list(df1, df2, df3, df4, df5)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
bind_cols(ls[1], ls[2], .id = NULL)
#> New names:
#> * A1 -> A1...1
#> * A1 -> A1...3
#>    A1...1 B1 A1...3 C1
#> 1       1 11      1 21
#> 2       2 12      2 22
#> 3       3 13      3 23
#> 4       4 14      4 24
#> 5       5 15      5 25
#> 6       6 16      6 26
#> 7       7 17      7 27
#> 8       8 18      8 28
#> 9       9 19      9 29
#> 10     10 20     10 30
bind_cols(ls[3], ls[4], .id = NULL)
#> New names:
#> * A2 -> A2...1
#> * A2 -> A2...4
#>    A2...1 B2 C2 A2...4 D2 E2
#> 1       1 11 31      1 11 51
#> 2       2 12 32      2 12 52
#> 3       3 13 33      3 13 53
#> 4       4 14 34      4 14 54
#> 5       5 15 35      5 15 55
#> 6       6 16 36      6 16 56
#> 7       7 17 37      7 17 57
#> 8       8 18 38      8 18 58
#> 9       9 19 39      9 19 59
#> 10     10 20 40     10 20 60
#> 11     11 21 41     11 21 61
#> 12     12 22 42     12 22 62
#> 13     13 23 43     13 23 63
#> 14     14 24 44     14 24 64
#> 15     15 25 45     15 25 65

在我的实际列表中,我有大约 20 个不同行数的 data.frames。我想知道是否有更有效的方法来绑定相同行数的 data.frames 而无需给出列表元素的名称和索引。

【问题讨论】:

    标签: r dplyr tidyverse bind


    【解决方案1】:

    splitting 更容易做到这一点。使用gl创建分组索引

    grp <- as.integer(gl(length(ls), 2, length(ls)))
    

    然后使用split

    library(dplyr)
    library(purrr)
    library(stringr)
    split(ls, grp) %>% # // split by the grouping index 
         map(bind_cols) %>% # // loop over the `list` and use `bind_cols`
         set_names(str_c('df', seq_along(.))) %>% # // name the `list`
         list2env(.GlobalEnv) # // create objects in global env
    

    -输出

    head(df1)
    #  A1...1 B1 A1...3 C1
    #1      1 11      1 21
    #2      2 12      2 22
    #3      3 13      3 23
    #4      4 14      4 24
    #5      5 15      5 25
    #6      6 16      6 26
    
    head(df2)
    #  A2...1 B2 C2 A2...4 D2 E2
    #1      1 11 31      1 11 51
    #2      2 12 32      2 12 52
    #3      3 13 33      3 13 53
    #4      4 14 34      4 14 54
    #5      5 15 35      5 15 55
    #6      6 16 36      6 16 56
    
    head(df3)
    # A tibble: 1 x 1
    #   ...1
    #  <dbl>
    #1     5
    

    注意:

    1. 最好将元素保留在list 中,而不是在全局环境中创建对象,即list2env
    2. ls 是一个函数名,用函数名命名一个对象不是一个好的选择,因为它可能导致错误的情况

    【讨论】:

      【解决方案2】:

      也许不是最佳方法,但您可以使用循环并将具有相同列数的数据帧绑定到新的数据帧中。这段代码的主要内容是检查每个数据框的维度并创建一个唯一的向量。然后在循环中,您可以使用lapply()ls 中的数据帧进行子集化并绑定它们的列。这里的代码(更新考虑到小df5,您可以将其作为数据框进行管理):

      library(dplyr)
      #Data
      df1 <- data.frame(A1 = 1:10, B1 = 11:20)
      df2 <- data.frame(A1 = 1:10, C1 = 21:30)
      df3 <- data.frame(A2 = 1:15, B2 = 11:25, C2 = 31:45)
      df4 <- data.frame(A2 = 1:15, D2 = 11:25, E2 = 51:65)
      df5 <- 5
      #List
      ls <- list(df1, df2, df3, df4,df5)
      #Index
      index <- sapply(ls,function(x)dim(as.data.frame(x))[1])
      m <- unique(index)
      #Loop
      for(i in 1:length(m))
      {
        assign(paste0('df',i),do.call(bind_cols,ls[lapply(ls,function(x) dim(as.data.frame(x))[1]==m[i])==T]))
      }
      

      输出:

      df1
         A1...1 B1 A1...3 C1
      1       1 11      1 21
      2       2 12      2 22
      3       3 13      3 23
      4       4 14      4 24
      5       5 15      5 25
      6       6 16      6 26
      7       7 17      7 27
      8       8 18      8 28
      9       9 19      9 29
      10     10 20     10 30
      
      df2
         A2...1 B2 C2 A2...4 D2 E2
      1       1 11 31      1 11 51
      2       2 12 32      2 12 52
      3       3 13 33      3 13 53
      4       4 14 34      4 14 54
      5       5 15 35      5 15 55
      6       6 16 36      6 16 56
      7       7 17 37      7 17 57
      8       8 18 38      8 18 58
      9       9 19 39      9 19 59
      10     10 20 40     10 20 60
      11     11 21 41     11 21 61
      12     12 22 42     12 22 62
      13     13 23 43     13 23 63
      14     14 24 44     14 24 64
      15     15 25 45     15 25 65
      
      df3
        ...1
      1    5
      

      【讨论】:

      • 感谢@Duck 提供有用的答案。请在我的问题中查看轻微的编辑。一些列表元素是整数。
      • @MYaseen208 我为您添加了更新。我希望这对你有帮助:)
      猜你喜欢
      • 2021-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-18
      • 1970-01-01
      • 2018-10-19
      • 2020-04-08
      • 1970-01-01
      相关资源
      最近更新 更多