寻找最佳互惠匹配

时间:2017-07-28 03:31:32

标签: r dataframe datatable dplyr match

这是在两组相互映射的字符串之间找到最佳互惠匹配的问题。

我拥有的两个data.frame包含将第一个集映射到另一个集合(下面是df1)和其他映射方向(df2下面)的结果

映射获得score。此外,每个字符串都有一个parent,而且几个不同的字符串具有相同的parent

以下是模拟数据:

library(dplyr)
set.seed(1)

#generate the first string set mapping data.frame
df1 <- data.frame(query = paste("a",unlist(sapply(1:5,function(i) rep(i,ceiling(runif(1,1,3))))),sep="."),stringsAsFactors = F)

#add hits and scores
df1 <- do.call(rbind,lapply(unique(df1$query),function(q) {
  dplyr::filter(df1,query == q) %>%
    dplyr::mutate(hit = paste("b",sample(5,nrow(.),replace = F),sep="."),score = runif(nrow(.),0,100))

})) 

#add parents
df1 <- left_join(df1,data.frame(query=unique(df1$query),parent = paste("p.a",sample(3,5,replace=T),sep="."),stringsAsFactors = F),by=c("query"="query"))

#generate the second string set mapping data.frame
df2 <- data.frame(query = paste("b",unlist(sapply(1:5,function(i) rep(i,ceiling(runif(1,1,3))))),sep="."),stringsAsFactors = F)

#add hits and scores
df2 <- do.call(rbind,lapply(unique(df2$query),function(q) {
  dplyr::filter(df2,query == q) %>%
    dplyr::mutate(hit = paste("a",sample(5,nrow(.),replace = F),sep="."),
                  score = runif(nrow(.),0,100))

})) 

#add parents
df2 <- left_join(df2,data.frame(query=unique(df2$query),parent = paste("p.b",sample(3,5,replace=T),sep="."),stringsAsFactors = F),by=c("query"="query"))

我想要的是拥有一个返回以下内容的高效函数:

对于第一个集合中的每个字符串(unique(df1$query)),如果它映射到最高score的字符串映射回其最高score(倒数最佳匹配)返回该匹配的ID,映射score和匹配的parent ID,否则返回NA以获取匹配的ID和score。至于父级,如果parent是最佳互惠匹配,则返回匹配的parent ID,否则返回NA

生成的data.frame应包含以下列: set.a.idset.a.parent.idset.b.matchset.b.match.scoreset.b.parent.id

对于df1和df2,按queryscore排序:

df1[order(df1$query,-df1$score),]
   query hit    score parent
1    a.1 b.4 84.72860  p.a.1
2    a.1 b.1 57.64333  p.a.1
3    a.1 b.2 56.02473  p.a.1
5    a.2 b.3 82.18000  p.a.2
4    a.2 b.4 72.56507  p.a.2
6    a.2 b.1 59.24316  p.a.2
7    a.3 b.3 71.47014  p.a.3
8    a.3 b.4 22.60246  p.a.3
10   a.4 b.2 35.13778  p.a.2
11   a.4 b.1 26.89667  p.a.2
9    a.4 b.4 20.33758  p.a.2
12   a.5 b.2 26.85910  p.a.2
13   a.5 b.4 26.77832  p.a.2



df2[order(df2$query,-df2$score),]
   query hit    score parent
1    b.1 a.2 90.76623  p.b.2
2    b.1 a.5 24.57950  p.b.2
3    b.2 a.5 39.58975  p.b.1
4    b.2 a.1 39.11946  p.b.1
6    b.3 a.5 35.94917  p.b.1
5    b.3 a.4 11.57524  p.b.1
8    b.4 a.5 80.93301  p.b.2
7    b.4 a.4 57.07636  p.b.2
9    b.4 a.3 10.13098  p.b.2
11   b.5 a.5 49.70569  p.b.1
10   b.5 a.2 12.88346  p.b.1

这是结果data.frame

res.df <- data.frame(set.a.id = unique(df1$query),set.a.parent.id = unique(df1$parent),
                     set.b.match = c(NA,NA,NA,NA,"b.2"),set.b.match.score = c(NA,NA,NA,NA,26.85910),
                     set.b.parent.id = c(NA,"p.b.1",NA,"p.b.1","p.b.1"))

0 个答案:

没有答案