findInterval () avec des intervalles fermés à droite
Le grand findInterval() fonction dans R gauche-fermé en sous-intervalles dans son vec argument, comme montré dans ses docs:
si
i <- findInterval(x,v)nous avonsv[i[j]] <= x[j] < v[i[j] + 1]
si je veux des sous-intervalles droits-fermés, quelles sont mes options? Le meilleur que j'ai trouvé c'est ça:
findInterval.rightClosed <- function(x, vec, ...) {
fi <- findInterval(x, vec, ...)
fi - (x==vec[fi])
}
un Autre travaille aussi:
findInterval.rightClosed2 <- function(x, vec, ...) {
length(vec) - findInterval(-x, -rev(vec), ...)
}
Voici un petit test:
x <- c(3, 6, 7, 7, 29, 37, 52)
vec <- c(2, 5, 6, 35)
findInterval(x, vec)
# [1] 1 3 3 3 3 4 4
findInterval.rightClosed(x, vec)
# [1] 1 2 3 3 3 4 4
findInterval.rightClosed2(x, vec)
# [1] 1 2 3 3 3 4 4
mais j'aimerais voir d'autres solutions s'il y a une meilleure un. Par "mieux", je veux dire" plus satisfaisant "ou" ne ressemble pas à un kludge "ou peut-être même"plus efficace". =)
(notez qu'il y a un rightmost.closed argument findInterval(), mais c'est différent - cela se réfère seulement au dernier sous-intervalle et a un sens différent.)
3 réponses
EDIT: nettoyage majeur dans toutes les allées.
Vous pourriez regarder cut. Par défaut, cut rend gauche ouverte et droite des intervalles fermés, et qui peuvent être changés en utilisant l'argument approprié (right). Pour utiliser votre exemple:
x <- c(3, 6, 7, 7, 29, 37, 52)
vec <- c(2, 5, 6, 35)
cutVec <- c(vec, max(x)) # for cut, range of vec should cover all of x
maintenant, créez quatre fonctions qui devraient faire la même chose: deux de L'OP, une de Josh O'Brien, et puis cut. Deux arguments pour cut ont été changés des paramètres par défaut:include.lowest = TRUE va créer un intervalle fermé des deux côtés pour le plus petit (le plus à gauche) intervalle. labels = FALSE causera cut pour retourner simplement les valeurs entières des bins au lieu de créer un facteur, ce qui est le cas.
findInterval.rightClosed <- function(x, vec, ...) {
fi <- findInterval(x, vec, ...)
fi - (x==vec[fi])
}
findInterval.rightClosed2 <- function(x, vec, ...) {
length(vec) - findInterval(-x, -rev(vec), ...)
}
cutFun <- function(x, vec){
cut(x, vec, include.lowest = TRUE, labels = FALSE)
}
# The body of fiFun is a contribution by Josh O'Brien that got fed to the ether.
fiFun <- function(x, vec){
xxFI <- findInterval(x, vec * (1 + .Machine$double.eps))
}
est-ce que toutes les fonctions renvoient le même résultat? Yup. (notez l'utilisation de cutVeccutFun)
mapply(identical, list(findInterval.rightClosed(x, vec)),
list(findInterval.rightClosed2(x, vec), cutFun(x, cutVec), fiFun(x, vec)))
# [1] TRUE TRUE TRUE
maintenant un vecteur plus exigeant à bin:
x <- rpois(2e6, 10)
vec <- c(-Inf, quantile(x, seq(.2, 1, .2)))
tester si identique (noter l'utilisation de unname)
mapply(identical, list(unname(findInterval.rightClosed(x, vec))),
list(findInterval.rightClosed2(x, vec), cutFun(x, vec), fiFun(x, vec)))
# [1] TRUE TRUE TRUE
Et référence:
library(microbenchmark)
microbenchmark(findInterval.rightClosed(x, vec), findInterval.rightClosed2(x, vec),
cutFun(x, vec), fiFun(x, vec), times = 50)
# Unit: milliseconds
# expr min lq median uq max
# 1 cutFun(x, vec) 35.46261 35.63435 35.81233 36.68036 53.52078
# 2 fiFun(x, vec) 51.30158 51.69391 52.24277 53.69253 67.09433
# 3 findInterval.rightClosed(x, vec) 124.57110 133.99315 142.06567 155.68592 176.43291
# 4 findInterval.rightClosed2(x, vec) 79.81685 82.01025 86.20182 95.65368 108.51624
à Partir de ce terme, cut semble être le plus rapide.
peut-être que vous pouvez utiliser l'option gauche.ouvert:
findInterval(x, vec, left.open=T)
[1] 1 2 3 3 3 4 4
si vos limites sont des intervalles, vous pouvez tout simplement augmenter un peu l'intervalle de droite: intervalle+c(0,0.1) ferait: findinterval(valeur, Intervalle+c(0,0.1))--1-->