2010-05-06 4 views
10

Estoy implementando un algoritmo que implica muchas sumas y eliminaciones de conjuntos. En R, esto es lento porque, hasta donde yo sé, agregar o quitar cosas de un vector es lento, ya que todo el vector debe ser reasignado. ¿Hay alguna forma de hacerlo de manera más eficiente?Agregando o eliminando elementos de manera eficiente a un vector o lista en R?

Editar: Mi solución actual es utilizar un vector booleano de la misma longitud que la lista de cosas que pueden estar en el set, y el uso que, como una tabla de miembros.

+1

¿Hay alguna posibilidad de que usted proporciona código exacto? De su pregunta, no puedo averiguar si está usando listas o vectores, cómo agrega o elimina (¿qué función?) Elementos, cómo funciona su solución actual (¿está recreando el vector lógico en lugar de agregar/eliminar al original?)? Más información que proporciona, se puede hacer más optimización. – Marek

+0

nueva versión de R debería ser mejor en esto. ¿Es eso cierto? – userJT

+0

Dudo que volver a clasificar según el tamaño un vector repetidamente mientras que los elementos se agregan o se quitan de él sea alguna vez rápido. –

Respuesta

12

Capítulo 2 de The R Inferno tiene algunos comentarios interesantes sobre esto, incluyendo objetos que crecen perdiodic para re duce la fragmentación de memoria y la sobrecarga de asignación.

Si sabe cuál es el tamaño final del conjunto, entonces el método que sugiere es probablemente el mejor, es decir, subset de todo el universo utilizando un vector de membresía adecuado. Difícil saber cuál es el mejor sin ver exactamente lo que estás tratando de hacer.

+0

+1 para hacer referencia a The R Inferno – Stedy

+0

Terminé con un vector booleano que representa membresía establecida. –

+0

podría actualizar el enlace?'404 No encontrado' – Shreyans

11

Si puede, inicializar un vector de modo que tenga una longitud igual a la longitud máxima durante el algoritmo puede ayudar.

p. Ej.

vec <- rep(NA,10) 
vec[1:3] <- 1:3 
vec[4:5] <- 4:5 
vec[6:10] <- 6:10 

en lugar de

vec <- 1:3 
vec <- c(vec,4:5) 
vec <- c(vec,6:10) 

comparar

> system.time({vec <- rep(NA,10^4); for (i in 1:(10^4)) vec[i] <- i }) 
    user system elapsed 
    0.043 0.001 0.044 

a

> system.time({vec <- NULL; for (i in 1:(10^4)) vec <- c(vec,i) }) 
    user system elapsed 
    0.249 0.089 0.335 
+0

Pero posiblemente podría estar eliminando cualquier elemento en el vector, no solo el último. –

+1

Claro. Los bucles son solo ejemplos para mostrar la diferencia entre inicializar un vector y construir uno con una asignación repetida. Obviamente no he visto tu algoritmo, pero este método aún debería funcionar, ya que 'i' podría ser cualquier número en cualquier punto de tu algoritmo. Para empezar, solo se necesita conocer la longitud de tu vector. Además, en lugar de eliminarlo, simplemente asignaría ese elemento como 'NA' y mantendría un vector de la misma longitud. – wkmor1

+0

No necesita usar 'eval/parse', es suficiente cuando toma la expresión entre llaves, es decir:' system.time ({vec <- rep (NA, 10^4); for (i en 1 :(10^4)) vec [i] <- i}) ' – Marek

3

Es difícil decir lo que quiere. Tal vez realmente quieres comandos de pila como push y pop. El siguiente no es eso. Pero es una solución rápida.

Asigne un vector lo suficientemente grande como para contener todos sus elementos del tipo que necesita. Establezca cada valor en NA. Agregar elementos es simple. Quitar elementos es volver a establecerlos en NA. Utilizando el vector se acaba na.omit(myVec)

myVec <- numeric (maxLength) # a vector of maximum length 

is.na(myVec) <- 1:maxLength # set every item in myVec to NA 

myVec[c(2,6,20)] <- 5   # add some values 

na.omit(myVec) 

#This will also work if you can initialize all of your values to something that you know you won't need. 
+0

Una pila R: http://rosettacode.org/wiki/Stack#R –

+1

@John: 'myVec <- rep (NA, maxLength)' reemplaza las dos primeras líneas más limpiamente. Además, ¿qué pasa con la gran escritura? –

Cuestiones relacionadas