#r #dplyr
#r #dplyr
Вопрос:
У меня есть фрейм данных, который включает в себя 2 столбца, скажем, «левый» и «правый», которые определяют интервалы. Я хочу проверить, является ли данное число «x» частью любого интервала, определенного фреймом данных (если это так, оно должно быть только один раз, эти интервалы не перекрываются). Ожидаемое поведение:
> df <- data.frame(id = c("A", "B", "C"), left = c(0, 50, 150), right = c(15, 78, 190))
> df
id left right
1 A 0 15
2 B 50 78
3 C 150 190
> my_function(7)
TRUE
> my_function(20)
FALSE
Итак, я сделал это таким образом, но это ужасно медленно, и я уверен, что это можно было бы оптимизировать:
my_function <- function(x) {
test <- df %>% dplyr::rowwise() %>% dplyr::mutate(test = (x >= left) amp;amp; (x <= right)) %>% ungroup()
test <- test %>% filter(test == T)
nrow(test) == 1
}
Тогда мне было бы интересно получить соответствующую строку в случае, если вывод TRUE, но с текущей функцией это займет целую вечность (фактический фрейм данных содержит ~ 5000 строк, и я хочу проверить / получить координаты для тысяч значений x).
Я нашел библиотеку, которая управляет объектами интервалов, но, похоже, она адаптирована для временных интервалов. Есть предложения?
Ответ №1:
Вот простой способ с примером:
z <- 567 # single dummy value
left <- x1 <- seq(100, 900, 200)
right <- seq(200, 1000, 200)
df <- data.frame(left, right) # dummy intervals
lo <- z >= df$left
hi <- z <= df$right
check <- lo * hi
introw <- which(check == 1)
introw
3
z2 <- c(356, 934, 134, 597, 771) # vector of values to check
lo2 <- sapply(z2, function(x) x >= df$left)
hi2 <- sapply(z2, function(x) x <= df$right)
check2 <- lo2 * hi2
introws <- apply(check2, 2, function(x) which(x ==1))
introws #vector of intervals for each input value
introws
2 5 1 3 4
final <- cbind(value = z2, interval = introws)
final
value interval
[1,] 356 2
[2,] 934 5
[3,] 134 1
[4,] 597 3
[5,] 771 4
Комментарии:
1. Это действительно выглядит лучше, хотя все еще немного медленно
user system elapsed 80.435 4.117 84.951
2. Я векторизовал свою функцию, поэтому я могу избавиться от
rowwise()
ungroup()
вызовов and . Теперь намного быстрее! Спасибоuser system elapsed 0.260 0.026 0.290
Ответ №2:
Попробуйте этот подход, используя between()
:
#Code
my_function <- function(x) {
test <- df %>% dplyr::rowwise() %>%
dplyr::mutate(test = between(x,left,right)) %>% ungroup()
test <- test %>% filter(test == T)
nrow(test) == 1
}
Комментарии:
1.Это так же медленно:
user system elapsed 125.149 4.637 130.022
user system elapsed 135.310 4.640 140.233
2. @rioulan. Re: «Это так же медленно» Почему бы вам не попробовать мой ответ и не сообщить о результатах. Просто подключите свои собственные векторы для
df$left
,df$right
иz2
3. О, ваш ответ исчез