【问题标题】:How do I get all pairs of values in a variable based on shared values in a different variable如何根据不同变量中的共享值获取变量中的所有值对
【发布时间】:2018-01-23 17:33:21
【问题描述】:

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

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

在这样的 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

...我想找到所有“脚手架”对ABCD,它们共享任何“geneID”64162176281,这样上面就变成了一个数据框,所有的脚手架对都在 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 找到

【问题讨论】:

    标签: r dataframe combinations


    【解决方案1】:

    这是一个可能的解决方案。请注意,我修改了您的示例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 的结果。然后我们lapplyy 的每个元素(其中包含多个元素)提供一个函数,该函数为我们提供了所有n 2 的可能组合作为nx2 矩阵。通过在此函数内部对x 调用sort(),我们可以更轻松地删除重复项,因为我们随后将rbind 这个列表变成一个大矩阵,并在结果上调用unique() 以删除重复项。

    希望这会有所帮助!

    【讨论】:

    • 非常感谢!很好的解决方案。我会将此标记为答案,因为它比 Roman 在 7000 个脚手架上的速度快 5 倍。 5 秒对 1 秒,所以没什么大不了的,但会在更大的数据上 :)
    • 用管道写的:split <- split(df$scaffold, df$geneID); shared_genes <- split[which(sapply(split, length) > 1)] %>% lapply(function(split) { sort(split) %>% combn(m = 2) %>% t() }) %>% do.call(what = rbind) %>% unique()
    • 嗨,kasper,很高兴我能帮上忙!而且你的管道实现看起来非常好,从来没有想过要这样写。
    • @KasperSkytteAndersen 我有兴趣查看代码的时序和分析。如果您愿意,可以编辑您的问题以附加此信息。
    • 当然。干得好。数据在figshare上:rpubs.com/kasperskytte/SO_question_48407650
    【解决方案2】:

    查看代码中的推荐。

    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" 
    

    【讨论】:

    • 非常感谢,快速解决方案,效果很好!
    猜你喜欢
    • 2015-09-30
    • 1970-01-01
    • 1970-01-01
    • 2020-07-03
    • 2013-07-06
    • 1970-01-01
    • 1970-01-01
    • 2022-07-12
    • 2011-01-08
    相关资源
    最近更新 更多