Ich versuche herauszufinden, wann ich verschiedene Auswahlmethoden in Pandas DataFrame verwenden kann. Insbesondere suche ich nach skalaren Werten. Ich höre oft ix
wird allgemein empfohlen. Aber in Pandas-Dokumentation
Es wird empfohlen, at
und iat
für den schnellen Zugriff auf skalare Werte zu verwenden:
Since indexing with [] must handle a lot of cases (single-label access, slicing, boolean indexing, etc.), it has a bit of overhead in order to figure out what you’re asking for. If you only want to access a scalar value, the fastest way is to use the
bei and iat methods, which are implemented on all of the data structures.
Also würde ich annehmen, dass iat
schneller sein sollte, um einzelne Zellen zu bekommen und zu setzen. Nach einigen Tests haben wir jedoch festgestellt, dass ix
für das Lesen von Zellen vergleichbar oder schneller ist, während iat
viel schneller für das Zuweisen von Werten zu Zellen ist.
Ist dieses Verhalten überall dokumentiert? Ist es immer so und warum passiert das? Muss es etwas mit der Rückgabe oder Kopie tun? Ich würde mich freuen, wenn jemand diese Frage beleuchten und erklären könnte, was empfohlen wird, um Zellwerte zu bekommen und festzulegen und warum.
Hier sind einige Tests mit Pandas (Version 0.15.2).
Um sicherzustellen, dass dieses Verhalten kein Bug dieser Version ist, habe ich es auch auf 0.11.0 getestet. Ich gebe die Ergebnisse nicht, aber der Trend ist genau der gleiche - ix being much faster for getting, and iat for setting individual cells
.
Pandas macht ziemlich interessante Dinge mit den Indexierungsklassen . Ich glaube nicht, dass ich in der Lage bin, einen einfachen Weg zu beschreiben, um zu wissen, was ich verwenden soll, aber ich kann einen Einblick in die Implementierung geben.
DataFrame#ix
ist ein _IXIndexer
, die keine eigenen __getitem__
oder __setitem__
. Diese beiden Methoden sind wichtig, da sie steuern, wie auf Werte mit Pandas zugegriffen wird. Da _IXIndexer
diese Methoden nicht als Superklasse _NDFrameIndexer
's werden stattdessen verwendet.
Weitere Informationen zum Thema _NDFrameIndexer
__getitem__
zeigt, dass es relativ einfach ist und in einigen Fällen die in % co_de enthaltene Logik umschließt % Dann ist get_value
für einige Szenarien fast so schnell wie __getitem__
.
get_value
s _NDFrameIndexer
ist anders Geschichte. Zuerst sieht es einfach aus, aber die zweite Methode, die es aufruft, ist __setitem__
was für die meisten Szenarien eine Menge Arbeit bedeutet.
Diese Information legt nahe, dass Aufrufe zum Abrufen von Werten mit _setitem_with_indexer
im besten Fall durch ix
begrenzt sind und Aufrufe zum Festlegen von Werten mit get_value
einen Kern-Committer zur Erklärung benötigen.
Nun zu ix
, das ein DataFrame#iat
, das auch nicht seine eigene _iAtIndexer
oder% co_de deklariert Damit fällt% zurück in die Superklasse __getitem__
Implementierung .
__setitem__
hat eine einfache _ScalarAccessIndexer
Implementierung es erfordert eine Schleife, um den Schlüssel in das richtige Format zu konvertieren. Die zusätzliche Schleife fügt zusätzliche Verarbeitungszeit hinzu, bevor _ScalarAccessIndexer
aufgerufen wird.
__getitem__
hat auch eine ziemlich einfache get_value
Implementierung, die den Schlüssel konvertiert, den die Parameter _ScalarAccessIndexer
benötigen, bevor der Wert gesetzt wird.
Diese Information deutet darauf hin, dass Aufrufe zum Abrufen von Werten mit __setitem__
durch set_value
sowie durch ein for loop . Einstellungswerte mit iat
werden hauptsächlich durch Aufrufe von get_value
begrenzt. Das Abrufen von Werten mit iat
hat also einen gewissen Mehraufwand, während das Setzen von ihnen einen geringeren Overhead hat.
TL; DR
Ich glaube, Sie verwenden den richtigen Accessor für einen set_value
Index basierend auf der Dokumentation, aber ich denke nicht, dass das der schnellste ist. Die beste Leistung kann mit iat
und Int64Index
direkt gefunden werden, aber sie erfordern eine zusätzliche Tiefe an Wissen darüber, wie Pandas DataFrames implementiert werden.
Hinweise
Es ist erwähnenswert, dass in der Dokumentation zu Pandas erwähnt wird, dass get_value
und set_value
veraltet sind, was meiner Meinung nach get_value
statt.
Beispiele
Um den Unterschied in der Leistung mit ein paar Indexern zu zeigen (inklusive direktem Aufruf von set_value
und iget_value
) habe ich dieses Skript gemacht:
get_value
:
Ausgabe:
%Vor%