2013-07-29 10 views
21

Sto provando a leggere in un file csv con numpy.genfromtxt ma alcuni campi sono stringhe che contengono virgole. Le stringhe sono tra virgolette, ma numpy non riconosce le virgolette come se definissero una singola stringa. Ad esempio, con i dati in 't.csv':Utilizzo di numpy.genfromtxt per leggere un file csv con stringhe contenenti virgole

2012, "Louisville KY", 3.5 
2011, "Lexington, KY", 4.0 

il codice

np.genfromtxt('t.csv', delimiter=',') 

produce l'errore:

ValueError: Some errors were detected ! Line #2 (got 4 columns instead of 3)

La struttura dei dati che sto cercando è:

array([['2012', 'Louisville KY', '3.5'], 
     ['2011', 'Lexington, KY', '4.0']], 
     dtype='|S13') 

Osservando la documentazione, I non vedo alcuna opzione per affrontare questo. C'è un modo per farlo con Numpy, o devo solo leggere i dati con il modulo csv e poi convertirlo in un array numpy?

+0

potete inserire più del pieno csv, credo di sapere come risolvere il problema;) –

+0

Si dovrebbe cambiare la vostra csv sostituendo il carattere separatore da ',' a ';' ad esempio ... –

+0

@ SaulloCastro: Non posso farlo perché i miei dati reali sono molto più confusi e hanno delle stringhe con ';' e/o qualsiasi altro personaggio a cui puoi pensare - questo è solo un esempio di giocattolo. Quello che sto cercando è una soluzione più generale. – CraigO

risposta

17

Per questo è possibile utilizzare pandas (la libreria che diventa predefinita per lavorare con i dataframes (dati eterogenei) in python scientifico). È read_csv in grado di gestirlo. Da i documenti:

quotechar : string

The character to used to denote the start and end of a quoted item. Quoted items 
can include the delimiter and it will be ignored. 

Il valore predefinito è ". Un esempio:

In [1]: import pandas as pd 

In [2]: from StringIO import StringIO 

In [3]: s="""year, city, value 
    ...: 2012, "Louisville KY", 3.5 
    ...: 2011, "Lexington, KY", 4.0""" 

In [4]: pd.read_csv(StringIO(s), quotechar='"', skipinitialspace=True) 
Out[4]: 
    year   city value 
0 2012 Louisville KY 3.5 
1 2011 Lexington, KY 4.0 

Il trucco è che si hanno anche per usare skipinitialspace=True a che fare con gli spazi dopo la virgola-delimitatore.

A parte un potente lettore csv, posso anche consigliare vivamente di usare i panda con i dati eterogenei che avete (l'output di esempio in numpy che date sono tutte stringhe, sebbene potreste usare array strutturati).

+0

Fantastico, funziona come un fascino. Ho sentito un po 'di 'panda' ma non ho mai provato a provarlo prima - questa sembra una grande opportunità. E a proposito, stavo cercando di mantenere il mio esempio iniziale semplice, ma in realtà stavo pianificando di usare 'np.recfromcsv' per ottenere array strutturati e numpy. – CraigO

9

Il problema con la virgola aggiuntiva, np.genfromtxt non si occupa di ciò.

Una soluzione semplice consiste nel leggere il file condal modulo di python in un elenco e quindi eseguirne il dump in un array numpy, se lo si desidera.

Se si desidera utilizzare realmente np.genfromtxt, si noti che può richiedere iteratori anziché file, ad es. np.genfromtxt(my_iterator, ...). Pertanto, puoi racchiudere un valore csv.reader in un iteratore e assegnarlo a np.genfromtxt.

che sarebbe andato qualcosa come questo:

import csv 
import numpy as np 

np.genfromtxt(("\t".join(i) for i in csv.reader(open('myfile.csv'))), delimiter="\t") 

Questo sostituisce essenzialmente on-the-fly solo il virgole appropriata con le schede.

+0

Bene, vedo cosa si sta facendo qui, ma ho giocato un po 'ma ancora non riuscivo a farlo funzionare correttamente. Ad ogni modo, penso che oggi vado con la rotta 'panda '. Grazie comunque. – CraigO

3

Se si utilizza un numpy, probabilmente si desidera lavorare con numpy.ndarray. Questo vi darà un numpy.ndarray:

import pandas 
data = pandas.read_csv('file.csv').as_matrix() 

Pandas gestirà il caso "Lexington, KY" in modo corretto

+0

Si noti che se si esegue questa operazione, la prima riga potrebbe essere persa. La prima riga viene considerata come le etichette delle colonne del dataframe. –

1

Fai un migliore funzione che combina la potenza dello standard csv module e Numpy di recfromcsv.Ad esempio, il modulo csv ha un buon controllo e personalizzazione di dialetti, virgolette, caratteri di escape e così via, che è possibile aggiungere all'esempio seguente.

La funzione di esempio genfromcsv_mod si legge in un file CSV complesso simile a ciò che vede Microsoft Excel, che può contenere virgole nei campi tra virgolette. Internamente, la funzione ha una funzione di generatore che riscrive ogni riga con delimitatori di tabulazione.

import csv 
import numpy as np 

def recfromcsv_mod(fname, **kwargs): 
    def rewrite_csv_as_tab(fname): 
     with open(fname, 'rb') as fp: 
      reader = csv.reader(fp) 
      for row in reader: 
       yield '\t'.join(row) 
    return np.recfromcsv(rewrite_csv_as_tab(fname), delimiter='\t', **kwargs) 

# Use it to read a CSV file into a record array 
x = recfromcsv_mod('t.csv', case_sensitive=True)