将数据帧与"一个列名称共同使用该公共列中的不同数量的元素"合而为一

时间:2017-12-13 14:17:18

标签: r dataframe merge

假设我们有5个数据帧,其中一列基于相同的时间戳("年");每个都有可能有不同数量的行和列,但每个都有一个名为year的第一列。每个开始和结束在不同的年份,因此所有数据帧中没有共同的开始或结束日期。我们希望根据收集这些数据的年份将所有数据帧组合成一个(即,在特定年份的一个矩阵中收集的数据,对应于同一年的其他数据帧中的数据)。对于那些没有相应年份的数据帧,我们希望用NA填充这些空白。

我们如何排列数据并将它们合并为一个数据框?

假设为了论证,我们有以下数据帧:

M1 <- data.frame(year=2000:2010, v1=16:26, v2=25:35)
M1; dim(M1) # 11x3
M2 <- data.frame(year=2005:2018, v3=6:19, v4=5:18, v5=3:16)
M2; dim(M2) #14x4
M3 <- data.frame(year=2002:2016, v3=3:17, v6=2:16, v7=0:14)
M3; dim(M3) # 15x4
M4 <- data.frame(year=2008:2020, v3=9:21, v6=8:20, v8=6:18)
M4; dim(M4) # 13x4
M5 <- data.frame(year=2018:2020, v9=19:21, v10=18:20, v11=16:18, v12=29:31)
M5; dim(M5) # 3x5

注意:另一个useR询问了一个非常相似的问题,并且由推理结束&#34;不清楚&#34;。我整整地澄清了他的问题。

4 个答案:

答案 0 :(得分:3)

我认为使用full_join的{​​{1}}命令效率更高。每次需要加入新数据帧时,您都可以使用dplyr,或者在full_join函数中使用一次,以便按顺序工作。请参阅以下两种方法:

reduce

第一种方法:

# create example datasets
M1 <- data.frame(year=2000:2010, v1=16:26, v2=25:35)
M2 <- data.frame(year=2005:2018, v3=6:19, v4=5:18, v5=3:16)
M3 <- data.frame(year=2002:2016, v3=3:17, v6=2:16, v7=0:14)
M4 <- data.frame(year=2008:2020, v3=9:21, v6=8:20, v8=6:18)
M5 <- data.frame(year=2018:2020, v9=19:21, v10=18:20, v11=16:18, v12=29:31)

第二种方法:

library(dplyr)

# use the full_join command
# you have to "manually" use a full_join command for every new dataset you want to join 
full_join(M1, M2, by="year") %>%
  full_join(M3, by="year") %>%
  full_join(M4, by="year") %>%
  full_join(M5, by="year")

#    year v1 v2 v3.x v4 v5 v3.y v6.x v7 v3 v6.y v8 v9 v10 v11 v12
# 1  2000 16 25   NA NA NA   NA   NA NA NA   NA NA NA  NA  NA  NA
# 2  2001 17 26   NA NA NA   NA   NA NA NA   NA NA NA  NA  NA  NA
# 3  2002 18 27   NA NA NA    3    2  0 NA   NA NA NA  NA  NA  NA
# 4  2003 19 28   NA NA NA    4    3  1 NA   NA NA NA  NA  NA  NA
# 5  2004 20 29   NA NA NA    5    4  2 NA   NA NA NA  NA  NA  NA
# 6  2005 21 30    6  5  3    6    5  3 NA   NA NA NA  NA  NA  NA
# 7  2006 22 31    7  6  4    7    6  4 NA   NA NA NA  NA  NA  NA
# 8  2007 23 32    8  7  5    8    7  5 NA   NA NA NA  NA  NA  NA
# 9  2008 24 33    9  8  6    9    8  6  9    8  6 NA  NA  NA  NA
# 10 2009 25 34   10  9  7   10    9  7 10    9  7 NA  NA  NA  NA
# 11 2010 26 35   11 10  8   11   10  8 11   10  8 NA  NA  NA  NA
# 12 2011 NA NA   12 11  9   12   11  9 12   11  9 NA  NA  NA  NA
# 13 2012 NA NA   13 12 10   13   12 10 13   12 10 NA  NA  NA  NA
# 14 2013 NA NA   14 13 11   14   13 11 14   13 11 NA  NA  NA  NA
# 15 2014 NA NA   15 14 12   15   14 12 15   14 12 NA  NA  NA  NA
# 16 2015 NA NA   16 15 13   16   15 13 16   15 13 NA  NA  NA  NA
# 17 2016 NA NA   17 16 14   17   16 14 17   16 14 NA  NA  NA  NA
# 18 2017 NA NA   18 17 15   NA   NA NA 18   17 15 NA  NA  NA  NA
# 19 2018 NA NA   19 18 16   NA   NA NA 19   18 16 19  18  16  29
# 20 2019 NA NA   NA NA NA   NA   NA NA 20   19 17 20  19  17  30
# 21 2020 NA NA   NA NA NA   NA   NA NA 21   20 18 21  20  18  31

