¿Cómo leo datos CSV en una matriz de registros en NumPy?

415

Me pregunto si hay una forma directa de importar el contenido de un archivo CSV en una matriz de registro, tanto en la forma en que de R read.table(), read.delim()y read.csv()la importación de datos a la familia trama de datos de R?

¿O es la mejor manera de usar csv.reader () y luego aplicar algo como numpy.core.records.fromrecords()?

hatmatrix
fuente
Posible duplicado de ¿Cómo leo y escribo archivos CSV con Python?
Martin Thoma

Respuestas:

647

Puede usar el genfromtxt()método de Numpy para hacerlo, estableciendo el delimiterkwarg en una coma.

from numpy import genfromtxt
my_data = genfromtxt('my_file.csv', delimiter=',')

Puede encontrar más información sobre la función en su documentación respectiva .

Andrés
fuente
10
¿Qué pasa si quieres algo de diferentes tipos? ¿Como cuerdas e ints?
CGTheLegend
11
@CGTheLegend np.genfromtxt ('myfile.csv', delimiter = ',', dtype = None)
chickensoup
2
numpy.loadtxt también funcionó bastante bien para mí
Yibo Yang
11
Intenté esto pero solo obtengo nanvalores, ¿por qué? También con loadtxt, estoy obteniendo UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 155: ordinal not in range(128). Tengo diéresis como ä y ö en los datos de entrada.
hhh
1
@hhh intenta agregar encoding="utf8"argumento. Python es una de las pocas piezas de software modernas que con frecuencia causa problemas de codificación de texto, que se sienten como cosas del pasado.
kolen
187

Recomendaría la read_csvfunción de la pandasbiblioteca:

import pandas as pd
df=pd.read_csv('myfile.csv', sep=',',header=None)
df.values
array([[ 1. ,  2. ,  3. ],
       [ 4. ,  5.5,  6. ]])

Esto proporciona un DataFrame de pandas , que permite muchas funciones útiles de manipulación de datos que no están disponibles directamente con matrices de registros numpy .

DataFrame es una estructura de datos etiquetada bidimensional con columnas de tipos potencialmente diferentes. Puedes pensarlo como una hoja de cálculo o una tabla SQL ...


Yo también lo recomendaría genfromtxt. Sin embargo, dado que la pregunta solicita una matriz de registros , a diferencia de una matriz normal, el dtype=Noneparámetro debe agregarse a la genfromtxtllamada:

Dado un archivo de entrada, myfile.csv:

1.0, 2, 3
4, 5.5, 6

import numpy as np
np.genfromtxt('myfile.csv',delimiter=',')

da una matriz:

array([[ 1. ,  2. ,  3. ],
       [ 4. ,  5.5,  6. ]])

y

np.genfromtxt('myfile.csv',delimiter=',',dtype=None)

da una matriz de registros:

array([(1.0, 2.0, 3), (4.0, 5.5, 6)], 
      dtype=[('f0', '<f8'), ('f1', '<f8'), ('f2', '<i4')])

Esto tiene la ventaja de que el archivo con múltiples tipos de datos (incluidas las cadenas) se puede importar fácilmente .

atomh33ls
fuente
read_csv funciona con comas entre comillas. Recomiende esto sobre genfromtxt
Viet
3
use header = 0 para omitir la primera línea en los valores, si su archivo tiene un encabezado de 1 línea
c-chavez
Tenga en cuenta que esto crea una matriz 2D: por ejemplo (1000, 1). np.genfromtxtno hace eso: ej (1000,).
Newskooler
74

Cronometré el

from numpy import genfromtxt
genfromtxt(fname = dest_file, dtype = (<whatever options>))

versus

import csv
import numpy as np
with open(dest_file,'r') as dest_f:
    data_iter = csv.reader(dest_f,
                           delimiter = delimiter,
                           quotechar = '"')
    data = [data for data in data_iter]
data_array = np.asarray(data, dtype = <whatever options>)

en 4.6 millones de filas con aproximadamente 70 columnas y descubrió que la ruta NumPy tomó 2 min 16 segundos y el método de comprensión de la lista csv tomó 13 segundos.

Recomendaría el método de comprensión csv-list, ya que probablemente se basa en bibliotecas precompiladas y no en el intérprete tanto como NumPy. Sospecho que el método de los pandas tendría una sobrecarga de intérprete similar.

