Versuchen Sie, diese für sich selbst:Warum ist DataFrame.loc [[1]] 1.800x langsamer als df.ix [[1]] und 3.500x als df.loc [1]?
import pandas as pd
s=pd.Series(xrange(5000000))
%timeit s.loc[[0]] # You need pandas 0.15.1 or newer for it to be that slow
1 loops, best of 3: 445 ms per loop
aktualisieren: die a legitimate bug in pandas ist, die wahrscheinlich in 0.15.1 im August 2014 oder so eingeführt wurde. Workarounds: Warte auf eine neue Version, während du eine alte Version von Pandas verwendest; Holen Sie sich einen topaktuellen Entwickler. Version von GitHub; manuell eine einzeilige Änderung in Ihrer Version pandas
; vorübergehend .ix
anstelle von .loc
verwenden.
Ich habe einen Datenrahmen mit 4,8 Millionen Zeilen und eine einzelne Zeile auswählen .iloc[[ id ]]
Verwendung (mit einem Einzelelement-Liste) dauert 489 ms, fast eine halbe Sekunde, 1,800x-mal langsamer als die identische .ix[[ id ]]
und 3.500x mal langsamer als.iloc[id]
(die ID als Wert übergeben, nicht als Liste). Um fair zu sein, .loc[list]
dauert etwa die gleiche Zeit unabhängig von der Länge der Liste, aber ich möchte nicht verbringen 489 ms darauf, vor allem, wenn .ix
ist tausendmal schneller, und produziert identische Ergebnis. Es war mein Verständnis, dass .ix
langsamer sein sollte, oder?
Ich benutze Pandas 0.15.1. Das ausgezeichnete Tutorial auf Indexing and Selecting Data schlägt vor, dass .ix
ist irgendwie allgemeiner und vermutlich langsamer als .loc
und .iloc
. Konkret heißt das:
Wenn jedoch eine Achse integer ist, wird NUR Label-basierter Zugriff und nicht positionsabhängiger Zugriff unterstützt. In solchen Fällen ist es normalerweise besser, explizit zu sein und .iloc oder .loc zu verwenden.
Hier eine ipython Sitzung mit dem Benchmarks:
print 'The dataframe has %d entries, indexed by integers that are less than %d' % (len(df), max(df.index)+1)
print 'df.index begins with ', df.index[:20]
print 'The index is sorted:', df.index.tolist()==sorted(df.index.tolist())
# First extract one element directly. Expected result, no issues here.
id=5965356
print 'Extract one element with id %d' % id
%timeit df.loc[id]
%timeit df.ix[id]
print hash(str(df.loc[id])) == hash(str(df.ix[id])) # check we get the same result
# Now extract this one element as a list.
%timeit df.loc[[id]] # SO SLOW. 489 ms vs 270 microseconds for .ix, or 139 microseconds for .loc[id]
%timeit df.ix[[id]]
print hash(str(df.loc[[id]])) == hash(str(df.ix[[id]])) # this one should be True
# Let's double-check that in this case .ix is the same as .loc, not .iloc,
# as this would explain the difference.
try:
print hash(str(df.iloc[[id]])) == hash(str(df.ix[[id]]))
except:
print 'Indeed, %d is not even a valid iloc[] value, as there are only %d rows' % (id, len(df))
# Finally, for the sake of completeness, let's take a look at iloc
%timeit df.iloc[3456789] # this is still 100+ times faster than the next version
%timeit df.iloc[[3456789]]
Ausgang:
The dataframe has 4826616 entries, indexed by integers that are less than 6177817
df.index begins with Int64Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], dtype='int64')
The index is sorted: True
Extract one element with id 5965356
10000 loops, best of 3: 139 µs per loop
10000 loops, best of 3: 141 µs per loop
True
1 loops, best of 3: 489 ms per loop
1000 loops, best of 3: 270 µs per loop
True
Indeed, 5965356 is not even a valid iloc[] value, as there are only 4826616 rows
10000 loops, best of 3: 98.9 µs per loop
100 loops, best of 3: 12 ms per loop
Hinweis numpy geschaltet, dass '[[id]]' und '[id] mit' nicht gleichwertig sind. '[id]' gibt eine Serie zurück, aber '[[id]]' gibt einen einreihigen DataFrame zurück. – BrenBarn
@BrenBarn, ja, das erklärt den Unterschied für die '.ix': 141 μs vs. 270 μs. Aber warum ist '.loc [[id]]' so langsam? – osa