答案 1 :(得分:2)

你可以这样做,

Reduce(function(x, y)merge(x, y, by = 'year', all = TRUE), mget(ls(pattern = 'M[0-9]+')))

给出,

   year v1 v2 v3.x v4 v5 v3.y v6.x v7 v3 v6.y v8 v9 v10 v11 v12
1  2000 16 25   NA NA NA   NA   NA NA NA   NA NA NA  NA  NA  NA
2  2001 17 26   NA NA NA   NA   NA NA NA   NA NA NA  NA  NA  NA
3  2002 18 27   NA NA NA    3    2  0 NA   NA NA NA  NA  NA  NA
4  2003 19 28   NA NA NA    4    3  1 NA   NA NA NA  NA  NA  NA
5  2004 20 29   NA NA NA    5    4  2 NA   NA NA NA  NA  NA  NA
6  2005 21 30    6  5  3    6    5  3 NA   NA NA NA  NA  NA  NA
7  2006 22 31    7  6  4    7    6  4 NA   NA NA NA  NA  NA  NA
8  2007 23 32    8  7  5    8    7  5 NA   NA NA NA  NA  NA  NA
9  2008 24 33    9  8  6    9    8  6  9    8  6 NA  NA  NA  NA
10 2009 25 34   10  9  7   10    9  7 10    9  7 NA  NA  NA  NA
11 2010 26 35   11 10  8   11   10  8 11   10  8 NA  NA  NA  NA
12 2011 NA NA   12 11  9   12   11  9 12   11  9 NA  NA  NA  NA
13 2012 NA NA   13 12 10   13   12 10 13   12 10 NA  NA  NA  NA
14 2013 NA NA   14 13 11   14   13 11 14   13 11 NA  NA  NA  NA
15 2014 NA NA   15 14 12   15   14 12 15   14 12 NA  NA  NA  NA
16 2015 NA NA   16 15 13   16   15 13 16   15 13 NA  NA  NA  NA
17 2016 NA NA   17 16 14   17   16 14 17   16 14 NA  NA  NA  NA
18 2017 NA NA   18 17 15   NA   NA NA 18   17 15 NA  NA  NA  NA
19 2018 NA NA   19 18 16   NA   NA NA 19   18 16 19  18  16  29
20 2019 NA NA   NA NA NA   NA   NA NA 20   19 17 20  19  17  30
21 2020 NA NA   NA NA NA   NA   NA NA 21   20 18 21  20  18  31

答案 2 :(得分:2)

某些数据框确实具有相同的列名。因此,同一年份和列名称可能有不同的值。

因此,我建议rbindlist()所有数据框,并使用melt()dcast()使用适当的聚合函数,这将使这些&#34;重复&#34;条目可见:

df_list <- mget(paste0("M", 1:5))

library(datat.table)
rbindlist(df_list, use.names = TRUE, fill = TRUE, idcol = "df")[
  , melt(.SD, id.vars = c("df", "year"), na.rm = TRUE)][
    , dcast(.SD, year ~ variable, function(x) toString(unique(x)))]
    year v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12
 1: 2000 16 25                                 
 2: 2001 17 26                                 
 3: 2002 18 27  3        2  0                  
 4: 2003 19 28  4        3  1                  
 5: 2004 20 29  5        4  2                  
 6: 2005 21 30  6  5  3  5  3                  
 7: 2006 22 31  7  6  4  6  4                  
 8: 2007 23 32  8  7  5  7  5                  
 9: 2008 24 33  9  8  6  8  6  6               
