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 cutVec
cutFun
)
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-->