Pandas hat einige ziemlich interessante Dinge mit dem indexing classes. Ich glaube nicht, dass ich in der Lage bin, einen einfachen Weg zu beschreiben, den ich verwenden könnte, aber ich kann einige Einblicke in die Implementierung geben.
DataFrame#ix
ist ein _IXIndexer
, die nicht über ein eigenes __getitem__
oder __setitem__
erklären. Diese beiden Methoden sind wichtig, da sie steuern, wie auf Werte mit Pandas zugegriffen wird. Da _IXIndexer
diese Methoden nicht deklariert, werden die super class _NDFrameIndexer
stattdessen verwendet.
Weitere Graben auf der _NDFrameIndexer
's __getitem__
zeigt, dass es relativ einfach ist und in einigen Fällen die Logik umschließt, die in get_value
gefunden wird. Dann ist __getitem__
für einige Szenarien so schnell wie get_value
.
_NDFrameIndexer
's __setitem__
ist eine andere Geschichte. Zunächst sieht es einfach aus, aber die zweite Methode, die es aufruft, ist _setitem_with_indexer
, die für die meisten Szenarien eine beträchtliche Menge Arbeit leistet.
Diese Daten lassen darauf schließen, dass die Werte Anrufe erhalten mit ix
werden von get_value
im besten Fall begrenzt und ruft Werte setzen ix
wäre einen Kern Committer nehmen zu erklären. Jetzt
für DataFrame#iat
welches ein _iAtIndexer
die auch nicht seine eigene __getitem__
oder __setitem__
dafür fallen in seine Superklasse nicht erklären zurück _ScalarAccessIndexer
‚s Umsetzung.
_ScalarAccessIndexer
hat eine simple __getitem__
Implementierung, aber es erfordert eine Schleife, um den Schlüssel in das richtige Format zu konvertieren. Die zusätzliche Schleife fügt vor dem Aufruf von get_value
zusätzliche Verarbeitungszeit hinzu.
_ScalarAccessIndexer
hat auch eine ziemlich simple __setitem__
Implementierung, die den Schlüssel konvertiert die Parameter set_value
erfordert, bevor Sie den Wert festlegen.
Diese Information legt nahe, dass Aufrufe zum Abrufen von Werten unter Verwendung von iat
durch get_value
sowie for loop begrenzt sind. Einstellwerte mit iat
werden hauptsächlich durch Aufrufe an set_value
begrenzt. Werte mit iat
zu erhalten, hat also einen gewissen Overhead, während das Setzen von diesen einen geringeren Overhead hat.
TL; DR
Ich glaube, Sie die richtige Accessor verwenden für einen Int64Index
Index für die Dokumentation basiert, aber ich glaube nicht, das bedeutet, dass es die am schnellsten ist. Die beste Leistung kann unter Verwendung von get_value
und set_value
direkt gefunden werden, aber sie erfordern eine zusätzliche Tiefe an Wissen, wie Pandas DataFrames implementiert werden.
Hinweise
Es ist erwähnenswert, dass die Dokumentation auf Pandas erwähnt, dass get_value
und set_value
sind veraltet, die ich glaube, gemeint war iget_value
anstatt zu sein.
Beispiele
Um den Unterschied in der Leistung mit wenigen Indexer zu zeigen (einschließlich get_value
und set_value
direkt aufrufen) Ich habe dieses Skript:
example.py
:
import timeit
def print_index_speed(stmnt_name, stmnt):
"""
Repeatedly run the statement provided then repeat the process and take the
minimum execution time.
"""
setup = """
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.rand(1000,2),columns = ['A','B'])
idx = 0
"""
minimum_execution_time = min(
timeit.Timer(stmnt, setup=setup).repeat(5, 10))
print("{stmnt_name}: {time}".format(
stmnt_name=stmnt_name,
time=round(minimum_execution_time, 5)))
print_index_speed("set ix", "for i in range(1000): df.ix[i, 'A'] = 1")
print_index_speed("set at", "for i in range(1000): df.at[i, 'A'] = 2")
print_index_speed("set iat", "for i in range(1000): df.iat[i, idx] = 3")
print_index_speed("set loc", "for i in range(1000): df.loc[i, 'A'] = 4")
print_index_speed("set iloc", "for i in range(1000): df.iloc[i, idx] = 5")
print_index_speed(
"set_value scalar",
"for i in range(1000): df.set_value(i, idx, 6, True)")
print_index_speed(
"set_value label",
"for i in range(1000): df.set_value(i, 'A', 7, False)")
print_index_speed("get ix", "for i in range(1000): tmp = df.ix[i, 'A']")
print_index_speed("get at", "for i in range(1000): tmp = df.at[i, 'A']")
print_index_speed("get iat", "for i in range(1000): tmp = df.iat[i, idx]")
print_index_speed("get loc", "for i in range(1000): tmp = df.loc[i, 'A']")
print_index_speed("get iloc", "for i in range(1000): tmp = df.iloc[i, idx]")
print_index_speed(
"get_value scalar",
"for i in range(1000): tmp = df.get_value(i, idx, True)")
print_index_speed(
"get_value label",
"for i in range(1000): tmp = df.get_value(i, 'A', False)")
Ausgang :
set ix: 0.9918
set at: 0.06801
set iat: 0.08606
set loc: 1.04173
set iloc: 1.0021
set_value: 0.0452
**set_value**: 0.03516
get ix: 0.04827
get at: 0.06889
get iat: 0.07813
get loc: 0.8966
get iloc: 0.87484
get_value: 0.04994
**get_value**: 0.03111
Ich denke, die get_value() und set_value() ist schneller – HYRY
Interessant, um die relativen Unterschiede zu beachten. Mit Pandas 0.14.1 erhalte ich die folgenden Ergebnisse: 1) 10 Schleifen, das Beste aus 3: 108 ms pro Schleife 2) 100 Schleifen, das Beste aus 3: 12,1 ms pro Schleife 3) 100 Schleifen, das Beste aus 3: 5,55 ms pro Schleife 4) 100 Schleifen, best of 3: 9,43 ms pro Schleife – Alexander
Sieht aus wie iat zum Erhalten hat sich in den letzten Versionen erheblich verbessert. Mit Pandas 0.19.1 sehe ich immer noch ix schneller als iat für die letzten 2 Timings, aber gerade noch. Die obigen Ergebnisse sind 5,31 vs 19,4 (in Version 0.15.2), aber ich sehe 6.01 vs 7.16 (in Version 0.19.1). – JohnE