2015-12-15 14 views
6

Wystąpił następujący problem z NumPy 1.10.2 podczas odczytu pliku CSV. Nie mogę wymyślić, jak przekazać jawne typy danych do genfromtxt.NumPy: niedopasowanie rozmiaru starego i nowego deskryptora danych

Oto CSV, minimal.csv:

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

Tutaj staram się czytać z genfromtxt:

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

Próbowałem również:

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

W każdym razie, ja dostać błąd:

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 

Alternatywnie, próbowałem:

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

Która rzuca:

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. 

mi wiadomo dtype=None sprawia NumPy spróbować odgadnąć prawidłowe typy i zazwyczaj działa dobrze. Jednak dokumentacja wspomina, że ​​jest znacznie wolniejsza niż typy jawne. W moim przypadku wymagana jest wydajność obliczeniowa, więc nie jest to opcja.

Czy jest coś nie w porządku z moim podejściem lub NumPy?

+1

Miałem bardzo podobny problem, który rozwiązałem, podając dtype jako listę zamiast krotki i wydaje się, że to samo dotyczy przypadku. – pela

Odpowiedz

3

Działa to dobrze i zachowuje swoje dane nagłówka:

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

To sprawia genfromtxt odgadnąć dtype, która jest na ogół to, co chcesz. Delimiter jest przecinkiem, więc powinniśmy przekazać ten argument również i ostatecznie, names=True zachowuje informacje nagłówka.

Wystarczy dostęp do swoich danych, jak w przypadku każdej ramki:

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

Edit:, jak na swój komentarz poniżej, można dostarczyć dtype wyraźnie, tak jak poniżej:

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

Dzięki! I przepraszam, niestety "dtype = None" nie jest odpowiedni w moim przypadku ze względu na jego powolność. Dodałem to na pytanie. Po prostu nie mogę wymyślić, jak wyraźnie podać typy genfromtxt. –

+0

@ AkseliPalén, zobacz moją zaktualizowaną odpowiedź! Mam nadzieję, że to pomoże :) –

0

Od krótkiego spojrzenia na documentation, domyślną delimiter=None.

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

+0

możesz użyć 'names = True', aby odczytać nazwy kolumn z pierwszego wiersza – MaxNoe

+0

@MaxNoe o mój błąd. Tak więc pole ogranicznika nie jest wtedy ważne. – pushkin

+0

'names = True' zastępuje' skip_header'. Nadal potrzebujesz 'delimiter = ',' 'i' dtype = None'. – hpaulj

0

I znajduję się w tej samej pozycji, w której nie mam pewności, dlaczego podane przeze mnie typy powodują błąd. To powiedziawszy, to może być dla ciebie praktyczne rozwiązanie. Oto przykład użycia mojego zestawu danych, który wydaje się podobny do twojego.

Najpierw załadować niektórych danych i sprawdzić rzeczywiste dtypes NumPy używa:

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

Następnie załadować wszystkie dane z wykorzystaniem wykrytego typu:

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

To nie jest wprawdzie tak zadowalające jak wiedząc, dlaczego NumPy rzuca błąd, ale działa w konkretnym przypadku użycia.