Какой самый быстрый способ определить, находится ли число в списке диапазонов? - PullRequest
2 голосов
/ 30 апреля 2020

Я действительно новичок в R, и я искал простой и быстрый способ проверить, находится ли число в списке диапазонов. например:

Numbers <- c(77,3,66)
RangesList <- data.frame(cbind(c(5,20,33,60,91),c(8,23,45,76,100)))
colnames(RangesList) <- c("Start","End")

> RangesList

  Start End
1     5   8
2    20  23
3    33  45
4    60  76
5    91 100

Теперь я ищу простой и быстрый способ (избегая "если", насколько это возможно), чтобы проверить для каждого числа в "Числа", находится ли оно в одном из диапазонов в RangesList. В приведенном выше примере я ожидаю, что функция будет иметь следующий результат: "FALSE" "FALSE" "TRUE" Мне нужно применить эту функцию к 100k строк, и мой список диапазонов составляет около 2000 строк - поэтому я подчеркиваю последствия времени выполнения (время выполнения с использованием «если» занимает ~ 5 минут), и я ищу более «элегантное» решение.

Спасибо :)

Ответы [ 2 ]

3 голосов
/ 30 апреля 2020

Вот способ использования sapply:

sapply(Numbers, function(x) any(x >= RangesList$Start & x <= RangesList$End))
#[1] FALSE FALSE  TRUE
1 голос
/ 30 апреля 2020

Опция путем установки ключа и использования неэкви-соединения в data.table:

library(data.table)
setDT(RangesList, key=c("Start", "End"))
RangesList[.(v=Numbers), on=.(Start<=v, End>=v), mult="first", by=.EACHI, .N > 0L]$V1

временный код:

set.seed(0L)
nn <- 100e3
nr <- 2e3
Numbers <- rnorm(nn)
s <- rnorm(nr); e <- rnorm(nr)
RangesList <- data.frame(Start=pmin(s, e), End=pmax(s, e))

library(data.table)
microbenchmark::microbenchmark(times=1L,
    base = abase <- sapply(Numbers, function(x) any(x >= RangesList$Start & x <= RangesList$End)),
    dt = adt <- {
        setDT(RangesList, key=c("Start", "End"))
        RangesList[.(v=Numbers), on=.(Start<=v, End>=v), mult="first", by=.EACHI, .N > 0L]$V1
    }
)
identical(abase, adt)
#[1] TRUE

время:

Unit: milliseconds
 expr       min        lq      mean    median        uq       max neval
 base 2338.6214 2338.6214 2338.6214 2338.6214 2338.6214 2338.6214     1
   dt  804.2691  804.2691  804.2691  804.2691  804.2691  804.2691     1
...