2015-10-07 12 views
8

Ho un file CSV che ho scaricato dal sito dell'OMS (http://apps.who.int/gho/data/view.main.52160, Download, "tabella multiuso in formato CSV"). Provo a caricare il file in una matrice numpy. Ecco il mio codice:Caricamento file UTF-8 in Python 3 con numpy.genfromtxt

import numpy 
#U75 - unicode string of max. length 75 
world_alcohol = numpy.genfromtxt("xmart.csv", dtype="U75", skip_header=2, delimiter=",") 
print(world_alcohol) 

E ho

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2: ordinal not in range(128).

immagino che NumPy ha un problema di lettura della stringa "Costa d'Avorio". Il file è correttamente codificato UTF-8 (secondo il mio editor di testo). Sto usando Python 3.4.3 e Numpy 1.9.2.

Cosa sto sbagliando? Come posso leggere il file in numpy?

risposta

8

In python3 che posso fare:

In [224]: txt = "Côte d'Ivoire" 
In [225]: x = np.zeros((2,),dtype='U20') 
In [226]: x[0] = txt 
In [227]: x 
Out[227]: 
array(["Côte d'Ivoire", ''], dtype='<U20') 

Il che significa che probabilmente potuto aprire il file di un 'UTF-8' (regolare, non la modalità di byte), e readlines, e assegnarli a elementi di un array come x.

Ma genfromtxt insiste sul funzionamento con stringhe di byte (ascii) che non possono gestire il più grande set UTF-8 (7 byte v 8). Quindi ho bisogno di applicare decode ad un certo punto per ottenere un array U.

posso caricarlo in una matrice 'S' con genfromtxt:

In [258]: txt="Côte d'Ivoire" 
In [259]: a=np.genfromtxt([txt.encode()],delimiter=',',dtype='S20') 
In [260]: a 
Out[260]: 
array(b"C\xc3\xb4te d'Ivoire", dtype='|S20') 

e applicare decode ai singoli elementi:

In [261]: print(a.item().decode()) 
Côte d'Ivoire 

In [325]: print _ 
Côte d'Ivoire 

oppure utilizzare np.char.decode applicarlo a ciascun elemento di un array :

In [263]: np.char.decode(a) 
Out[263]: 
array("Côte d'Ivoire", dtype='<U13') 
In [264]: print(_) 
Côte d'Ivoire 

genfromtxt let s che specificare le converters:

In [297]: np.genfromtxt([txt.encode()],delimiter=',',dtype='U20', 
    converters={0:lambda x: x.decode()}) 
Out[297]: 
array("Côte d'Ivoire", dtype='<U20') 

Se il csv ha un mix di stringhe e numeri, questo approccio converters sarà più facile da usare rispetto alla np.char.decode. Basta specificare il convertitore per ogni colonna di stringhe.

(Vedere le mie precedenti modifiche per i tentativi Python2).

+0

Non OP ma grazie per l'accumulo chiaro e utile della risposta. – KobeJohn

+1

Grazie per la risposta. Funziona! Sto solo iniziando con Python e trovo strano che numpy non possa leggere l'UTF-8 immediatamente. Ho letto che Python è facile e sviluppato con semplicità e facilità d'uso in mente ma leggere UTF-8 richiede una conversione aggiuntiva? Pensavo che vivessimo nel 2015. – JustAC0der