una sucesiones sucesion que oscilantes monotonas monotona funcion ejemplos divergentes demostrar decrecientes crecientes convergentes como acotadas acotada r vector

r - que - sucesiones monotonas y acotadas



¿Cómo verificar si una secuencia de números es monótonamente creciente(o decreciente)? (5)

Otro: verifique si

all(x == cummax(x))

o

all(x == cummin(x))

para aumentar o disminuir monótonamente, respectivamente. Parece que cummax es mucho más rápido que diff y también usa menos memoria:

> x <- seq_len(1e7) > system.time(all(x == cummax(x))) user system elapsed 0.11 0.00 0.11 > system.time(all(diff(x) >= 0)) user system elapsed 0.47 0.13 0.59 > x <- seq_len(1e8) > system.time(all(x == cummax(x))) user system elapsed 1.06 0.09 1.16 > system.time(all(diff(x) >= 0)) Error: cannot allocate vector of size 381.5 Mb In addition: Warning messages: 1: Reached total allocation of 1535Mb: see help(memory.size) 2: Reached total allocation of 1535Mb: see help(memory.size) 3: Reached total allocation of 1535Mb: see help(memory.size) 4: Reached total allocation of 1535Mb: see help(memory.size) Timing stopped at: 1.96 0.38 2.33

Mi apuesta sobre por qué cummax es más rápido que diff es porque solo tiene que comparar números, que es más rápido que tener que calcular diferencias.

Editar : a petición de (Ali), pruebas adicionales que incluyan su respuesta (tenga en cuenta que ahora estoy ejecutando desde una máquina diferente, por lo que los siguientes resultados no se deben comparar con los anteriores)

> x <- seq_len(1e7) > system.time(x == cummax(x)) user system elapsed 0.316 0.096 0.416 > system.time(all(diff(x) >= 0)) user system elapsed 4.364 0.240 4.632 > system.time(x[-1] - x[-length(x)] >= 0) user system elapsed 3.828 0.380 4.227 > system.time(all(x[-1] >= x[-length(x)])) user system elapsed 2.572 0.288 2.865

Se nos da una secuencia de números, como un vector foo . La tarea es encontrar que foo está aumentando monótonamente - cada elemento es menor o igual que el siguiente - o disminuyendo monótonamente - cada elemento mayor o igual que el siguiente.

Seguro que esto se puede encontrar a través de un bucle, pero ¿hay más ideas creativas?


Para la versión en aumento, puede usar is.unsorted() :

x <- seq_len(1e7) !is.unsorted(x) > !is.unsorted(x) [1] TRUE

Esto es bastante rápido también:

> system.time(!is.unsorted(x)) user system elapsed 0.099 0.000 0.099 > system.time(all(x == cummax(x))) user system elapsed 0.320 0.039 0.360

Desafortunadamente is.unsorted() es explícitamente para aumentar el orden. Nos llevamos un poco de golpe convirtiendo esto a una situación decreciente, pero sigue siendo competitivo con las otras opciones en mi sistema:

xx <- 1e7:1 !is.unsorted(-xx) system.time(!is.unsorted(-xx)) > system.time(!is.unsorted(-xx)) user system elapsed 0.205 0.020 0.226 > system.time(all(xx == cummin(xx))) user system elapsed 0.356 0.088 0.444

Y en un problema más grande ...

x <- 1:1e8 xx <- 1e8:1 system.time(!is.unsorted(x)) system.time(all(x == cummax(x))) system.time(!is.unsorted(-xx)) system.time(all(xx == cummin(xx))) > system.time(!is.unsorted(x)) user system elapsed 1.019 0.000 1.019 > system.time(all(x == cummax(x))) user system elapsed 3.255 0.354 3.608 > system.time(!is.unsorted(-xx)) user system elapsed 2.089 0.561 2.650 > system.time(all(xx == cummin(xx))) user system elapsed 3.318 0.395 3.713

Si desea forzar una secuencia estrictamente creciente, entonces vea strictly in ?is.unsorted .


Una opción es emplear la función diff() para dar las diferencias entre elementos adyacentes en un vector.

Una función monótonamente creciente tendrá diff(x) todo> o igual a 0:

f1 <- 1:10 f2 <- 10:1 > all(diff(f1) >= 0) [1] TRUE > all(diff(f2) >= 0) [1] FALSE

Aunque probar la igualdad a 0 puede ser mal visto; mejor podría ser utilizar < 0 y negar la comparación a través de ! :

> all(!diff(f1) < 0) [1] TRUE > all(!diff(f2) < 0) [1] FALSE

La razón de esto es que estás usando una computadora en la que no todos los números se pueden representar exactamente. Puede calcular un resultado que sea efectivamente cero pero no exactamente cero porque los números en el cálculo no se pudieron representar exactamente (es decir, puntos flotantes ). Entonces, si foo es el resultado de un cálculo, probar si es igual a 0 podría ser algo que debería ser 0 un poco mayor que o menor que 0, que luego puede dar el resultado incorrecto para una función creciente / decreciente.


Una respuesta interesante es la siguiente:

foo = c(1, 3, 7, 10, 15) all(foo[-1] - foo[-length(foo)] >= 0) # TRUE foo[3] = 20 all(foo[-1] - foo[-length(foo)] >= 0) # FALSE


all(diff(x)<0) (sustituto > , <= , >= según corresponda)