合并两个数据帧或小标题

时间:2018-08-03 13:19:53

标签: r

我有以下数据帧:

a <- data.frame(Test=1:4,
            TestA=5:6)
> a
    Test TestA
1    1     5
2    2     6
3    3     5
4    4     6


b <- data.frame(TEST=1:10,
            TestB=11:20)

> b
    TEST TestB
1     1    11
2     2    12
3     3    13
4     4    14
5     5    15
6     6    16
7     7    17
8     8    18
9     9    19
10   10    20

我想将它们组合起来,以便结果看起来像这样:

    Test TestA TEST   TestB
1     1     5    1      11
2     2     6    2      12
3     3     5    3      13
4     4     6    4      14
5     0     0    5      15
6     0     0    6      16
7     0     0    7      17
8     0     0    8      18
9     0     0    9      19
10    0     0   10      20

也就是说,要与填充零的不匹配行合并。

我坚信存在一个简单的解决方案,如果可以使用dplyr,那就很好了。

6 个答案:

答案 0 :(得分:1)

有了data.table,您可以

  1. b中预先填充0,然后
  2. 来自a
  3. update-join值

喜欢...

# input
a <- data.frame(Test=1:4, TestA=5:6)
b <- data.frame(TEST=1:10, TestB=11:20)
library(data.table)
setDT(a); setDT(b)

# prefill
b[, c("Test", "TestA") := 0L]

# update join
b[a, on=.(TEST = Test), c("Test", "TestA") := .(i.Test, i.TestA)]

    TEST TestB Test TestA
 1:    1    11    1     5
 2:    2    12    2     6
 3:    3    13    3     5
 4:    4    14    4     6
 5:    5    15    0     0
 6:    6    16    0     0
 7:    7    17    0     0
 8:    8    18    0     0
 9:    9    19    0     0
10:   10    20    0     0

这将修改b而不是创建新表。这适用于您的示例,但是如果您需要“完全连接”(其中b在最终表中没有您想要的完整行集合),则另一个答案会更好。

另一方面,如果您的表具有不希望用零填充的真实NA,则这是比前几个答案更好的方法(覆盖所有NA,不仅覆盖由于行不匹配而导致的NA)。表的联接/合并/组合)。


要归纳为更多列,请定义default值的列表...

# input
a <- data.frame(Test=1:4, TestA=5:6)
b <- data.frame(TEST=1:10, TestB=11:20)

library(data.table)
setDT(a); setDT(b)    
defaults = list(Test = 0L, TestA = 0L)
new_cols = names(defaults)

# prefill defaults
b[, (new_cols) := defaults]

# update join
b[a, on=.(TEST = Test), (new_cols) := mget(sprintf("i.%s", new_cols))]

答案 1 :(得分:1)

您可以使用软件包sqldf

library(sqldf)
res <- sqldf("SELECT a.*, b.* FROM b LEFT JOIN a on a.test = B.test")
res[is.na(res)] <- 0
res
#    Test TestA TEST TestB
# 1     1     5    1    11
# 2     2     6    2    12
# 3     3     5    3    13
# 4     4     6    4    14
# 5     0     0    5    15
# 6     0     0    6    16
# 7     0     0    7    17
# 8     0     0    8    18
# 9     0     0    9    19
# 10    0     0   10    20

或者仅使用SQL,将功能coalesce用作@G。格洛腾迪克提到:

sqldf("SELECT coalesce(a.Test, 0) Test, coalesce(a.TestA, 0) TestA, b.* FROM b LEFT JOIN a using(test)")

答案 2 :(得分:0)

要重复“测试”列并希望用0而不是NA有点不寻常,但正是您所要求的是:

library(dplyr)
b$Test <- b$TEST
c <- full_join(a,b, by="Test")
c$Test[is.na(c$TestA)] <-0
c$TestA[is.na(c$TestA)] <-0

答案 3 :(得分:0)

df <- merge(a, b, by = 0, all = TRUE,sort = FALSE)[-1]
df[is.na(df)] <- 0
df
   Test TestA TEST TestB
1     1     5    1    11
2     2     6    2    12
3     3     5    3    13
4     4     6    4    14
5     0     0    5    15
6     0     0    6    16
7     0     0    7    17
8     0     0    8    18
9     0     0    9    19
10    0     0   10    20

答案 4 :(得分:0)

您可以使用merge()合并两个数据帧。

df<-merge(x=a,y=b,by.x="Test",by.y = "TEST",all= T)

以上内容产生:

   Test TestA TestB
1     1     5    11
2     2     6    12
3     3     5    13
4     4     6    14
5     5    NA    15
6     6    NA    16
7     7    NA    17
8     8    NA    18
9     9    NA    19
10   10    NA    20

如果要将TestTEST分开,则可以为两者创建一个ID列,并用该ID变量替换by.xby.y

要将NA替换为0,可以使用df$TestA[is.na(TestA)]<-0。如果您想同时保留TestTest,则与TEST相同。

答案 5 :(得分:0)

# example datasets
a <- data.frame(Test=1:4,
                TestA=5:6)

b <- data.frame(TEST=1:10,
                TestB=11:20)

library(dplyr)

a %>%
  mutate(TEST = Test) %>%                        # duplicate Test column and give the name TEST
  full_join(b, by="TEST") %>%                    # full join 
  mutate_at(vars(Test, TestA), ~coalesce(.,0L))  # replace NAs with 0s for those two variables

#    Test TestA TEST TestB
# 1     1     5    1    11
# 2     2     6    2    12
# 3     3     5    3    13
# 4     4     6    4    14
# 5     0     0    5    15
# 6     0     0    6    16
# 7     0     0    7    17
# 8     0     0    8    18
# 9     0     0    9    19
# 10    0     0   10    20

您还可以使用mutate_all(~coalesce(.,0L)),但是如果您知道它们仅存在于这两列中,则无需查找所有NA。