如何识别所有未包含在“到”和“从”位置中的序号?

Pow*_*ege 6 r sequence large-data

我有一个数据表,该数据表定义了一组序列的开始和结束坐标。例如:

df1 <- data.frame(from = c(7, 22, 35, 21, 50),
              to = c(13, 29, 43, 31, 60))
Run Code Online (Sandbox Code Playgroud)

给定开始和结束坐标(即1和100),我试图使用相同的输出格式来识别序列未涵盖的所有整数。例如:

df2 <- data.frame(from = c(1, 14, 32, 44, 61),
              to = c(6, 20, 34, 49, 100))
Run Code Online (Sandbox Code Playgroud)

这是我目前的尝试,其中我对df1中的序列进行矢量化处理,然后识别出与序列1:100不匹配的所有整数。

seq2 <- Vectorize(seq.default, vectorize.args = c("from", "to"))
seq <- c(1:100)
df1_int <- unlist(seq2(from = df1$from, to = df1$to))
df1_int <- unique(df1_int)
df2_int <- seq[!seq %in% df1_int]
all(diff(df2_int) == 1)
Run Code Online (Sandbox Code Playgroud)

但是,这种方法对于我想将其应用于(〜100,000,000个整数)的数据集来说太慢了,而且我不知道如何将向量df2_int重新格式化为df2格式的数据帧。

任何帮助将不胜感激!

注意:df1中的序列并不总是以最低整数开头(例如,序列可以从13到7,而不是从7到13)。也可能只有一个整数(例如7到7)的序列。

jay*_*.sf 2

setdiff由于您需要一个快速的解决方案,我们可以尝试使用和 的基本 R 方法split。我们将矢量化留给mapply​​. split找到我们使用的因素findInterval。为了获取结果列表中元素的起点和终点,我们使用 进行清除range。

d <- setdiff(1:100, unlist(mapply(seq.default, df1[, 1], df1[, 2])))
t(sapply(split(d, findInterval(d, d[which(c(1, diff(d)) > 1)])), range))
#   [,1] [,2]
# 0    1    6
# 1   14   20
# 2   32   34
# 3   44   49
# 4   61  100
Run Code Online (Sandbox Code Playgroud)

基准

正如我们从基准测试中看到的,我们已经实现了相当快的解决方案。

Unit: microseconds
         expr      min        lq      mean    median       uq      max neval cld
        purrr 1575.479 1593.2110 1634.3573 1604.9475 1634.033 2028.095   100   b
 findInterval  250.801  256.9245  276.8609  273.3815  281.673  498.285   100  a 
Run Code Online (Sandbox Code Playgroud)