Come posso leggere i dati CSV in un array di record in NumPy?


415

Mi chiedo se c'è un modo diretto per importare il contenuto di un file CSV in una matrice di record, tanto nel modo di quella R read.table(), read.delim()e read.csv()le importazioni della famiglia di dati per inquadrare i dati di R?

O è il modo migliore per usare csv.reader () e quindi applicare qualcosa del genere numpy.core.records.fromrecords()?


Risposte:


647

Puoi usare il genfromtxt()metodo di Numpy per farlo, impostando delimiterkwarg su una virgola.

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

Ulteriori informazioni sulla funzione sono disponibili nella relativa documentazione .


10
E se vuoi qualcosa di diverso tipo? Come stringhe e ints?
CGTheLegend,

11
@CGTheLegend np.genfromtxt ('myfile.csv', delimiter = ',', dtype = None)
chickensoup

2
numpy.loadtxt ha funzionato abbastanza bene anche per me
Yibo Yang,

11
Ho provato questo, ma sto solo ottenendo nanvalori, perché? Anche con loadtxt, sto ottenendo UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 155: ordinal not in range(128). Ho dati come ä e ö nei dati di input.
hhh

1
@hhh prova ad aggiungere encoding="utf8"argomento. Python è uno dei pochi software moderni che spesso causa problemi di codifica del testo, che sembrano cose del passato.
Kolen,

187

Vorrei raccomandare la read_csvfunzione dalla pandaslibreria:

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

Questo dà un DataFrame di Panda - che consente molte utili funzioni di manipolazione dei dati che non sono direttamente disponibili con array di record intorpiditi .

DataFrame è una struttura di dati con etichetta bidimensionale con colonne di tipi potenzialmente diversi. Puoi pensarlo come un foglio di calcolo o una tabella SQL ...


Vorrei anche raccomandare genfromtxt. Tuttavia, poiché la domanda richiede un array di record , al contrario di un array normale, il dtype=Noneparametro deve essere aggiunto alla genfromtxtchiamata:

Dato un file di input, myfile.csv:

1.0, 2, 3
4, 5.5, 6

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

dà un array:

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

e

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

fornisce un array di record:

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

Ciò ha il vantaggio di poter importare facilmente file con più tipi di dati (comprese le stringhe) .


read_csv funziona con virgole tra virgolette. Consiglio questo su genfromtxt
Viet

3
usa header = 0 per saltare la prima riga nei valori, se il tuo file ha un'intestazione di 1 riga
c-chavez,

Ricorda che questo crea un array 2d: ad es (1000, 1). np.genfromtxtnon lo fa: ad es (1000,).
Newskooler

74

Ho cronometrato il

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

contro

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>)

su 4,6 milioni di righe con circa 70 colonne e ha scoperto che il percorso NumPy impiegava 2 minuti e 16 secondi e il metodo di comprensione dell'elenco csv impiegava 13 secondi.

Consiglierei il metodo di comprensione csv-list in quanto molto probabilmente si basa su librerie precompilate e non sull'interprete tanto quanto su NumPy. Sospetto che il metodo panda avrebbe un simile sovraccarico di interprete.


23
Ho testato un codice simile a questo con un file CSV contenente 2,6 milioni di righe e 8 colonne. numpy.recfromcsv () ha impiegato circa 45 secondi, np.asarray (list (csv.reader ())) ha impiegato circa 7 secondi e pandas.read_csv () ha impiegato circa 2 secondi (!). (Il file era stato letto di recente dal disco in tutti i casi, quindi era già nella cache dei file del sistema operativo.) Penso che andrò con i panda.
Matthias Fripp,

5
Ho appena notato che ci sono alcune note sul design del veloce parser CSV panda su wesmckinney.com/blog/… . L'autore prende molto sul serio i requisiti di velocità e memoria. È anche possibile utilizzare as_recarray = True per ottenere il risultato direttamente come un array di record Python anziché come un frame di dati panda.
Matthias Fripp,

67

Puoi anche provare recfromcsv()quale può indovinare i tipi di dati e restituire un array di record formattato correttamente.


9
Se si desidera mantenere i nomi di ordini / colonne nel CSV, è possibile utilizzare la seguente chiamata: numpy.recfromcsv(fname, delimiter=',', filling_values=numpy.nan, case_sensitive=True, deletechars='', replace_space=' ')Gli argomenti chiave sono gli ultimi tre.
eacousineau,

16

Come ho provato in entrambi i modi usando NumPy e Panda, l'uso di Panda ha molti vantaggi:

  • Più veloce
  • Minore utilizzo della CPU
  • 1/3 di utilizzo della RAM rispetto a NumPy genfromtxt

Questo è il mio codice di prova:

$ 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')

File di dati:

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

Con NumPy e Panda nelle versioni:

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

5

È possibile utilizzare questo codice per inviare i dati del file CSV in un array:

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

4

utilizzando numpy.loadtxt

Un metodo abbastanza semplice. Ma richiede che tutti gli elementi siano float (int e così via)

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

4

Questo è il modo più semplice:

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

Ora ogni voce nei dati è un record, rappresentato come un array. Quindi hai un array 2D. Mi ha fatto risparmiare così tanto tempo.


Perché dovremmo andare in giro con i panda, quando questi strumenti hanno molte meno funzioni gonfie?
Christopher

3

Ho provato questo:

import pandas as p
import numpy as n

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

3

Suggerirei di usare tables ( pip3 install tables). Puoi salvare il tuo .csvfile .h5usando panda ( pip3 install pandas),

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

Puoi quindi facilmente e con meno tempo anche per una grande quantità di dati, caricare i tuoi dati in un array NumPy .

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

# Data in NumPy format
data = data.values

3

Questo lavoro come un incanto ...

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)

il codice deve essere correttamente rientrato nel suo layout di markdown del codice.
surajs1n,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.