2013-03-22 11 views
11

Mam kolejne podstawowe pytanie, na które nie byłem w stanie znaleźć odpowiedzi, ale wydaje się, że powinno być to łatwe.Jak usunąć kolumnę ze struktury numpy?

Ok, wyobraź sobie, że masz uporządkowaną tablicę numpy, wygenerowaną z pliku csv z pierwszym wierszem jako nazwy pól. Tablica ma postać:

dtype([('A', '<f8'), ('B', '<f8'), ('C', '<f8'), ..., ('n','<f8']) 

Teraz powiedzmy, że chcesz usunąć z tej tablicy z „” i-tą kolumnę. Czy istnieje wygodny sposób na zrobienie tego?

Chciałbym go do pracy jak kasowania:

new_array = np.delete(old_array, 'i') 

pomysłów?

+0

Czy wszystkie dtypes f8? –

Odpowiedz

13

To nie całkiem pojedynczego wywołania funkcji, ale Poniżej przedstawiono jeden sposób, aby upuścić pole I-th:

In [67]: a 
Out[67]: 
array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)], 
     dtype=[('A', '<f8'), ('B', '<f8'), ('C', '<f8')]) 

In [68]: i = 1 # Drop the 'B' field 

In [69]: names = list(a.dtype.names) 

In [70]: names 
Out[70]: ['A', 'B', 'C'] 

In [71]: new_names = names[:i] + names[i+1:] 

In [72]: new_names 
Out[72]: ['A', 'C'] 

In [73]: b = a[new_names] 

In [74]: b 
Out[74]: 
array([(1.0, 3.0), (4.0, 6.0)], 
     dtype=[('A', '<f8'), ('C', '<f8')]) 

Owinięty jako funkcję:

def remove_field_num(a, i): 
    names = list(a.dtype.names) 
    new_names = names[:i] + names[i+1:] 
    b = a[new_names] 
    return b 

To może być więcej naturalny do usunięcia danej dziedzinie nazwę:

def remove_field_name(a, name): 
    names = list(a.dtype.names) 
    if name in names: 
     names.remove(name) 
    b = a[names] 
    return b 

również ch eck out drop_rec_fields function, który jest częścią mlab module z matplotlib.


Aktualizacja: Zobacz moją odpowiedź na How to remove a column from a structured numpy array *without copying it*? na sposób utworzyć widok podzbiorów dziedzinach zorganizowanego tablicy bez podejmowania kopię tablicy.

+0

+1 Pokonaj mnie przez 3 minuty! – Jaime

+1

@ Junime: Ledwo. :) Ponieważ usunąłeś odpowiedź, wspomnę o usuwaniu według nazwy pola zamiast numeru, co może być bardziej naturalne. –

5

Po google moją drogę tutaj i dowiedziałem się, co potrzebne, aby wiedzieć z odpowiedzią Warrena, nie mogłem się oprzeć zamieszczając bardziej zwięzłą wersję, z dodatkową możliwością usunięcia wielu pól skutecznie za jednym zamachem:

def rmfield(a, *fieldnames_to_remove): 
    return a[ [ name for name in a.dtype.names if name not in fieldnames_to_remove ] ] 

Przykłady:

a = rmfield(a, 'foo') 
a = rmfield(a, 'foo', 'bar') # remove multiple fields at once 

Lub jeśli jesteśmy naprawdę będzie golfa, następujące jest równoważne:

rmfield=lambda a,*f:a[[n for n in a.dtype.names if n not in f]] 
+0

Twoje drugie rozwiązanie jest dość brzydkie, jeśli mogę tak powiedzieć. W szczególności nie podoba mi się użycie wyrażenia lambda dla deklaracji funkcji. To nie jest dobry styl i trudne do odczytania. Inni wydają się ze mną zgodzić: http://stackoverflow.com/a/134638/1375015 –

+1

Być może nie przeczytałeś zwrotu "jeśli naprawdę zamierzamy to zagrać w golfa" ... Celem "code golfa" "jest stworzenie najkrótszego kodu niezależnie od czytelności i że prawie nigdy nie przestaje być brzydki. – jez

+0

Nie wiedziałem o tym frazie. Nadal nie widzę sensu, ale w tym kontekście może moja odpowiedź była trochę surowa. –

Powiązane problemy