readdlm read dataframes julia-lang

julia lang - read - leer csv en Julia es lento comparado con Python



read csv julia (5)

En mi experiencia, la mejor manera de tratar con archivos de texto más grandes no es cargarlos en Julia, sino transmitirlos. Este método tiene algunos costos fijos adicionales, pero generalmente se ejecuta extremadamente rápido. Algún pseudo código es este:

function streamdat() mycsv=open("/path/to/text.csv", "r") # <-- opens a path to your text file sumvec = [0.0] # <-- store a sum here i = 1 while(!eof(mycsv)) # <-- loop through each line of the file row = readline(mycsv) vector=split(row, "|") # <-- split each line by | sumvec+=parse(Float64, vector[i]) i+=1 end end streamdat()

El código anterior es solo una suma simple, pero esta lógica se puede expandir a problemas más complejos.

La lectura de grandes archivos de texto / csv en Julia lleva mucho tiempo en comparación con Python. Estos son los tiempos para leer un archivo cuyo tamaño es 486.6 MB y tiene 153895 filas y 644 columnas.

Python 3.3 ejemplo

import pandas as pd import time start=time.time() myData=pd.read_csv("C://myFile.txt",sep="|",header=None,low_memory=False) print(time.time()-start) Output: 19.90

R 3.0.2 ejemplo

system.time(myData<-read.delim("C:/myFile.txt",sep="|",header=F, stringsAsFactors=F,na.strings="")) Output: User System Elapsed 181.13 1.07 182.32

Ejemplo de Julia 0.2.0 (Julia Studio 0.4.4) # 1

using DataFrames timing = @time myData = readtable("C:/myFile.txt",separator=''|'',header=false) Output: elapsed time: 80.35 seconds (10319624244 bytes allocated)

Ejemplo de Julia 0.2.0 (Julia Studio 0.4.4) # 2

timing = @time myData = readdlm("C:/myFile.txt",''|'',header=false) Output: elapsed time: 65.96 seconds (9087413564 bytes allocated)

  1. Julia es más rápida que R, pero bastante lenta en comparación con Python. ¿Qué puedo hacer de manera diferente para acelerar la lectura de un archivo de texto grande?

  2. un problema aparte es que el tamaño en la memoria es 18 x el tamaño del archivo del disco duro en Julia, pero solo 2.5 x el tamaño de python. en Matlab, que me parece que es más eficiente en memoria para archivos grandes, es 2 veces el tamaño del archivo de disco duro. ¿Alguna razón en particular para el gran tamaño de archivo en la memoria en Julia?


Hay un paquete de julia relativamente nuevo llamado CSV.jl por Jacob Quinn que proporciona un analizador CSV mucho más rápido, en muchos casos a la par con pandas: https://github.com/JuliaData/CSV.jl


He encontrado algunas cosas que pueden ayudar parcialmente a esta situación.

  1. el uso de la función readdlm() en Julia parece funcionar considerablemente más rápido (por ejemplo, 3 veces en una prueba reciente) que readtable() . Por supuesto, si desea el tipo de objeto DataFrame, tendrá que convertirlo, lo que puede acabar con la mayor parte o la mejora de la velocidad.

  2. Especificar las dimensiones de su archivo puede hacer una GRAN diferencia, tanto en la velocidad como en las asignaciones de memoria. Ejecuté esta prueba de lectura en un archivo que tiene 258.7 MB en el disco:

    julia> @time Data = readdlm("MyFile.txt", ''/t'', Float32, skipstart = 1); 19.072266 seconds (221.60 M allocations: 6.573 GB, 3.34% gc time) julia> @time Data = readdlm("MyFile.txt", ''/t'', Float32, skipstart = 1, dims = (File_Lengths[1], 62)); 10.309866 seconds (87 allocations: 528.331 MB, 0.03% gc time)

  3. La especificación de tipo para su objeto importa mucho. Por ejemplo, si sus datos tienen cadenas, entonces los datos de la matriz que leyó serán de tipo Any, lo que es costoso en cuanto a memoria. Si la memoria es realmente un problema, es posible que desee considerar el preprocesamiento de sus datos convirtiendo primero las cadenas en números enteros, haciendo sus cálculos y luego volviendo a convertir. Además, si no necesita una tonelada de precisión, usar el tipo Float32 en lugar de Float64 puede ahorrar MUCHO espacio. Puede especificar esto al leer el archivo, por ejemplo:

    Data = readdlm("file.csv", '','', Float32)

  4. Con respecto al uso de la memoria, he encontrado en particular que el tipo PooledDataArray (del paquete DataArrays) puede ser útil para reducir el uso de la memoria si sus datos tienen muchos valores repetidos. El tiempo para convertir a este tipo es relativamente grande, por lo que no es un ahorro de tiempo en sí mismo, pero al menos ayuda a reducir un poco el uso de la memoria. Por ejemplo, al cargar un conjunto de datos con 19 millones de filas y 36 columnas, 8 de las cuales representaban variables categóricas para el análisis estadístico, esto redujo la asignación de memoria del objeto de 5 veces su tamaño en el disco a 4 veces su tamaño. Si hay aún más valores repetidos, la reducción de la memoria puede ser aún más significativa (he tenido situaciones en las que PooledDataArray reduce la asignación de memoria a la mitad).

  5. A veces también puede ayudar a ejecutar la función gc() (recolector de basura) después de cargar y formatear los datos para borrar cualquier asignación de ram innecesaria, aunque en general Julia lo hará automáticamente bastante bien.

Sin embargo, a pesar de todo esto, estaré esperando nuevos desarrollos en Julia para permitir una carga más rápida y un uso más eficiente de la memoria para grandes conjuntos de datos.


La mejor respuesta es probablemente que no soy tan buen programador como Wes.

En general, el código en DataFrames está mucho menos optimizado que el código en Pandas. Confío en que podamos ponernos al día, pero tomará algo de tiempo, ya que primero necesitamos implementar una gran cantidad de funciones básicas. Como en Julia hay que construir muchas cosas, tiendo a centrarme en hacer las cosas en tres partes: (1) construir cualquier versión, (2) construir una versión correcta, (3) construir una versión rápida y correcta. Para el trabajo que hago, Julia a menudo no ofrece ninguna versión de funcionalidad esencial, por lo que mi trabajo se centra en (1) y (2). A medida que se construyan más herramientas, será más fácil centrarse en el rendimiento.

En cuanto al uso de la memoria, creo que la respuesta es que usamos un conjunto de estructuras de datos cuando analizamos datos tabulares que son mucho menos eficientes que los utilizados por Pandas. Si conociera mejor los aspectos internos de Pandas, podría enumerar los lugares donde somos menos eficientes, pero por ahora solo especularé que una falla obvia es que estamos leyendo todo el conjunto de datos en la memoria en lugar de extraer fragmentos del disco. . Esto ciertamente se puede evitar y hay problemas abiertos para hacerlo. Es solo cuestión de tiempo.

En esa nota, el código readtable es bastante fácil de leer. La forma más segura de obtener una readtable más rápida es sacar el perfilador de Julia y comenzar a corregir las fallas de rendimiento que descubre.


Tenga en cuenta que la salida de "n bytes asignados" de @time es el tamaño total de todos los objetos asignados, ignorando cuántos de ellos podrían haberse liberado. Este número suele ser mucho más alto que el tamaño final de los objetos vivos en la memoria. No sé si esto es en lo que se basa su estimación de tamaño de memoria, pero quería señalar esto.