2012-06-26 10 views
18

R tiene una semántica de paso por valor, que minimiza los efectos secundarios accidentales (algo bueno). Sin embargo, cuando el código está organizado en muchas funciones/métodos para reusabilidad/legibilidad/mantenibilidad y cuando ese código necesita manipular estructuras de datos grandes a través de, por ejemplo, marcos de datos grandes, a través de una serie de transformaciones/operaciones, los hilos semánticos pasan por valor a una gran cantidad de copia de datos en todo y mucha agitación de montón (algo malo). Por ejemplo, un marco de datos que toma 50Mb en el montón pasado como parámetro de función se copiará como mínimo la misma cantidad de veces que la profundidad de la llamada a la función y el tamaño del montón en la parte inferior de la pila de llamadas será N * 50Mb. Si las funciones devuelven una trama de datos transformada/modificada desde lo profundo de la cadena de llamada, entonces la copia sube por otra N.R: Al pasar un marco de datos por referencia

La pregunta What is the best way to avoid passing a data frame around? de SO toca este tema pero está redactada de una manera que evita preguntar directamente el pase -pregunta de referencia y la respuesta ganadora básicamente dice: "sí, pase-por-valor es cómo funciona R". Eso no es realmente 100% exacto. Los entornos R permiten la semántica de paso a paso y los marcos OO como proto usan esta capacidad de forma extensiva. Por ejemplo, cuando se pasa un objeto proto como un argumento de función, mientras que su "envoltorio mágico" se pasa por valor, para el desarrollador R la semántica se pasa por referencia.

Parece que pasar un gran marco de datos por referencia sería un problema común y me pregunto cómo se han acercado otros y si hay bibliotecas que lo permitan. En mi búsqueda, no he descubierto uno.

Si no hay nada disponible, mi enfoque sería crear un objeto proto que envuelva un marco de datos. Agradecería sugerencias sobre el azúcar sintáctico que debería agregarse a este objeto para que sea útil, por ejemplo, sobrecargar los operadores $ y [[,] así como cualquier combinación que debería tener en cuenta. No soy un experto en R

Puntos de bonificación para una solución de paso a paso de tipo agnóstico que se integra muy bien con R, aunque mis necesidades son exclusivamente con marcos de datos.

+4

No creo que la premisa en su pregunta sea correcta. R solo copia al cambiar, por lo que puede pasar argumentos por la pila de llamadas sin hacer nuevas copias, siempre y cuando no cambie el objeto.Trataré de encontrar algunas referencias sobre esto en un minuto. – Andrie

+0

Vea por ejemplo esta pregunta y su respuesta por @matthewdowle: http://stackoverflow.com/q/10225098/602276 – Andrie

+2

Andrie tiene razón. Sorprendido de que no haya encontrado ['data.table'] (http://datatable.r-forge.r-project.org/LondonR_2012.pdf) en sus búsquedas de' data.frame' grande. ¿Qué buscabas? –

Respuesta

26

La premisa de la pregunta es (en parte) incorrecta. R funciona como aprobado y se repiten las copias de la forma en que se describen solo cuando se realizan más asignaciones y alteraciones en el marco de datos a medida que se transmite la promesa. Por lo tanto, el número de copias no será N *, donde N es la profundidad de la pila, sino que N es el número de niveles donde se realizan las asignaciones. Sin embargo, tiene razón en que los entornos pueden ser útiles. Veo al seguir el enlace que ya has encontrado el paquete 'proto'. También hay una introducción relativamente reciente de una "clase de referencia" a veces denominada "R5" donde R/S3 era el sistema de clase original de S3 que se copia en R y R4 sería el sistema de clase más reciente que parece apoyar en su mayoría el desarrollo del paquete BioConductor.

Aquí hay un enlace a un ejemplo de Steve Lianoglou (en una línea de discusión sobre el fondo de clases de referencia) de la incrustación de un entorno dentro de un objeto S4 para evitar los gastos de copia:

https://stat.ethz.ch/pipermail/r-help/2011-September/289987.html

Mateo Dowle de El paquete 'data.table' crea una nueva clase de objeto de datos cuya semántica de acceso usando el "[" son diferentes a las de los data.frames R normales, y que realmente funciona como pass-by-reference. Tiene una velocidad superior de acceso y procesamiento. También puede recurrir a la semántica del marco de datos, ya que en los últimos años tales objetos ahora heredan la clase 'data.frame'.

También es posible que desee investigar Hesterberg's dataframe package.

+1

+1 Me complace que amplíe y mejore esta respuesta. – Andrie

+1

Y +1 para el enlace al paquete de marco de datos, que ahora se incorpora (o al menos en filosofía) a R 2.15-1 – Andrie

+1

@DWin, gracias por la información. Pass-by-promise tiene sentido como una optimización, aunque no ayuda en mi caso donde varios pasos operan en el mismo marco de datos para pasar de "raw" a procesable. Por lo general, las modificaciones se llevan a cabo en pasos separados de una canalización de procesamiento, pero en algunos casos se realizan en la misma cadena de llamadas que se cruzan los límites de abstracción con invariantes diferentes. Veré los paquetes que recomiendas. – Sim

Cuestiones relacionadas