【发布时间】:2017-01-04 20:32:02
【问题描述】:
我在 R 方面相对较新,我有一个关于合并两个数据帧的问题,这两个数据帧确实包含来自两个域(mz 和 rt)但不相同的相似数字数据。 这是一个描述我的问题的示例:
mz1 <- c(seq(100, 190, by = 10))
rt1 <- c(seq(1, 10, by = 1))
value1 <- runif(10, min = 100, max = 100000)
mz2 <- mz1 + runif(10, -0.1, 0.1)
rt2 <- rt1 + runif(10, -0.2, 0.2)
value2 <- runif(10, min = 100, max = 100000)
df1 <- as.data.frame(cbind(mz1, rt1, value1))
df2 <- as.data.frame(cbind(mz2, rt2, value2))
df1
mz1 rt1 value1
1 100 1 44605.646
2 110 2 13924.598
3 120 3 35727.265
4 130 4 75175.652
5 140 5 25221.724
6 150 6 29080.653
7 160 7 3170.749
8 170 8 10184.708
9 180 9 48055.072
10 190 10 77644.865
df2
mz2 rt2 value2
1 100.0243 1.043092 58099.49
2 110.0514 2.164753 76397.67
3 120.0258 2.838141 43901.05
4 130.0921 4.044322 34543.96
5 139.9577 5.023823 53086.10
6 150.0170 6.061794 13929.27
7 160.0884 6.828779 60905.61
8 170.0440 7.932000 66627.20
9 180.0872 9.116425 44587.62
10 189.9694 9.834091 51186.03
我想合并来自 df1 和 df2 的所有行,它们在 rt 域 和 在 mz 域中具有
到目前为止我所尝试的:
merge.data.frame(df1, df2, by.x = c("mz1", "rt1"), by.y = c("mz2", "rt2") , all = T)
mz1 rt1 value1 rt2 value2
1 100.0000 1 44605.646 NA NA
2 100.0243 NA NA 1.043092 58099.49
3 110.0000 2 13924.598 NA NA
4 110.0514 NA NA 2.164753 76397.67
5 120.0000 3 35727.265 NA NA
6 120.0258 NA NA 2.838141 43901.05
7 130.0000 4 75175.652 NA NA
8 130.0921 NA NA 4.044322 34543.96
9 139.9577 NA NA 5.023823 53086.10
10 140.0000 5 25221.724 NA NA
11 150.0000 6 29080.653 NA NA
12 150.0170 NA NA 6.061794 13929.27
13 160.0000 7 3170.749 NA NA
14 160.0884 NA NA 6.828779 60905.61
15 170.0000 8 10184.708 NA NA
16 170.0440 NA NA 7.932000 66627.20
17 180.0000 9 48055.072 NA NA
18 180.0872 NA NA 9.116425 44587.62
19 189.9694 NA NA 9.834091 51186.03
20 190.0000 10 77644.865 NA NA
这至少给了我一个正确格式的数据框,其中包含无法合并的 NA。
如果有人能帮我解决这个问题,那就太棒了!
问候
更新
好的,我会记住的。到目前为止谢谢。我尝试了以下想法:
#select data in joined which has no partner
no_match_df1 <- anti_join(joined, df2)
no_match_df1 <- no_match_df1[1:3]
#select data in df2 which has been excluded due to duplication
collist <- c("mz2", "rt2", "value2")
dublicates <- joined[complete.cases(joined[collist]), collist]
dublicates <- anti_join(df2, dublicates)
#repetition for joining
joined2 <- fuzzy_join(no_match_df1, dublicates, multi_by = c("mz1" = "mz2", "rt1" = "rt2"),
multi_match_fun = mmf, mode = "full")
joined2 <- group_by(joined2, mz1, rt1) %>%
mutate(min_dist = min(dist))
head(joined2)
joined2 <- filter(joined2, dist == min_dist | is.na(dist)) %>%
select(-dist, -min_dist)
head(joined2)
#select only rows with new match or where dublicates coulnd't find a partner
add <- subset(joined2, !is.na(joined2$mz2) | !is.na(joined2$mz2) & !is.na(joined2$mz1))
#add to joined
##I need some help here, how can I update the existing joined data frame?
也许我们可以像以前那样将no_match_df1 与duplicates 连接起来,然后通过覆盖现有joined 数据框中的特定行来添加结果。
最后,我们必须重复该过程作为日志,因为duplicates 的长度>1。
【问题讨论】:
-
您可以尝试查看包 fuzzyjoin。
-
我也从我的同事那里遇到过这样的案例,他们曾经嘲笑在 SAS 中实现这种合并的方式很容易。
-
@Marco,如果您需要更新您的问题,因为答案以某种方式帮助了您 edit 您自己的问题,而不是帮助您的答案。
-
好吧,对不起我的错误。我是新来的,这实际上是一次错误的点击。