Estoy buscando la biblioteca de Python más rápida para leer un archivo CSV (si eso importa, 1 o 3 columnas, todos los números enteros o flotantes, ejemplo ) en una matriz de Python (o algún objeto al que pueda acceder de manera similar, con un similar tiempo de acceso). Debería ser gratuito, funcionar en Windows 7 y Ubuntu 12.04, y con Python 2.7 x64.
CSV con 1 columna:
350
750
252
138
125
125
125
112
95
196
105
101
101
101
102
101
101
102
202
104
CSV con 3 columnas:
9,52,1
52,91,0
91,135,0
135,174,0
174,218,0
218,260,0
260,301,0
301,341,0
341,383,0
383,423,0
423,466,0
466,503,0
503,547,0
547,583,0
583,629,0
629,667,0
667,713,0
713,754,0
754,796,0
796,839,1
Así que eventualmente escribí un pequeño punto de referencia usando las bibliotecas que Steve Barnes había señalado. Encontré lo mismo al buscarlo mientras escribía la pregunta, así que supongo que esos son los principales. Algunas otras ideas que aún no se han probado: HDF5 para Python , PyTables , IOPro (no gratuito).
En resumen, pandas.io.parsers.read_csv
supera a todos los demás, NumPy loadtxt
es impresionantemente lento y NumPy es from_file
impresionantemente load
rápido.
Datos (debería haberlos generado en el punto de referencia, pero ahora mismo me estoy quedando sin tiempo)
Código:
import csv
import os
import cProfile
import time
import numpy
import pandas
import warnings
# Make sure those files in the same folder as benchmark_python.py
# As the name indicates:
# - '1col.csv' is a CSV file with 1 column
# - '3col.csv' is a CSV file with 3 column
filename1 = '1col.csv'
filename3 = '3col.csv'
csv_delimiter = ' '
debug = False
def open_with_python_csv(filename):
'''
https://docs.python.org/2/library/csv.html
'''
data =[]
with open(filename, 'rb') as csvfile:
csvreader = csv.reader(csvfile, delimiter=csv_delimiter, quotechar='|')
for row in csvreader:
data.append(row)
return data
def open_with_python_csv_cast_as_float(filename):
'''
https://docs.python.org/2/library/csv.html
'''
data =[]
with open(filename, 'rb') as csvfile:
csvreader = csv.reader(csvfile, delimiter=csv_delimiter, quotechar='|')
for row in csvreader:
data.append(map(float, row))
return data
def open_with_python_csv_list(filename):
'''
https://docs.python.org/2/library/csv.html
'''
data =[]
with open(filename, 'rb') as csvfile:
csvreader = csv.reader(csvfile, delimiter=csv_delimiter, quotechar='|')
data = list(csvreader)
return data
def open_with_numpy_loadtxt(filename):
'''
http://stackoverflow.com/questions/4315506/load-csv-into-2d-matrix-with-numpy-for-plotting
'''
data = numpy.loadtxt(open(filename,'rb'),delimiter=csv_delimiter,skiprows=0)
return data
def open_with_pandas_read_csv(filename):
df = pandas.read_csv(filename, sep=csv_delimiter)
data = df.values
return data
def benchmark(function_name):
start_time = time.clock()
data = function_name(filename1)
if debug: print data[0]
data = function_name(filename3)
if debug: print data[0]
print function_name.__name__ + ': ' + str(time.clock() - start_time), "seconds"
def benchmark_numpy_fromfile():
'''
http://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfile.html
Do not rely on the combination of tofile and fromfile for data storage,
as the binary files generated are are not platform independent.
In particular, no byte-order or data-type information is saved.
Data can be stored in the platform independent .npy format using
save and load instead.
Note that fromfile will create a one-dimensional array containing your data,
so you might need to reshape it afterward.
'''
#ignore the 'tmpnam is a potential security risk to your program' warning
with warnings.catch_warnings():
warnings.simplefilter('ignore', RuntimeWarning)
fname1 = os.tmpnam()
fname3 = os.tmpnam()
data = open_with_numpy_loadtxt(filename1)
if debug: print data[0]
data.tofile(fname1)
data = open_with_numpy_loadtxt(filename3)
if debug: print data[0]
data.tofile(fname3)
if debug: print data.shape
fname3shape = data.shape
start_time = time.clock()
data = numpy.fromfile(fname1, dtype=numpy.float64) # you might need to switch to float32. List of types: http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html
if debug: print len(data), data[0], data.shape
data = numpy.fromfile(fname3, dtype=numpy.float64)
data = data.reshape(fname3shape)
if debug: print len(data), data[0], data.shape
print 'Numpy fromfile: ' + str(time.clock() - start_time), "seconds"
def benchmark_numpy_save_load():
'''
http://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfile.html
Do not rely on the combination of tofile and fromfile for data storage,
as the binary files generated are are not platform independent.
In particular, no byte-order or data-type information is saved.
Data can be stored in the platform independent .npy format using
save and load instead.
Note that fromfile will create a one-dimensional array containing your data,
so you might need to reshape it afterward.
'''
#ignore the 'tmpnam is a potential security risk to your program' warning
with warnings.catch_warnings():
warnings.simplefilter('ignore', RuntimeWarning)
fname1 = os.tmpnam()
fname3 = os.tmpnam()
data = open_with_numpy_loadtxt(filename1)
if debug: print data[0]
numpy.save(fname1, data)
data = open_with_numpy_loadtxt(filename3)
if debug: print data[0]
numpy.save(fname3, data)
if debug: print data.shape
fname3shape = data.shape
start_time = time.clock()
data = numpy.load(fname1 + '.npy')
if debug: print len(data), data[0], data.shape
data = numpy.load(fname3 + '.npy')
#data = data.reshape(fname3shape)
if debug: print len(data), data[0], data.shape
print 'Numpy load: ' + str(time.clock() - start_time), "seconds"
def main():
number_of_runs = 20
results = []
benchmark_functions = ['benchmark(open_with_python_csv)',
'benchmark(open_with_python_csv_list)',
'benchmark(open_with_python_csv_cast_as_float)',
'benchmark(open_with_numpy_loadtxt)',
'benchmark(open_with_pandas_read_csv)',
'benchmark_numpy_fromfile()',
'benchmark_numpy_save_load()']
# Compute benchmark
for run_number in range(number_of_runs):
run_results = []
for benchmark_function in benchmark_functions:
run_results.append(eval(benchmark_function))
results.append(run_results)
# Display benchmark's results
print results
results = numpy.array(results)
numpy.set_printoptions(precision=10) # http://stackoverflow.com/questions/2891790/pretty-printing-of-numpy-array
numpy.set_printoptions(suppress=True) # suppress suppresses the use of scientific notation for small numbers:
print numpy.mean(results, axis=0)
print numpy.std(results, axis=0)
#Another library, but not free: https://store.continuum.io/cshop/iopro/
if __name__ == "__main__":
#cProfile.run('main()') # if you want to do some profiling
main()
Producción:
open_with_python_csv: 1.57318865672 seconds
open_with_python_csv_list: 1.35567931732 seconds
open_with_python_csv_cast_as_float: 3.0801260484 seconds
open_with_numpy_loadtxt: 14.4942111801 seconds
open_with_pandas_read_csv: 0.371965476805 seconds
Numpy fromfile: 0.0130216095713 seconds
Numpy load: 0.0245501650124 seconds
Para instalar todas las bibliotecas: Binarios no oficiales de Windows para paquetes de extensión de Python
Configuración de ventanas:
import numpy; numpy.version.version
)import pandas as pd; pd.__version__
)Producción:
open_with_python_csv: 1.93 seconds
open_with_python_csv_list: 1.52 seconds
open_with_python_csv_cast_as_float: 3.19 seconds
open_with_numpy_loadtxt: 7.47 seconds
open_with_pandas_read_csv: 0.35 seconds
Numpy fromfile: 0.01 seconds
Numpy load: 0.02 seconds
Para instalar todas las bibliotecas:
sudo apt-get install python-pip
sudo pip install numpy
sudo pip install pandas
Si las bibliotecas ya están instaladas pero necesitan actualizarse:
sudo apt-get install python-pip
sudo pip install numpy --upgrade
sudo pip install pandas --upgrade
Configuración de Ubuntu:
import numpy; numpy.version.version
)import pandas as pd; pd.__version__
)Obviamente, siéntase libre de mejorar el punto de referencia comentando/editando/etc. Estoy seguro de que hay muchas cosas para mejorar:
numpy.loadtxt
np.fromfile
parece terriblemente rápido. Lo que encontré en mis pruebas es que solo funciona en la primera línea, por lo que para hacer todo el archivo tienes que hacer un ciclo que vuelve a ralentizar las cosas a 60 s para mi archivo csv de 20 000 líneas, frente a 0,75 s para Pandas. ¿Estás leyendo todo el archivo con np.fromfile
? También pude usarlo np.fromstring
cargando todo el archivo csv, replace
ing '\n
con ''
y luego ejecutando np.fromstring
. Las manipulaciones de cadenas fueron rápidas, pero la conversión a números fue lenta. Este método tomó 2.6s.Me gustaría contribuir con otra biblioteca aquí, con la que tropecé buscando una pregunta similar. Lo probé con el código de referencia de Franck Dernoncourts y supera a Pythons csv estándar y Pandas por millas. No pude probar con numpy, ya que probé con un csv de 24.000 líneas con números y valores de cadena.
Esta biblioteca rápida en realidad se basa en la implementación csv predeterminada, solo usa TextIO , que lo hace más rápido Y maneja las cadenas Unicode correctamente.
Se llama fastcsv y fue desarrollado por Masaya Suzuki. Puede cerrarlo en GitHub o usar Pypi para instalarlo. más simple es:
pip install fastcsv
En http://pythonhosted.org/fastcsv/ puede ver más resultados de Benchmark, pero solo para leer csv, permítame repetir sus resultados aquí:
Sería interesante saber cómo funciona esto con sus datos.
Tiene una amplia variedad según el tamaño y la complejidad de los datos y lo que va a hacer con los datos resultantes:
csv
biblioteca que viene con Python por defecto.numpy.from_file
función - Lee en una matriz NumPy, por lo que es muy potente.pandas.io.parsers.read_csv
función - lee un marco de datos de pandas, es muy potente y puede manejar grandes conjuntos de datos.El primero probablemente será más rápido de importar, mientras que los otros son más potentes. Todos son gratuitos y multiplataforma. El primero ya es parte de su instalación de Python si tiene uno predeterminado.
Hay un nuevo pydatatable
paquete que tiene un lector csv muy rápido basado en la implementación de R data.table fread
.
Lea más en https://github.com/h2oai/datatable Si desea que se cargue el objeto pandas, simplemente puede ejecutar
pandas_dataframe = dt.fread(srcfile).to_pandas()
Sugeriría estar atento a la documentación oficial de pandas en IO . La opción de uno sigue cambiando según el ciclo de desarrollo y se agregan nuevos formatos todo el tiempo. También publican el benchmark.
Hay un nuevo paquete de Python para la minería de datos que se llama DaPy . Que tiene una API de E/S simple y lo suficientemente rápida para ti. Según la prueba de rendimiento del autor, DaPy tardó 12,5 segundos en cargar un archivo csv con más de 2 millones de registros, mientras que pandas tardó 4 segundos. Sin embargo, DaPy se basa en algunas estructuras de datos nativas de Python y es más fácil de usar.
cmd: pip install DaPy
>>> import DaPy as dp
>>> data = dp.read('file.csv')
>>> data.show()
ComFreek
software hexadecimal