2012-05-24 15 views
12

Próbuję dodać nazwy kolumn do numpy ndarray, a następnie wybierz kolumny według ich nazw. Ale to nie działa. Nie mogę stwierdzić, czy problem występuje, gdy dodaję nazwy, czy później, gdy próbuję je wywoływać.Programowo dodawać nazwy kolumn do numpy ndarray

Oto mój kod.

data = np.genfromtxt(csv_file, delimiter=',', dtype=np.float, skip_header=1) 

#Add headers 
csv_names = [ s.strip('"') for s in file(csv_file,'r').readline().strip().split(',')] 
data = data.astype(np.dtype([(n, 'float64') for n in csv_names])) 

diagnostyka wymiarowe oparte dopasować czego oczekuję:

print len(csv_names) 
>> 108 
print data.shape 
>> (1652, 108) 

"data.dtype.names print" zwraca również oczekiwany wynik.

Ale kiedy zaczynam wywoływać kolumny według ich nazw pól, zdarzają się pomniejsze rzeczy. W „kolumna” jest wciąż tablicą z 108 kolumn ...

print data["EDUC"].shape 
>> (1652, 108) 

... i wydaje się zawierać więcej niż brakujące wartości są wiersze w zbiorze danych.

print np.sum(np.isnan(data["EDUC"])) 
>> 27976 

Masz pomysł, co tu jest nie tak? Dodawanie nagłówków powinno być trywialną operacją, ale od wielu godzin walczę z tym błędem. Wsparcie!

Odpowiedz

13

problemem jest to, że myślisz w kategoriach tablic kalkulacyjnych podobny, natomiast Num Py używa różnych pojęć.

Oto, co musisz wiedzieć o NumPy: tablice

  1. NumPy zawierać tylko elementy jednego typu.
  2. Jeśli potrzebujesz "kolumn" podobnych do arkusza kalkulacyjnego, ten typ musi być typem podobnym do krotki typu. Takie tablice nazywane są Tablicami Strukturalnymi, ponieważ ich elementy są strukturami (tj. Krotkami).

W twoim przypadku, NumPy byłoby zatem zabrać 2-wymiarową tablicę regularne i produkować jeden wymiarową tablicę, którego typ jest 108-elementowa krotka (tablica kalkulacyjnego że myślisz jest 2-wymiarowe).

Wybory te zostały prawdopodobnie dokonane ze względów wydajnościowych: wszystkie elementy tablicy mają ten sam typ i dlatego mają ten sam rozmiar: można uzyskać do nich dostęp na niskim poziomie, bardzo prosto i szybko.

Teraz, jak pokazał użytkownik545424, istnieje prosta odpowiedź NumPy na to, co chcesz zrobić (genfromtxt() akceptuje argument names z nazwami kolumn).

Jeśli chcesz zamienić tablicę z regularnym NumPy ndarray do zorganizowanego tablicy, można zrobić:

data.view(dtype=[(n, 'float64') for n in csv_names]).reshape(len(data)) 

(byłaś blisko: użyłeś astype() zamiast view()).

Możesz również sprawdzić odpowiedzi na kilka pytań Stackoverflow, w tym Converting a 2D numpy array to a structured array i how to convert regular numpy array to record array?.

+0

Dzięki - pomaga to konceptualnie. Ale wciąż mam kilka pytań na temat tej konkretnej sprawy. Tutaj wszystkie moje kolumny są zmiennoprzecinkowe i zamierzam wykonywać wiele mnożenia macierzy, więc chcę zachować strukturę tablic 2d - bez potrzeby stosowania tablicy strukturalnej. Wszystko, co chcę zrobić, to dodać nazwy pól. Czy to jest możliwe? – Abe

+0

NB: genfromtxt importuje plik CSV w formacie krotki numpy. Próbowałem wszystkiego, co mogłem wymyślić, aby importować nazwy pól w formacie tablicy i nic nie działało. – Abe

+0

@Abe: Nadal można wykonywać multiplikacje macierzy: 'view()' to po prostu inny sposób patrzenia na * same * dane. Tak więc możesz pracować zarówno z oryginalną tablicą danych, jak i tablicą 'view()' ed w tym samym czasie (pierwsza tablica to 2D, druga to 1D i ma strukturę). – EOL

2

Niestety, nie wiem, co się dzieje podczas próby dodania nazwy pól, ale wiem, że można zbudować tablicę chcesz bezpośrednio z pliku poprzez

data = np.genfromtxt(csv_file, delimiter=',', names=True) 

EDIT:

wydaje się, że dodanie nazwy pól działa tylko wtedy, gdy wejście jest listą krotek:

data = np.array(map(tuple,data), [(n, 'float64') for n in csv_names]) 
+0

Tak samo jest w przypadku, gdy ndarrays można odwoływać się do nazw pól, jeśli są one rzutowane jako krotki LUB odwołują się do identyfikatora pola, gdy są przesyłane jako tablice --- ale nigdy nie mają obu tych właściwości? Wygląda na to, że działa, ale nie widzę czegoś takiego w dokumentacji. – Abe

+0

Zaczynam się zastanawiać, czy to błąd. To dziwne zachowanie, że konstruktor tablicowy działa inaczej w zależności od typu struktury zagnieżdżonej, którą przekazujesz. – user545424

+0

@ user545424: Możesz zrozumieć to zachowanie, jeśli znasz zasady, na których opiera się NumPy (możesz na przykład sprawdzić moją odpowiedź). W skrócie: tuple() jest rodzajem "podstawowego typu" (jak float), dla NumPy (więc dostajesz rodzaj uporządkowanej tablicy, kiedy przechodzisz krotki), podczas gdy przekazywanie list lub tablic jako danych wejściowych oznacza "dodaj kolejny wymiar "do tablicy (zwykle dostajesz tablicę liczb). – EOL

Powiązane problemy