R 如何基于不同变量中的共享值获取变量中的所有值对

R 如何基于不同变量中的共享值获取变量中的所有值对,r,dataframe,combinations,R,Dataframe,Combinations,我的问题可能有点难以解释,因此我还没有找到任何解决方案,但我会尝试: 我不想根据它们是否共享另一个变量中的任何值来查找变量中的所有值对。也许下面的例子可以更清楚地说明这一点 在这样的2变量数据帧中: data.frame(scaffold = c("A", "A", "B", "B", "B", "C", "C", "D"), geneID = c("162", "276", "64", "276", "281", "64", "162", "162")) #>

我的问题可能有点难以解释,因此我还没有找到任何解决方案,但我会尝试:

我不想根据它们是否共享另一个变量中的任何值来查找变量中的所有值对。也许下面的例子可以更清楚地说明这一点

在这样的2变量数据帧中:

data.frame(scaffold = c("A", "A", "B", "B", "B", "C", "C", "D"), 
           geneID = c("162", "276", "64", "276", "281", "64", "162", "162"))
#>  scaffold geneID
#>         A    162
#>         A    276
#>         B     64
#>         B    276
#>         B    281
#>         C     64
#>         C    162
#>         D    162
data.frame(V1 = c("A", "A", "A", "B", "C"), V2 =c("B", "C", "D", "C", "D"))                                                         

#>  V1 V2
#>   A  B
#>   A  C
#>   A  D
#>   B  C
#>   C  D
。。。我想找到所有成对的“脚手架”
A
B
C
、和
D
,它们共享任何一个“geneID”的
64
162
176
、和
281
,这样上述内容将成为一个数据框架,所有成对的脚手架都位于两个新列中,如下所示:

data.frame(scaffold = c("A", "A", "B", "B", "B", "C", "C", "D"), 
           geneID = c("162", "276", "64", "276", "281", "64", "162", "162"))
#>  scaffold geneID
#>         A    162
#>         A    276
#>         B     64
#>         B    276
#>         B    281
#>         C     64
#>         C    162
#>         D    162
data.frame(V1 = c("A", "A", "A", "B", "C"), V2 =c("B", "C", "D", "C", "D"))                                                         

#>  V1 V2
#>   A  B
#>   A  C
#>   A  D
#>   B  C
#>   C  D
显然,A和B与B和A是同一对,所以应该以某种方式删除它们,但这可能很容易。之后,需要将该数据框与包含支架x/y坐标的数据框组合,以便在支架绘图顶部的对之间绘制一条线

我确实有一个working for循环来完成这项工作,但我需要用一个更快的替代方案来取代它。我不给你代码了,它很复杂,而且不总是正确的。在20个脚手架上运行可能需要几秒钟,但我需要在数千个脚手架上运行。我希望一系列的
dplyr
数据。table
函数可以完成这项工作,因为它们可能会以最快的速度完成,但我还没有弄清楚如何完成

我希望你能帮助我,或者类似的东西已经在另一个我无法发现的威胁中了



@Florian和@Roman对这两种解决方案的性能比较可以在

中找到,这是一种可能的解决方案。请注意,我修改了您的示例
df
,因此
A
C
共享
162
64
,我们必须确保此组不会在输出中出现两次

df  = data.frame(scaffold = c("A", "A", "B", "B", "B", "C", "C", "D","A"), 
           geneID = c("162", "276", "64", "276", "281", "64", "162", "162","64"),stringsAsFactors = F)

y = split(df$scaffold,df$geneID)
unique(do.call(rbind,(lapply(y[which(sapply(y, length) > 1)],function(x){t(combn(sort(x),2))}))))
输出:

     [,1] [,2]
[1,] "A"  "C" 
[2,] "A"  "D" 
[3,] "C"  "D" 
[4,] "A"  "B" 
[5,] "B"  "C" 
工作原理:首先,我们根据
df$geneID
将数据分成若干组,我们称之为
y
。然后,我们在
y
中的每个元素上重叠
y
一个函数,该函数将所有
n
2的可能组合作为
nx2
矩阵。通过在该函数中调用
x
上的
sort()
,我们以后可以更轻松地删除重复项,因为我们随后将
rbind
此列表放入一个大矩阵中,并对结果调用
unique()
,以删除重复项


希望这有帮助

请参见代码中的说明

xy <- data.frame(scaffold = c("A", "A", "B", "B", "B", "C", "C", "D"), 
           geneID = c("162", "276", "64", "276", "281", "64", "162", "162"))

# split by gene
xy1 <- split(xy, f = xy$geneID)

# find all combinations
out <- sapply(xy1, FUN = function(x) {
  x$scaffold <- as.character(x$scaffold)
  # add NA so that we can remove any cases that have a single scaffold
  tryCatch(t(combn(x$scaffold, 2)), error = function(e) NA)
}, simplify = FALSE)

# remove NAs and some fiddling to get the desired format
out <- out[!is.na(out)]
out <- do.call(rbind, out)

# sort the data
out <- t(apply(out, MARGIN = 1, FUN = function(x) sort(x)))

# remove duplicates
out <- out[!duplicated(out), ]
out

     [,1] [,2]
[1,] "A"  "C" 
[2,] "A"  "D" 
[3,] "C"  "D" 
[4,] "A"  "B" 
[5,] "B"  "C" 

xy非常感谢您的快速解决方案,效果非常好!谢谢!很好的解决方案。我将这个标记为答案,因为它比Roman在7000个脚手架上的速度快5倍。5秒对1秒,所以没什么大不了的,但会在更大的数据上:)用管道编写:
split%lappy(函数(split){sort(split)%%>%combn(m=2)%%>%t()})%%>%do.call(what=rbind)%%>%unique()
Hi kasper,很高兴我能帮上忙!你的管道实现看起来非常好,从来没有想过要这样写。@KasperSkytteAndersen我很想看看代码的计时和利润。如果您愿意,可以编辑您的问题以附加此信息。当然可以。干得好。数据在figshare上: