合并数据帧而不重复R中的行

时间:2017-11-21 14:33:45

标签: r dataframe

我有一个巨大的数据框列表,数据的结构使得合并变得困难。基本上我读了很多嵌套目录的.xls文件,所以我有一个数据帧列表,其中大约每5个左右应该水平组合成行,每组5个应该垂直组合。

我将尝试举例(为简单起见,组大小减少到3)。

df.list[1]:
id     Date     col1     col2
1      date1    <int>    <int>
2      date1    <int>    <int>
3      date1    <int>    <int>

df.list[2]:
id     Date     col3     col4
1      date1    <int>    <int>
2      date1    <int>    <int>
3      date1    <int>    <int>

df.list[3]:
id     Date     col5     col6
1      date1    <int>    <int>
2      date1    <int>    <int>
3      date1    <int>    <int>

接下来的几个是不同的样本......

df.list[4]:
id     Date     col1     col2
1      date2    <int>    <int>
2      date2    <int>    <int>
3      date2    <int>    <int>

df.list[5]:
id     Date     col3     col4
1      date2    <int>    <int>
2      date2    <int>    <int>
3      date2    <int>    <int>

df.list[6]:
id     Date     col5     col6
1      date2    <int>    <int>
2      date2    <int>    <int>
3      date2    <int>    <int>

这样可以保留几千个样本。 我尝试过使用dplyr中的bind_rows()但是产生了:

id     Date     col1     col2     col3     col4     col5     col6
1      date1    <int>    <int>      NA       NA       NA       NA
2      date1    <int>    <int>      NA       NA       NA       NA
3      date1    <int>    <int>      NA       NA       NA       NA
1      date1       NA       NA    <int>    <int>      NA       NA
2      date1       NA       NA    <int>    <int>      NA       NA
3      date1       NA       NA    <int>    <int>      NA       NA
1      date1       NA       NA      NA       NA     <int>    <int> 
2      date1       NA       NA      NA       NA     <int>    <int>
3      date1       NA       NA      NA       NA     <int>    <int>
1      date2    <int>    <int>      NA       NA       NA       NA
2      date2    <int>    <int>      NA       NA       NA       NA
3      date2    <int>    <int>      NA       NA       NA       NA
1      date2       NA       NA    <int>    <int>      NA       NA
2      date2       NA       NA    <int>    <int>      NA       NA
3      date2       NA       NA    <int>    <int>      NA       NA
1      date2       NA       NA      NA       NA     <int>    <int> 
2      date2       NA       NA      NA       NA     <int>    <int>
3      date2       NA       NA      NA       NA     <int>    <int>

这不是世界末日,但文件大小是它需要的5倍。理想情况下,数据结构如下:

id     Date     col1     col2     col3     col4     col5     col6
1      date1    <int>    <int>    <int>    <int>    <int>    <int>
2      date1    <int>    <int>    <int>    <int>    <int>    <int>
3      date1    <int>    <int>    <int>    <int>    <int>    <int>
1      date2    <int>    <int>    <int>    <int>    <int>    <int>
2      date2    <int>    <int>    <int>    <int>    <int>    <int>
3      date2    <int>    <int>    <int>    <int>    <int>    <int>

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

您需要先在第一组上使用合并功能,然后才能对数据框进行处理。 使用data.table库,非常有效:

Reduce(merge,df.list[1:3])

将给出合并的数据框

   id  Date  col1  col2  col3  col4  col5  col6
1:  1 date1 <int> <int> <int> <int> <int> <int>
2:  2 date1 <int> <int> <int> <int> <int> <int>
3:  3 date1 <int> <int> <int> <int> <int> <int>

然后你需要用lapply列出它们,并将rbind应用到该列表

do.call("rbind",lapply(list(c(1:3),c(4:6)),function(x){Reduce(merge,df.list[x])}))

   id  Date  col1  col2  col3  col4  col5  col6
1:  1 date1 <int> <int> <int> <int> <int> <int>
2:  2 date1 <int> <int> <int> <int> <int> <int>
3:  3 date1 <int> <int> <int> <int> <int> <int>
4:  1 date2 <int> <int> <int> <int> <int> <int>
5:  2 date2 <int> <int> <int> <int> <int> <int>
6:  3 date2 <int> <int> <int> <int> <int> <int>

数据:

library(data.table)
df.list <- list()

df.list[[1]] <- setDT(read.table(text = 
"  id     Date     col1     col2
  1      date1    <int>    <int>
  2      date1    <int>    <int>
  3      date1    <int>    <int>",
header = TRUE, stringsAsFactors = FALSE))

df.list[[2]] <- setDT(read.table(text = 
"  id     Date     col3     col4
  1      date1    <int>    <int>
  2      date1    <int>    <int>
  3      date1    <int>    <int>",
 header = TRUE, stringsAsFactors = FALSE))

df.list[[3]] <- setDT(read.table(text = 
"  id     Date     col5     col6
 1      date1    <int>    <int>
 2      date1    <int>    <int>
 3      date1    <int>    <int>",
 header = TRUE, stringsAsFactors = FALSE))


df.list[[4]] <- setDT(read.table(text = 
 "  id     Date     col1     col2
     1      date2    <int>    <int>
     2      date2    <int>    <int>
     3      date2    <int>    <int>",
     header = TRUE, stringsAsFactors = FALSE))

df.list[[5]] <- setDT(read.table(text = 
  "  id     Date     col3     col4
  1      date2    <int>    <int>
  2      date2    <int>    <int>
  3      date2    <int>    <int>",
  header = TRUE, stringsAsFactors = FALSE))

df.list[[6]] <- setDT(read.table(text = 
    "  id     Date     col5     col6
    1      date2    <int>    <int>
    2      date2    <int>    <int>
    3      date2    <int>    <int>",
    header = TRUE, stringsAsFactors = FALSE))

答案 1 :(得分:0)

在这里我认为你正在寻找tidyverse:

library(tidyverse)

ex_list <- list(df1, df2, df3, df4)

ex_list %>% 
  bind_rows() %>% 
  gather(measure, value, col1:col4) %>% 
  na.omit() %>% 
  spread(measure, value) %>% 
  arrange(date)


# A tibble: 6 x 6
     id       date  col1  col2  col3  col4
  <dbl>     <date> <dbl> <dbl> <dbl> <dbl>
1     1 2017-01-01     1     4     7    10
2     2 2017-01-01     2     5     8    11
3     3 2017-01-01     3     6     9    12
4     1 2017-01-02    11    14    21    24
5     2 2017-01-02    12    15    22    25
6     3 2017-01-02    13    16    23    26

数据:

 df1 <- tibble(
      id = c(1,2,3),
      date = as.Date(c("2017-01-01", "2017-01-01", "2017-01-01")),
      col1 = c(1, 2, 3),
      col2 = c(4, 5, 6)
    )

    df2 <- tibble(
      id = c(1,2,3),
      date = as.Date(c("2017-01-01", "2017-01-01", "2017-01-01")),
      col3 = c(7, 8, 9),
      col4 = c(10, 11, 12)
    )

    df3 <- tibble(
      id = c(1,2,3),
      date = as.Date(c("2017-01-02", "2017-01-02", "2017-01-02")),
      col1 = c(11, 12, 13),
      col2 = c(14, 15, 16)
    )

    df4 <- tibble(
      id = c(1,2,3),
      date = as.Date(c("2017-01-02", "2017-01-02", "2017-01-02")),
      col3 = c(21, 22, 23),
      col4 = c(24, 25, 26)
    )