Sie Kommentar:
Aber ist es nicht seltsam, dass solch eine grundlegende Operation f ails? Nur ein einfaches Array x = numpy.zeros(3, dtype={'names':['col1', 'col2'], 'formats':['i4','f4']})
kann eine Spalte mit numpy.delete(x,0,1)
nicht löschen. Was ist der Grund für dieses Problem, irgendwelche Ideen?
np.delete
ist keine grundlegende Operation. Schau dir den Code an. Es ist 5 Bildschirme lang (auf Ipython). Eine Menge davon behandelt die verschiedenen Möglichkeiten, wie Sie die Löschelemente angeben können.
Für np.delete (x, 0, Achse = 1)
es einen Sonderfall verwendet
# optimization for a single value
...
newshape[axis] -= 1
new = empty(newshape, arr.dtype, arrorder)
slobj[axis] = slice(None, obj)
new[slobj] = arr[slobj]
slobj[axis] = slice(obj, None)
slobj2 = [slice(None)]*ndim
slobj2[axis] = slice(obj+1, None)
new[slobj] = arr[slobj2]
für einen 2D-Array und Achse 1 = Funktion:
new = np.zeros((x.shape[0], x.shape[1]-1), dtype=x.dtype)
new[:, :obj] = x[:, :obj]
new[:, obj:] = x[:, obj+1:]
Mit anderen Worten, es reserviert ein neues Array mit 1 weniger Spalte und kopiert dann zwei Scheiben vom Original zu ihm.
Mit mehreren Spalten löschen und boolean obj
dauert es andere Routen.
Beachten Sie, dass für diese Aktion die Möglichkeit wichtig ist, die 2 Dimensionen zu indizieren.
Aber Sie können Ihre x
auf diese Weise nicht indexieren. x[0,1]
gibt einen too many indices
Fehler. Sie müssen x[0]['col1']
verwenden. Die Indexierung der Felder eines dtype
unterscheidet sich grundlegend von der Indizierung der Spalten eines 2d-Arrays.
Die recfunctions
manipulieren die dtype
Felder in Möglichkeiten, die normale numpy
Funktionen nicht tun. Basierend auf früheren Studie, vermute ich, dass drop_field
so etwas wie dies funktioniert:
In [57]: x # your x with some values
Out[57]:
array([(1, 3.0), (2, 2.0), (3, 1.0)],
dtype=[('col1', '<i4'), ('col2', '<f4')])
Ziel Array mit unterschiedlichen dtype
(fehlt ein Feld)
In [58]: y=np.zeros(x.shape, dtype=x.dtype.descr[1:])
Kopie Werte, Feld für Feld:
In [60]: for name in y.dtype.names:
...: y[name]=x[name]
In [61]: y
Out[61]:
array([(3.0,), (2.0,), (1.0,)],
dtype=[('col2', '<f4')])
Regelmäßige nd Indizierung wird um die Attribute shape
und strides
aufgebaut. Mit diesen (und der Bytegröße des Elements) kann die Position im Puffer data
eines gewünschten Elements schnell identifiziert werden.
Mit einer Verbindung dtype
arbeiten Form und Schritte auf die gleiche Weise, aber nbytes
ist anders. In Ihrem Fall x
ist es jeweils 24 - 12 für die Felder 10 und f4
Felder. Also regelmäßige Indexierungsschritte von einem 24-Bit-Datensatz zum nächsten. Um das 'col2'-Feld auszuwählen, muss daher der zweite Satz von 4 Bytes innerhalb jedes Datensatzes ausgewählt werden.
Wo es möglich ist, denke ich, dass es Feldauswahl in reguläre Indizierung übersetzt. __array_interface__
ist ein schönes Wörterbuch der wesentlichen Attribute eines Arrays.
In [70]: x.__array_interface__
Out[70]:
{'data': (68826112, False),
'descr': [('col1', '<i4'), ('col2', '<f4')],
'shape': (3,),
'strides': None,
'typestr': '|V8',
'version': 3}
In [71]: x['col2'].__array_interface__
Out[71]:
{'data': (68826116, False),
'descr': [('', '<f4')],
'shape': (3,),
'strides': (8,),
'typestr': '<f4',
'version': 3}
das zweite Array zeigt auf den gleichen Datenpuffer, aber 4 Bytes weiter entlang (der erste col2
-Wert). In der Tat ist es eine Ansicht.
(np.transpose
ist eine weitere Funktion, die nicht über die dtype
Grenze funktioniert.)
===================
Hier ist der Code für drop_fields
(zusammengefasst):
In [74]: from numpy.lib import recfunctions # separate import statement
In [75]: recfunctions.drop_fields??
def drop_fields(base, drop_names, usemask=True, asrecarray=False):
.... # define `drop_descr function
newdtype = _drop_descr(base.dtype, drop_names)
output = np.empty(base.shape, dtype=newdtype)
output = recursive_fill_fields(base, output)
return output
recursive_fill_fields
hat einen Namen von Namensfeld zu kopieren, und in der Lage ist dtypes zu behandeln, die Felder innerhalb Felder (rekursiven Teil) definieren.
In [81]: recfunctions.drop_fields(x, 'col1')
Out[81]:
array([(3.0,), (2.0,), (1.0,)],
dtype=[('col2', '<f4')])
In [82]: x[['col2']] # multifield selection that David suggests
Out[82]:
array([(3.0,), (2.0,), (1.0,)],
dtype=[('col2', '<f4')])
In [83]: x['col2'] # single field view
Out[83]: array([ 3., 2., 1.], dtype=float32)
drop_field
erzeugt ein ähnliches Ergebnis wie die Indizierung, die Mehrfelder @ David vorschlägt. Diese Multi-Indizierung ist jedoch nur wenig entwickelt, wie Sie sehen werden, wenn Sie irgendeine Art von Zuweisung versuchen.
Wie in der Antwort gezeigt, können Sie eine Teilmenge der dtype-Namen anzeigen. Es ist kein echtes Löschen. Es gibt auch eine Bibliothek von recfuncs, die eine Löschkopie implementieren könnte. – hpaulj
numpy.lib.recfunctions.drop_fields – hpaulj
@hpaulj, danke für den Kommentar, gut zu wissen es gibt eine externe Bibliothek dafür. Aber ist es nicht seltsam, dass so eine grundlegende Operation fehlschlägt? Nur ein einfaches Array 'x = numpy.zeros (3, dtype = {'names': ['col1', 'col2'], 'formats': ['i4', 'f4']})' kann nicht löschen a Spalte mit 'numpy.delete (x, 0,1)'. Was ist der Grund für dieses Problem, irgendwelche Ideen? –