首页 > 解决方案 > R:合并2个数据帧,其中一个重复测量,在适当的地方保留NA

问题描述

假设我有 2 个数据框mergedf1每个样本都有重复测量(我实际上不知道有多少,并且每个样本可能不同),而df2对于相同的样本只有一个测量。

作为 MWE,这样的事情:

> df1=data.frame(letter=rep(LETTERS[1:5],each=3), val1=1:15)
> df2=data.frame(letter=LETTERS[1:5], val2=16:20)
> df1
   letter val1
1       A    1
2       A    2
3       A    3
4       B    4
5       B    5
6       B    6
7       C    7
8       C    8
9       C    9
10      D   10
11      D   11
12      D   12
13      E   13
14      E   14
15      E   15
> df2
  letter val2
1      A   16
2      B   17
3      C   18
4      D   19
5      E   20

我希望merge他们以这种方式反映这一点。截至目前,我可以这样做:

> merge(df1, df2)
   letter val1 val2
1       A    1   16
2       A    2   16
3       A    3   16
4       B    4   17
5       B    5   17
6       B    6   17
7       C    7   18
8       C    8   18
9       C    9   18
10      D   10   19
11      D   11   19
12      D   12   19
13      E   13   20
14      E   14   20
15      E   15   20

但理想情况下,我需要这个:

> merge(df1, df2, all=T)
   letter rep val1 val2
1       A   1    1   16
2       A   2    2   NA
3       A   3    3   NA
4       B   1    4   17
5       B   2    5   NA
6       B   3    6   NA
7       C   1    7   18
8       C   2    8   NA
9       C   3    9   NA
10      D   1   10   19
11      D   2   11   NA
12      D   3   12   NA
13      E   1   13   20
14      E   2   14   NA
15      E   3   15   NA

但是我从一开始就没有该rep列,所以我应该事后添加它,但我不知道如何......或者,也许merge有一些选项只列出该val2列的第一个匹配项......

有什么帮助吗?这应该很容易,但我进入循环并检查以添加该rep列,这可能不是这样。

标签: rdataframemerge

解决方案


我们可以将两个数据集连接在一起并创建一个rep列,该列是每个数据集的行号,letter然后val2转到NA第一行以外的行。

library(dplyr)

inner_join(df1, df2, by = 'letter') %>% 
  group_by(letter) %>% 
  mutate(rep = row_number(), 
         val2 = replace(val2, -1, NA))

#  letter  val1  val2   rep
#   <chr>  <int> <int> <int>
# 1 A          1    16     1
# 2 A          2    NA     2
# 3 A          3    NA     3
# 4 B          4    17     1
# 5 B          5    NA     2
# 6 B          6    NA     3
# 7 C          7    18     1
# 8 C          8    NA     2
# 9 C          9    NA     3
#10 D         10    19     1
#11 D         11    NA     2
#12 D         12    NA     3
#13 E         13    20     1
#14 E         14    NA     2
#15 E         15    NA     3

要替换多个此类val列而不一一明确提及它们,我们可以使用across

inner_join(df1, df2, by = 'letter') %>% 
  group_by(letter) %>% 
  mutate(rep = row_number(), 
         across(val2:valn, ~replace(., -1, NA)))

在基础 R 中:

df3 <- merge(df1, df2)
cols <- c('val2')
df3[duplicated(df3[c('letter', cols)]), cols] <- NA

推荐阅读