2012-02-29 20 views
11

Tengo un gran marco de datos que toma alrededor de 900 MB de memoria RAM. Luego trató de modificar de esta manera:Sin memoria cuando se modifica un gran R data.frame

dataframe[[17]][37544]=0 

Parece que hace R utilizando más de RAM 3G y R se queja: (. Estoy en una máquina de 32 bits) "Error No se puede asignar el vector de tamaño de 3.0 Mb",

he encontrado de esta manera es mejor:

dataframe[37544, 17]=0 

pero la huella del R todavía se duplicó y el comando lleva bastante tiempo para funcionar.

De un fondo de C/C++, estoy realmente confundido acerca de este comportamiento. Pensé que algo como dataframe[37544, 17]=0 debería completarse en un abrir y cerrar de ojos sin que costara ninguna memoria extra (solo se debería modificar una celda). ¿Qué está haciendo R para esos comandos que publiqué? ¿Cuál es la forma correcta de modificar algunos elementos en un marco de datos sin duplicar la huella de memoria?

¡Muchas gracias por su ayuda!

Tao

+3

(Base) R es famoso por su espectacular manejo de grandes estructuras de datos. Deberá buscar una combinación de los paquetes ** ff **, ** bigmemory ** y ** data.table **. – joran

+3

Eso no es realmente cierto: los data.frames son famosos por ser ineficientes, pero existen estructuras muy eficientes en (base) R que deberías usar en cambio si te preocupas por la eficiencia. –

+0

@SimonUrbanek Sí, lo expresé muy mal. Simplemente quise decir exactamente lo que dijiste, que los marcos de datos tienden a ser ineficientes, y que los paquetes que mencioné a menudo pueden ser útiles para las personas que manejan grandes cantidades de datos. – joran

Respuesta

8

Busque 'copia en escritura' en el contexto de los debates R relacionadas con la memoria. Tan pronto como una parte de una estructura de datos (potencialmente muy grande) cambia, se realiza una copia.

Una regla útil es que si su objeto más grande es N MB/GB/... grande, se necesitan alrededor de 3 * N de RAM. Tal es la vida con un sistema interpretado.

Hace años, cuando tuve que manejar grandes cantidades de datos en máquinas con (relativo al volumen de datos) máquinas de 32 bits de baja velocidad, obtuve un buen uso de las primeras versiones del paquete bigmemory. Utiliza la interfaz del "puntero externo" para mantener grandes cantidades de memoria fuera de R. Eso le ahorra no solo el factor "3x", sino posiblemente más ya que puede salirse con la memoria no contigua (que es la otra cosa que le gusta a R)

+0

¡Muchas gracias! Exploré varias opciones mencionadas en las respuestas. Descubrí que bigmemory es bastante fácil para ti y suficiente para mí. – agmao

+7

@agmao O puede intentar ': =' en 'data.table' que hace exactamente lo que quiere. –

7

Las tramas de datos son los peores estructura se puede optar por hacer modificaciones a. Debido al manejo bastante complejo de todas las funciones (como mantener sincronizados los nombres de fila, concordancia parcial, etc.) que se realiza en código R puro (a diferencia de la mayoría de los otros objetos que pueden ir directamente a C) tienden a forzar copias adicionales como no puedes editarlos en su lugar. Verifique R-devel en las discusiones detalladas sobre esto; se ha discutido extensamente varias veces.

La regla práctica es nunca utilizar tramas de datos de datos de gran tamaño, a menos que se les trata de sólo lectura. Serás órdenes de magnitud más eficientes si trabajas en vectores o matrices.

4

Hay un tipo de objeto llamado ffdf en el paquete ff que es básicamente un data.frame almacenado en el disco. Además de los otros consejos anteriores, puede intentarlo.

También puede probar el paquete RSQLite.

12

seguimiento a Joran sugiriendo data.table, aquí hay algunos enlaces. Su objeto, a 900 MB, es manejable en RAM incluso en 32 bits R, sin copias.

When should I use the := operator in data.table?

Why has data.table defined := rather than overloading <-?

También, data.table v1.8.0 (todavía no en CRAN pero estable en R-Forge) tiene una función set() que proporciona asignación aún más rápido a los elementos, tan rápido como la asignación a matrix (apropiado para el uso dentro de los bucles, por ejemplo). Ver latest NEWS para más detalles y ejemplos. También vea ?":=" que está vinculado desde ?data.table.

Y, aquí está 12 questions en Stack Overflow con la etiqueta data.table que contiene la palabra "referencia".

Para completar:

require(data.table) 
DT = as.data.table(dataframe) 
# say column name 17 is 'Q' (i.e. LETTERS[17]) 
# then any of the following : 

DT[37544, Q:=0]    # using column name (often preferred) 

DT[37544, 17:=0, with=FALSE] # using column number 

col = "Q" 
DT[37544, col:=0, with=FALSE] # variable holding name 

col = 17 
DT[37544, col:=0, with=FALSE] # variable holding number 

set(DT,37544L,17L,0)   # using set(i,j,value) in v1.8.0 
set(DT,37544L,"Q",0) 

Pero, por favor, vea las preguntas vinculadas y documentación del paquete para ver cómo := es más general que este sencillo ejemplo; por ejemplo, combinando := con búsqueda binaria en una unión i.

Cuestiones relacionadas