2016-05-06 13 views
4

Bei einem strukturierten numpy Array möchte ich bestimmte Spalten nach Namen entfernen, ohne das Array zu kopieren. Ich weiß, ich kann dies tun:Wie entferne ich eine Spalte aus einem strukturierten numpy Array * ohne sie zu kopieren *?

names = list(a.dtype.names) 
if name_to_remove in names: 
    names.remove(name_to_remove) 
a = a[names] 

Aber das schafft eine temporäre Kopie des Arrays, die ich vermeiden will, da das Array mit denen ich zu tun könnte sehr groß sein.

Gibt es einen guten Weg, dies zu tun?

+0

Wenn Sie die Liste "Namen" vermeiden möchten, können Sie eine Lambda-Funktion schreiben, die diese Operation ausführt. –

+0

Das Problem ist, dass 'a [Namen]' eine Kopie des ursprünglichen Arrays erstellt, es einem zuweist und erst dann das ursprüngliche Array löscht. Ich möchte diese Kopie vermeiden. Vielleicht sollte ich meine Frage irgendwie klären? –

+0

Sie sprechen über die Erstellung der "Namen" Liste richtig? –

Antwort

5

Sie können einen neuen Datentyp erstellen, der nur die gewünschten Felder enthält, mit den gleichen Feldoffsets und derselben Objektgröße wie der Datentyp des ursprünglichen Arrays, und dann diesen neuen Datentyp verwenden, um eine Ansicht des ursprünglichen Arrays zu erstellen . Die dtype-Funktion behandelt Argumente mit vielen Formaten; Der relevante wird im Abschnitt der Dokumentation "Specifying and constructing data types" beschrieben. Scrollen Sie nach unten zu dem Unterabschnitt, der mit

beginnt

Hier sind ein paar Komfortfunktionen, die diese Idee verwenden.

import numpy as np 


def view_fields(a, names): 
    """ 
    `a` must be a numpy structured array. 
    `names` is the collection of field names to keep. 

    Returns a view of the array `a` (not a copy). 
    """ 
    dt = a.dtype 
    formats = [dt.fields[name][0] for name in names] 
    offsets = [dt.fields[name][1] for name in names] 
    itemsize = a.dtype.itemsize 
    newdt = np.dtype(dict(names=names, 
          formats=formats, 
          offsets=offsets, 
          itemsize=itemsize)) 
    b = a.view(newdt) 
    return b 


def remove_fields(a, names): 
    """ 
    `a` must be a numpy structured array. 
    `names` is the collection of field names to remove. 

    Returns a view of the array `a` (not a copy). 
    """ 
    dt = a.dtype 
    keep_names = [name for name in dt.names if name not in names] 
    return view_fields(a, keep_names) 

Zum Beispiel

In [297]: a 
Out[297]: 
array([(10.0, 13.5, 1248, -2), (20.0, 0.0, 0, 0), (30.0, 0.0, 0, 0), 
     (40.0, 0.0, 0, 0), (50.0, 0.0, 0, 999)], 
     dtype=[('x', '<f8'), ('y', '<f8'), ('i', '<i8'), ('j', '<i8')]) 

In [298]: b = remove_fields(a, ['i', 'j']) 

In [299]: b 
Out[299]: 
array([(10.0, 13.5), (20.0, 0.0), (30.0, 0.0), (40.0, 0.0), (50.0, 0.0)], 
     dtype={'names':['x','y'], 'formats':['<f8','<f8'], 'offsets':[0,8], 'itemsize':32}) 

Stellen Sie sicher, dass b eine Ansicht ist (keine Kopie) von a durch b[0]['x'] Ändern ...

In [300]: b[0]['x'] = 3.14 

und zu sehen, dass a ebenfalls geändert :

In [301]: a[0] 
Out[301]: (3.14, 13.5, 1248, -2) 
Verwandte Themen