如何根据不同变量

时间:2018-01-23 17:33:21

标签: 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"))
#>  scaffold geneID
#>         A    162
#>         A    276
#>         B     64
#>         B    276
#>         B    281
#>         C     64
#>         C    162
#>         D    162

...我想找到共享任何“geneID”的所有“脚手架”ABCD64162176281,以便上述内容将成为包含2个新列中所有支架对的数据框,如下所示:

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坐标的数据框组合,以便在支架上绘制一对线之间的线。

我确实有一个工作for循环来完成这项工作,但我需要用更快的替代方案替换它。我会为你节省代码,它很复杂,并不总是正确的。仅在20个脚手架上运行它可能需要几秒钟,但我需要在数千个脚手架上运行它。我希望一系列dplyrdata.table函数可以完成这项工作,因为它们可能会尽可能快,但我无法理解如何。

我希望你能帮助我,或者类似的东西已经处于我无法找到的另一个威胁中。

@Florian和@Roman对两种解决方案的性能比较可以在http://rpubs.com/kasperskytte/SO_question_48407650找到

2 个答案:

答案 0 :(得分:0)

这是一个可能的解决方案。请注意,我修改了您的示例df,因此AC共享16264,我们必须确保此组不会发生两次在输出中。

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。然后,我们lapply覆盖y中包含多个元素的每个元素,该函数为我们提供n个可能的2个nx2矩阵组合。通过调用此函数内sort()上的x,我们可以稍后更轻松地删除重复内容,因为我们将rbind此列表放入一个大矩阵中,并将结果调用unique()删除重复项。

希望这有帮助!

答案 1 :(得分:0)

见代码中的表彰。

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"