William komp
fuente
23
Probé un código similar a este con un archivo csv que contiene 2.6 millones de filas y 8 columnas. numpy.recfromcsv () tardó aproximadamente 45 segundos, np.asarray (list (csv.reader ())) tardó aproximadamente 7 segundos y pandas.read_csv () tomó aproximadamente 2 segundos (!). (El archivo se había leído recientemente del disco en todos los casos, por lo que ya estaba en la caché de archivos del sistema operativo). Creo que iré con pandas.
Matthias Fripp
55
Acabo de notar que hay algunas notas sobre el diseño del analizador rápido de csv de pandas en wesmckinney.com/blog/… . El autor se toma muy en serio los requisitos de velocidad y memoria. También es posible usar as_recarray = True para obtener el resultado directamente como una matriz de registros de Python en lugar de un marco de datos de pandas.
Matthias Fripp
67

También puede probar recfromcsv()qué puede adivinar los tipos de datos y devolver una matriz de registros con el formato adecuado.

btel
fuente
99
Si desea mantener los nombres de orden / columna en el CSV, puede usar la siguiente invocación: numpy.recfromcsv(fname, delimiter=',', filling_values=numpy.nan, case_sensitive=True, deletechars='', replace_space=' ')Los argumentos clave son los tres últimos.
eacousineau
16

Como probé en ambos sentidos usando NumPy y Pandas, usar pandas tiene muchas ventajas:

  • Más rápido
  • Menos uso de CPU
  • 1/3 de uso de RAM en comparación con NumPy genfromtxt

Este es mi código de prueba:

$ for f in test_pandas.py test_numpy_csv.py ; do  /usr/bin/time python $f; done
2.94user 0.41system 0:03.05elapsed 109%CPU (0avgtext+0avgdata 502068maxresident)k
0inputs+24outputs (0major+107147minor)pagefaults 0swaps

23.29user 0.72system 0:23.72elapsed 101%CPU (0avgtext+0avgdata 1680888maxresident)k
0inputs+0outputs (0major+416145minor)pagefaults 0swaps

test_numpy_csv.py

from numpy import genfromtxt
train = genfromtxt('/home/hvn/me/notebook/train.csv', delimiter=',')

test_pandas.py

from pandas import read_csv
df = read_csv('/home/hvn/me/notebook/train.csv')

Archivo de datos:

du -h ~/me/notebook/train.csv
 59M    /home/hvn/me/notebook/train.csv

Con NumPy y pandas en las versiones:

$ pip freeze | egrep -i 'pandas|numpy'
numpy==1.13.3
pandas==0.20.2
HVNSweeting
fuente
5

Puede usar este código para enviar datos del archivo CSV a una matriz:

import numpy as np
csv = np.genfromtxt('test.csv', delimiter=",")
print(csv)
chamzz.dot
fuente
4

Utilizando numpy.loadtxt

Un método bastante simple. Pero requiere que todos los elementos sean flotantes (int, etc.)

import numpy as np 
data = np.loadtxt('c:\\1.csv',delimiter=',',skiprows=0)  
Xiaojian Chen
fuente
4

Esta es la manera más fácil:

import csv with open('testfile.csv', newline='') as csvfile: data = list(csv.reader(csvfile))

Ahora cada entrada en los datos es un registro, representado como una matriz. Entonces tienes una matriz 2D. Me ahorró mucho tiempo.

Matthew Park
fuente
¿Por qué deberíamos tener que jugar con Pandas, cuando estas herramientas tienen mucha menos función hinchada?
Christopher
3

Intenté esto:

import pandas as p
import numpy as n

closingValue = p.read_csv("<FILENAME>", usecols=[4], dtype=float)
print(closingValue)
muTheTechie
fuente
3

Sugeriría usar tablas ( pip3 install tables). Puede guardar su .csvarchivo en .h5pandas ( pip3 install pandas),

import pandas as pd
data = pd.read_csv("dataset.csv")
store = pd.HDFStore('dataset.h5')
store['mydata'] = data
store.close()

Luego, puede cargar fácilmente sus datos en una matriz NumPy , y con menos tiempo incluso para una gran cantidad de datos .

import pandas as pd
store = pd.HDFStore('dataset.h5')
data = store['mydata']
store.close()

# Data in NumPy format
data = data.values
Jatin Mandav
fuente
3

Este trabajo como un encanto ...

import csv
with open("data.csv", 'r') as f:
    data = list(csv.reader(f, delimiter=";"))

import numpy as np
data = np.array(data, dtype=np.float)
Nihal Sargaiya
fuente
el código debe sangrarse correctamente dentro de su diseño de marcado de código.
surajs1n