Numpy carga csv demasiado lento en comparación con Matlab

Publiqué esta pregunta porque me preguntaba si hice algo terriblemente mal para obtener este resultado.

Tengo un archivo csv de tamaño mediano y traté de usar numpy para cargarlo. Para ilustrar, hice el archivo usando python:

import timeit import numpy as np my_data = np.random.rand(1500000, 3)*10 np.savetxt('./test.csv', my_data, delimiter=',', fmt='%.2f') 

Y luego, probé dos métodos: numpy.genfromtxt, numpy.loadtxt

 setup_stmt = 'import numpy as np' stmt1 = """\ my_data = np.genfromtxt('./test.csv', delimiter=',') """ stmt2 = """\ my_data = np.loadtxt('./test.csv', delimiter=',') """ t1 = timeit.timeit(stmt=stmt1, setup=setup_stmt, number=3) t2 = timeit.timeit(stmt=stmt2, setup=setup_stmt, number=3) 

Y el resultado muestra que t1 = 32.159652940464184, t2 = 52.00093725634724 .
Sin embargo, cuando intenté usar matlab:

 tic for i = 1:3 my_data = dlmread('./test.csv'); end toc 

El resultado muestra: El tiempo transcurrido es 3.196465 segundos .

Entiendo que puede haber algunas diferencias en la velocidad de carga, pero:

  1. Esto es mucho más de lo que esperaba;
  2. ¿No es que np.loadtxt debería ser más rápido que np.genfromtxt?
  3. No he probado el módulo csv de Python porque cargar archivos csv es algo muy frecuente que hago y con el módulo csv, la encoding es un poco detallada … Pero me encantaría probarlo si esa es la única manera . Actualmente me preocupa más si soy yo haciendo algo mal.

Cualquier entrada sería apreciada. ¡Muchas gracias por adelantado!

Sí, la lectura de archivos csv en numpy es bastante lenta. Hay una gran cantidad de Python puro a lo largo de la ruta del código. En estos días, incluso cuando estoy usando numpy puros, todavía uso pandas para IO:

 >>> import numpy as np, pandas as pd >>> %time d = np.genfromtxt("./test.csv", delimiter=",") CPU times: user 14.5 s, sys: 396 ms, total: 14.9 s Wall time: 14.9 s >>> %time d = np.loadtxt("./test.csv", delimiter=",") CPU times: user 25.7 s, sys: 28 ms, total: 25.8 s Wall time: 25.8 s >>> %time d = pd.read_csv("./test.csv", delimiter=",").values CPU times: user 740 ms, sys: 36 ms, total: 776 ms Wall time: 780 ms 

Alternativamente, en un caso tan simple como este, podrías usar algo como lo que Joe Kington escribió aquí :

 >>> %time data = iter_loadtxt("test.csv") CPU times: user 2.84 s, sys: 24 ms, total: 2.86 s Wall time: 2.86 s 

También está la biblioteca de lectores de texto de Warren Weckesser, en caso de que los pandas sean una dependencia demasiado pesada:

 >>> import textreader >>> %time d = textreader.readrows("test.csv", float, ",") readrows: numrows = 1500000 CPU times: user 1.3 s, sys: 40 ms, total: 1.34 s Wall time: 1.34 s 

Si solo desea guardar y leer una matriz numpy, es mucho mejor guardarlo como binario o binario comprimido según el tamaño:

 my_data = np.random.rand(1500000, 3)*10 np.savetxt('./test.csv', my_data, delimiter=',', fmt='%.2f') np.save('./testy', my_data) np.savez('./testz', my_data) del my_data setup_stmt = 'import numpy as np' stmt1 = """\ my_data = np.genfromtxt('./test.csv', delimiter=',') """ stmt2 = """\ my_data = np.load('./testy.npy') """ stmt3 = """\ my_data = np.load('./testz.npz')['arr_0'] """ t1 = timeit.timeit(stmt=stmt1, setup=setup_stmt, number=3) t2 = timeit.timeit(stmt=stmt2, setup=setup_stmt, number=3) t3 = timeit.timeit(stmt=stmt3, setup=setup_stmt, number=3) genfromtxt 39.717250824 save 0.0667860507965 savez 0.268463134766 

Quizás es mejor instalar un código c simple que convierte los datos a binarios y hacer que ‘numpy’ lea el archivo binario. Tengo un archivo CSV de 20 GB para leer, ya que los datos CSV son una mezcla de int, double, str. La lectura de conjuntos de estructuras con bultos lleva más de una hora, mientras que el volcado a binario tomó aproximadamente 2 minutos y la carga a numpy toma menos de 2 segundos.

Mi código específico, por ejemplo, está disponible aquí .

FWIW el módulo csv incorporado funciona muy bien y realmente no es tan detallado.

modulo csv:

 %%timeit with open('test.csv', 'r') as f: np.array([l for l in csv.reader(f)]) 1 loop, best of 3: 1.62 s per loop 

np.loadtext :

 %timeit np.loadtxt('test.csv', delimiter=',') 1 loop, best of 3: 16.6 s per loop 

pd.read_csv :

 %timeit pd.read_csv('test.csv', header=None).values 1 loop, best of 3: 663 ms per loop 

Personalmente, me gusta usar pandas read_csv pero el módulo csv es bueno cuando estoy usando números puros.