подмножество data.frame объединяет несколько интервалов - PullRequest
3 голосов
/ 09 февраля 2012

Рассмотрим следующее data.frame,

d <- data.frame(x = seq(0, 10, length=100), value = rnorm(100))

Я хочу установить подмножество на основе x, принадлежащего любому из следующих интервалов,

intervals <- list(c(0.2, 0.8), c(1, 2), c(8, 8.2))

test <- function(range, x){
  which(x >= range[1] & x <= range[2])
}

d[Reduce(`union`, lapply(intervals, test, x=d$x)), ]

Теперь функция тестирования кажется избыточной, так как выглядит очень похоже на встроенную findInterval, но я не могу найти элегантный способ ее использования.

condition <- Reduce(`|`, lapply(lapply(intervals,  findInterval,
                                       x=d$x, all.inside=FALSE), `==`, 1))

d[condition, ]

Можете ли вы предложить лучше?

Ответы [ 2 ]

4 голосов
/ 09 февраля 2012
d[unlist(sapply(intervals, function(x) which(!is.na(cut(d$x,x))))),]
           x       value
3  0.2020202  0.15488314
4  0.3030303 -0.06891842
5  0.4040404  1.59909655
6  0.5050505  0.31006866
7  0.6060606  1.68986821
8  0.7070707  0.18500635
11 1.0101010  0.18721091
12 1.1111111  0.32485063
13 1.2121212 -0.42728405
14 1.3131313  0.84220081
15 1.4141414 -1.30745237
16 1.5151515 -1.90335389
17 1.6161616 -0.47139683
18 1.7171717  0.01622827
19 1.8181818  0.76362918
20 1.9191919 -0.37827765
81 8.0808081  0.46672521
82 8.1818182  1.27038641

Редактировать: тот же результат, используя findInterval

d[findInterval(d$x,unlist(intervals))%%2==1,]
1 голос
/ 09 февраля 2012

Вот решение с пакетом intervals.

d <- data.frame(x = seq(0, 10, length=100), value = rnorm(100))
intervals <- list(c(0.2, 0.8), c(1, 2), c(8, 8.2))
library(intervals)
intervals <- Intervals( do.call( rbind, intervals ) )
intervals <- reduce( intervals )  # Simplify, if they overlap
condition <- distance_to_nearest(d$x, intervals) == 0
# The following would allow for non-closed intervals,
# but it is awfully slow.
condition <- sapply( d$x, function(u) 
  any(!empty(interval_intersection( Intervals(c(u,u)), intervals ))))
d[condition,]

С findInterval это может быть сложнее, потому что предполагается, что интервалы закрыты с одной стороны и открыты с другой. Если это приемлемо, если интервалы упорядочены и не перекрываются, вам просто нужно проверить, не является ли номер интервала нечетным.

intervals <- list(c(0.2, 0.8), c(1, 2), c(8, 8.2))
condition <- findInterval( d$x, unlist(intervals) ) %% 2 == 1
d[condition,]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...