10: 2009 25 34 10  9  7  9  7  7               
11: 2010 26 35 11 10  8 10  8  8               
12: 2011       12 11  9 11  9  9               
13: 2012       13 12 10 12 10 10               
14: 2013       14 13 11 13 11 11               
15: 2014       15 14 12 14 12 12               
16: 2015       16 15 13 15 13 13               
17: 2016       17 16 14 16 14 14               
18: 2017       18 17 15 17    15               
19: 2018       19 18 16 18    16 19  18  16  29
20: 2019       20       19    17 20  19  17  30
21: 2020       21       20    18 21  20  18  31
    year v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12

或者,源数据框的名称可用于使列名称唯一:

rbindlist(df_list, use.names = TRUE, fill = TRUE, idcol = "df")[
  , melt(.SD, id.vars = c("df", "year"), na.rm = TRUE)][
    , dcast(.SD, year ~ paste(variable, df, sep = "_"))]
    year v10_M5 v11_M5 v12_M5 v1_M1 v2_M1 v3_M2 v3_M3 v3_M4 v4_M2 v5_M2 v6_M3 v6_M4 v7_M3 v8_M4 v9_M5
 1: 2000     NA     NA     NA    16    25    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
 2: 2001     NA     NA     NA    17    26    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
 3: 2002     NA     NA     NA    18    27    NA     3    NA    NA    NA     2    NA     0    NA    NA
 4: 2003     NA     NA     NA    19    28    NA     4    NA    NA    NA     3    NA     1    NA    NA
 5: 2004     NA     NA     NA    20    29    NA     5    NA    NA    NA     4    NA     2    NA    NA
 6: 2005     NA     NA     NA    21    30     6     6    NA     5     3     5    NA     3    NA    NA
 7: 2006     NA     NA     NA    22    31     7     7    NA     6     4     6    NA     4    NA    NA
 8: 2007     NA     NA     NA    23    32     8     8    NA     7     5     7    NA     5    NA    NA
 9: 2008     NA     NA     NA    24    33     9     9     9     8     6     8     8     6     6    NA
10: 2009     NA     NA     NA    25    34    10    10    10     9     7     9     9     7     7    NA
11: 2010     NA     NA     NA    26    35    11    11    11    10     8    10    10     8     8    NA
12: 2011     NA     NA     NA    NA    NA    12    12    12    11     9    11    11     9     9    NA
13: 2012     NA     NA     NA    NA    NA    13    13    13    12    10    12    12    10    10    NA
14: 2013     NA     NA     NA    NA    NA    14    14    14    13    11    13    13    11    11    NA
15: 2014     NA     NA     NA    NA    NA    15    15    15    14    12    14    14    12    12    NA
16: 2015     NA     NA     NA    NA    NA    16    16    16    15    13    15    15    13    13    NA
17: 2016     NA     NA     NA    NA    NA    17    17    17    16    14    16    16    14    14    NA
18: 2017     NA     NA     NA    NA    NA    18    NA    18    17    15    NA    17    NA    15    NA
19: 2018     18     16     29    NA    NA    19    NA    19    18    16    NA    18    NA    16    19
20: 2019     19     17     30    NA    NA    NA    NA    20    NA    NA    NA    19    NA    17    20
21: 2020     20     18     31    NA    NA    NA    NA    21    NA    NA    NA    20    NA    18    21
    year v10_M5 v11_M5 v12_M5 v1_M1 v2_M1 v3_M2 v3_M3 v3_M4 v4_M2 v5_M2 v6_M3 v6_M4 v7_M3 v8_M4 v9_M5

答案 3 :(得分:0)

步骤1:在考虑所有数据框的情况下找出最小和最大年份:

min(M1["year"], M2["year"], M3["year"], M4["year"], M5["year"]) # 2000
max(M1["year"], M2["year"], M3["year"], M4["year"], M5["year"]) # 2020

