【问题标题】:how to rbind dataframes with identical column names in a list如何在列表中重新绑定具有相同列名的数据框
【发布时间】:2019-12-05 05:29:30
【问题描述】:

我有一个这样的列表:

list=list(
  df1=read.table(text = "a  b   c
11  14  20
                 17 15  12
                 6  19  17
                 ",header=T),

  df2=read.table(text = "a  b   c
6   19  12
                 9  7   19

                 ",header=T),
  df3=read.table(text = "a  d   f
12  20  15
                 12 10  8
                 7  8   7

                 ",header=T),
  df4=read.table(text = "g  f   e   z
5   12  11  5
16  17  20  16
19  9   11  20

                 ",header=T),
  df5=read.table(text = "g  f   e   z
15  13  9   18
                 12 12  17  16
                 15 9   12  11
                 15 20  19  15

                 ",header=T),
  df6=read.table(text = "a  d   f
11  7   16
                 11 12  11

                 ",header=T)
)

我的列表包含不同的数据框。根据列名,列表中有 3 种类型的数据框。

type1:df1 and df2
type2:df3 and df6
type3:f4 and df5

我要去rbind 具有相同列名的数据框并将结果保存在新列表中。例如 df1 与 df2、df3 与 df6 以及 df4 与 df5 具有相同的列名。我需要一个自动识别和rbind 具有相同列名的数据帧的代码。

预期结果如下:

> new list
$df1.df2
  a  b  c
1 11 14 20
2 17 15 12
3  6 19 17
4  6 19 12
5  9  7 19

$df3.df6
   a  d  f
1 12 20 15
2 12 10  8
3  7  8  7
4 11  7 16
5 11 12 11

$df4.df5
   g  f  e  z
1  5 12 11  5
2 16 17 20 16
3 19  9 11 20
4 15 13  9 18
5 12 12 17 16
6 15  9 12 11
7 15 20 19 15

新列表中数据框的名称可以是任何名称。

【问题讨论】:

  • dplyr::bind_rows(dfls)起点
  • dplyr::bind_rows(dfls) rbind 所有数据帧。我需要重新绑定相同的数据帧。

标签: r list dataframe rbind


【解决方案1】:

我们可以

library(tidyverse)
library(janitor)

bind_rows(dfls) %>% 
  mutate(code= apply(apply(., 2, function(x){
               ifelse(is.na(x), 1, 2)}), 1, paste, collapse="")) %>% 
  nest(.,-code, .key="code") %>% 
  mutate(filtered = map(code, janitor::remove_empty_cols)) %>% 
  pull(filtered) -> out

glimpse(out)

# List of 3
#  $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 5 obs. of  3 variables:
#   ..$ a: int [1:5] 11 17 6 6 9
#   ..$ b: int [1:5] 14 15 19 19 7
#   ..$ c: int [1:5] 20 12 17 12 19
#  $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 5 obs. of  3 variables:
#   ..$ a: int [1:5] 12 12 7 11 11
#   ..$ d: int [1:5] 20 10 8 7 12
#   ..$ f: int [1:5] 15 8 7 16 11
#  $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 7 obs. of  4 variables:
#   ..$ f: int [1:7] 12 17 9 13 12 9 20
#   ..$ g: int [1:7] 5 16 19 15 12 15 15
#   ..$ e: int [1:7] 11 20 11 9 17 12 19
#   ..$ z: int [1:7] 5 16 20 18 16 11 15

【讨论】:

    【解决方案2】:

    因为我不喜欢将变量命名为list,所以我将您的数据命名为l

    lapply(
      split(l, sapply(l, function(a) paste(colnames(a), collapse = "_"))),
      dplyr::bind_rows)
    # $a_b_c
    #    a  b  c
    # 1 11 14 20
    # 2 17 15 12
    # 3  6 19 17
    # 4  6 19 12
    # 5  9  7 19
    # $a_d_f
    #    a  d  f
    # 1 12 20 15
    # 2 12 10  8
    # 3  7  8  7
    # 4 11  7 16
    # 5 11 12 11
    # $g_f_e_z
    #    g  f  e  z
    # 1  5 12 11  5
    # 2 16 17 20 16
    # 3 19  9 11 20
    # 4 15 13  9 18
    # 5 12 12 17 16
    # 6 15  9 12 11
    # 7 15 20 19 15
    

    我通常更喜欢使用by(data, INDICES, FUN)lapply(split(data, INDICES), FUN),但由于某种原因它一直在抱怨......所以上面。

    连接与_ 折叠的列名的选择是任意的,旨在找到它们的简单“散列”;设计这样一种情况并不难,即这种方法会发现两个相似的帧,但实际上它们并不相似……也许这不太可能成为一个问题。

    我还应该注意我正在使用dplyr::bind_rows,但没有其他来自 dplyr 的内容。这可以很容易地使用purrr:: 或其他整洁的包分组来转换。

    【讨论】:

      猜你喜欢
      • 2018-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多