2015-12-15 10 views
6

Ho riscontrato il seguente problema con NumPy 1.10.2 durante la lettura di un file CSV. Non riesco a capire come fornire tipi di dati espliciti a genfromtxt.NumPy: disadattamento delle dimensioni del vecchio e nuovo descrittore di dati

Ecco il CSV, minimal.csv:

x,y 
1,hello 
2,hello 
3,jello 
4,jelly 
5,belly 

Qui provo a leggerla con genfromtxt:

import numpy 
numpy.genfromtxt('minimal.csv', dtype=(int, str)) 

Ho anche provato:

import numpy 
numpy.genfromtxt('minimal.csv', names=True, dtype=(int, str)) 

In ogni caso, ho la errore:

Traceback (most recent call last): 
    File "visualize_numpy.py", line 39, in <module> 
    numpy.genfromtxt('minimal.csv', dtype=(int, str)) 
    File "/Users/xeli/workspace/myproj/env/lib/python3.5/site-packages/numpy/lib/npyio.py", line 1518, in genfromtxt 
    replace_space=replace_space) 
    File "/Users/xeli/workspace/myproj/env/lib/python3.5/site-packages/numpy/lib/_iotools.py", line 881, in easy_dtype 
    ndtype = np.dtype(ndtype) 
ValueError: mismatch in size of old and new data-descriptor 

In alternativa, ho provato:

import numpy 
numpy.genfromtxt('minimal.csv', dtype=[('x', int), ('y', str)]) 

che getta:

Traceback (most recent call last): 
    File "visualize_numpy.py", line 39, in <module> 
    numpy.genfromtxt('minimal.csv', dtype=[('x', int), ('y', str)]) 
    File "/Users/xeli/workspace/myproj/env/lib/python3.5/site-packages/numpy/lib/npyio.py", line 1834, in genfromtxt 
    rows = np.array(data, dtype=[('', _) for _ in dtype_flat]) 
ValueError: size of tuple must match number of fields. 

ho conosciuto dtype=None rende NumPy per cercare di indovinare i tipi corretti e di solito funziona bene. Tuttavia, la documentazione menziona che è molto più lento di tipi espliciti. Nel mio caso è richiesta l'efficienza computazionale, quindi dtype=None non è un'opzione.

C'è qualcosa di terribilmente sbagliato nel mio approccio o in NumPy?

+1

Ho avuto un problema molto simile, che ho risolto dando il dtype come una lista invece di una tupla, e sembra lo stesso per il tuo caso. – pela

risposta

3

Questo metodo funziona bene, e di conservare le informazioni di intestazione:

df = numpy.genfromtxt('minimal.csv', 
         names=True, 
         dtype=None, 
         delimiter=',') 

Questo rende genfromtxt indovinare il DTYPE, che è generalmente quello che si vuole. Il delimitatore è una virgola, quindi dovremmo passare anche questo argomento e infine, names=True conserva le informazioni dell'intestazione.

È sufficiente accedere ai propri dati come si farebbe con qualsiasi fotogramma:

>>>>print(df['x']) 
[1 2 3 4 5] 

Edit: secondo il vostro commento qui sotto, è possibile fornire il DTYPE esplicitamente, in questo modo:

df = numpy.genfromtxt('file1.csv', 
         names=True, 
         dtype=[('x', int), ('y', 'S5')], # assuming each string is of len =< 5 
         delimiter=',') 
+0

Grazie! E scusa, purtroppo 'dtype = None' non è adatto nel mio caso a causa della sua lentezza. Ho aggiunto questo alla domanda. Non riesco proprio a capire come dare esplicitamente i tipi a genfromtxt. –

+0

@ AkseliPalén, vedere la mia risposta aggiornata! Spero che aiuti :) –

0

Da uno sguardo breve allo documentation, il valore predefinito delimiter=None.

Prova numpy.genfromtxt('minimal.csv', dtype=(int, str), names=True, delimiter=',')

+0

puoi usare 'names = True' per leggere i nomi delle colonne dalla prima riga – MaxNoe

+0

@MaxNoe oh mio errore. Quindi il campo delimitatore non è importante allora. – pushkin

+0

'names = True' sostituisce' skip_header'. Hai ancora bisogno di 'delimitatore = ','' e 'dtype = None'. – hpaulj

0

I Sono nella stessa posizione in cui non sono sicuro del motivo per cui i miei tipi forniti stanno generando un errore. Detto questo, questa potrebbe essere una soluzione praticabile per te. Ecco un esempio che utilizza il mio set di dati, che sembra simile al tuo.

In primo luogo, caricare alcuni dei dati e ispezionare le dtypes effettivi NumPy utilizza:

>>> movies = np.genfromtxt('movies.csv', delimiter='|', dtype=None) 
>>> movies 
array([(1, 'Toy Story (1995)'), (2, 'GoldenEye (1995)'), 
     (3, 'Four Rooms (1995)'), ..., (1680, 'Sliding Doors (1998)'), 
     (1681, 'You So Crazy (1994)'), 
     (1682, 'Scream of Stone (Schrei aus Stein) (1991)')], 
     dtype=[('f0', '<i8'), ('f1', 'S81')]) 

Poi caricare tutti i dati utilizzando i tipi rilevate:

>>> movies = np.genfromtxt('movies.csv', delimiter='|', 
          dtype=[('f0', '<i8'), ('f1', 'S81')]) 

Questo non è certamente soddisfacente come sapendo perché NumPy lancia l'errore, ma funziona per il tuo caso d'uso specifico.

Problemi correlati