步骤2:通过抽取相关的NA来扩展M1到M5,并在开始和结束时注意缺失的年份

M1NA <- rbind(M1, data.frame(year=2011:2020, v1=NA, v2=NA))
M1NA
M2NA <- rbind(data.frame(year=2000:2004, v3=NA, v4=NA, v5=NA), M2, data.frame(year=2019:2020, v3=NA, v4=NA, v5=NA))
M2NA
M3NA <- rbind(data.frame(year=2000:2001, v3=NA, v6=NA, v7=NA), M3, data.frame(year=2017:2020, v3=NA, v6=NA, v7=NA))
M3NA
M4NA <- rbind(data.frame(year=2000:2007, v3=NA, v6=NA, v8=NA), M4)
M4NA
M5NA <- rbind(data.frame(year=2000:2017, v9=NA, v10=NA, v11=NA, v12=NA), M5)
M5NA

步骤3:在最终数据帧中合并NA'ed数据帧;无需在其他数据框中重复年份列,因此删除它们。

CombinedFrame <- cbind(M1NA, M2NA[-1], M3NA[-1], M4NA[-1], M5NA[-1])
CombinedFrame

如果是矩阵,请执行以下操作:
通过以下任一方式将结果数据帧转换为矩阵:

CombinedMatrix <- as.matrix(sapply(CombinedFrame, as.numeric))
CombinedMatrix
CombinedMatrix <- matrix(as.numeric(unlist(CombinedFrame)),nrow=nrow(CombinedFrame))
CombinedMatrix

注意:上述转换考虑了数据帧中字符串存在的可能性(即开头的矩阵)

这会产生以下内容(正如所需):

     year v1 v2 v3 v4 v5 v3 v6 v7 v3 v6 v8 v9 v10 v11 v12
 [1,] 2000 16 25 NA NA NA NA NA NA NA NA NA NA  NA  NA  NA
 [2,] 2001 17 26 NA NA NA NA NA NA NA NA NA NA  NA  NA  NA
 [3,] 2002 18 27 NA NA NA  3  2  0 NA NA NA NA  NA  NA  NA
 [4,] 2003 19 28 NA NA NA  4  3  1 NA NA NA NA  NA  NA  NA
 [5,] 2004 20 29 NA NA NA  5  4  2 NA NA NA NA  NA  NA  NA
 [6,] 2005 21 30  6  5  3  6  5  3 NA NA NA NA  NA  NA  NA
 [7,] 2006 22 31  7  6  4  7  6  4 NA NA NA NA  NA  NA  NA
 [8,] 2007 23 32  8  7  5  8  7  5 NA NA NA NA  NA  NA  NA
 [9,] 2008 24 33  9  8  6  9  8  6  9  8  6 NA  NA  NA  NA
[10,] 2009 25 34 10  9  7 10  9  7 10  9  7 NA  NA  NA  NA
[11,] 2010 26 35 11 10  8 11 10  8 11 10  8 NA  NA  NA  NA
[12,] 2011 NA NA 12 11  9 12 11  9 12 11  9 NA  NA  NA  NA
[13,] 2012 NA NA 13 12 10 13 12 10 13 12 10 NA  NA  NA  NA
[14,] 2013 NA NA 14 13 11 14 13 11 14 13 11 NA  NA  NA  NA
[15,] 2014 NA NA 15 14 12 15 14 12 15 14 12 NA  NA  NA  NA
[16,] 2015 NA NA 16 15 13 16 15 13 16 15 13 NA  NA  NA  NA
[17,] 2016 NA NA 17 16 14 17 16 14 17 16 14 NA  NA  NA  NA
[18,] 2017 NA NA 18 17 15 NA NA NA 18 17 15 NA  NA  NA  NA
[19,] 2018 NA NA 19 18 16 NA NA NA 19 18 16 19  18  16  29
[20,] 2019 NA NA NA NA NA NA NA NA 20 19 17 20  19  17  30
[21,] 2020 NA NA NA NA NA NA NA NA 21 20 18 21  20  18  31