【问题标题】:More memory efficient overlap joins in RR中内存效率更高的重叠连接
【发布时间】:2020-07-28 23:11:47
【问题描述】:

考虑以下data.tables。 第一个是一组段,每个组都有开始和结束坐标"chr"

    library(data.table)
    set.seed(1L)
    n = 20e5L; k = 100e3L
    idx1 = sample(n, 5000, TRUE)
    idx2 = sample(n, 5000, TRUE)

    d1 = unique(data.table(chr = sample(c(1:22), n, TRUE), 
                    segment.start = pmin(idx1, idx2), 
                    segment.end = pmax(idx1, idx2)))
    setkey(d1, chr, segment.start, segment.end)

#   chr segment.start segment.end
#    1           213     1073538
#    1           242     1571071
#    1           401      270962
#    1          1142      832856
#    1          1211     1906488
#    1          1313      609844

第二个数据集具有相同的分组变量"chr",在每个组中的位置"pos"

    d2 = unique(data.table(chr = sample(c(1:22), k, TRUE), 
                           pos = sample(n, k, TRUE)))
    d2[, pos2 := pos]
    setkey(d2, chr, pos, pos2)

#  chr  pos pos2
#    1  774  774
#    1  870  870
#    1 1312 1312
#    1 2256 2256
#    1 2611 2611
#    1 2727 2727

我目前正在使用data.table::foverlaps 来计算d1 中与d2"pos" 重叠的开始/结束段数"chr"

    outdf <- foverlaps(d2, d1) [, .(count = sum(!is.na(segment.start))), by = .(chr,pos, pos2) ][, pos2 := NULL ]

#  chr  pos count
#    1  774     3
#    1  870     3
#    1 1312     5
#    1 2256    11
#    1 2611    14
#    1 2727    16

查看Profvis 输出,此示例数据集的内存使用量峰值约为 9.5GB,而我正在使用的实际数据集的内存使用量峰值约为 85GB。

有谁知道在不显着增加运行时间的情况下获得所需输出的内存效率更高的方法?

【问题讨论】:

  • 你的 pos 和 pos2 在 d2 中是一样的吗?
  • 是的。我相信第二列对于 foverlaps 是必要的。
  • 你可以尝试非 equi join 看看内存使用是否更少

标签: r data.table


【解决方案1】:

你可以试试下面的...

但我没有足够的profvis() 经验来解释结果。虽然速度更快...

d2[, N := d1[ d2, 
              on = .(chr, segment.start <= pos, segment.end >= pos), 
              .N, 
              by=.EACHI, 
              allow.cartesian = TRUE]$N ]

基准测试

microbenchmark::microbenchmark(
  wimpel = {
    dt1 <- copy(d1)
    dt2 <- copy(d2)
    d2[, N := d1[ d2, 
                  on = .(chr, segment.start <= pos, segment.end >= pos), 
                  .N, 
                  by=.EACHI, 
                  allow.cartesian = TRUE]$N ]
    },
  your_solution = {
    dt1 <- copy(d1)
    dt2 <- copy(d2)
    outdf <- foverlaps(d2, d1)[, .(count = sum(!is.na(segment.start))), by = .(chr,pos, pos2) ][, pos2 := NULL ]
  },
  times = 3L
  )

# Unit: seconds
#          expr      min        lq     mean    median       uq       max neval
#        wimpel  7.62565  7.781653  7.96709  7.937655  8.13781  8.337965     3
# your_solution 13.89000 14.032308 14.09881 14.174619 14.20321 14.231810     3

【讨论】:

  • 感谢您提供这个替代方案!它确实更快,但它使用了大约 33% 的内存,所以不幸的是,它不是解决我特定问题的理想解决方案。
猜你喜欢
  • 2017-06-21
  • 1970-01-01
  • 2020-06-18
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 2019-05-06
  • 1970-01-01
  • 2018-04-20
相关资源
最近更新 更多