Wenn Sie mit Tischdaten in Pandas spielen, möchten Sie möglicherweise die Zeilenrichtung für jede Kategorie verschieben (z. B. möchten Sie für jeden Benutzer einen Zeitraum mit Zeitreihendaten verschieben). Wenn Sie Daten mit Pandas nach Gruppen transformieren möchten, können Sie dies ehrlich mit groupby (). Transform
tun. Der Gruppierungsprozess nimmt jedoch viel Zeit in Anspruch. Lassen Sie uns also untersuchen, wie lange es auf verschiedene Weise dauern wird.
--OS Name Microsoft Windows 10 Home
Ich habe vorerst 10 Millionen Zeilen vorbereitet. Es gibt 7 Variablen, 5 sind geeignete Zahlen und 2 sind kategoriale Variablen (X, Y), die 10 Kategorien bzw. 4 Kategorien sind.
import numpy as np
import pandas as pd
x = np.arange(10_000_000)
y = np.tile(np.arange(10), int(len(x)/10))
z = np.tile(np.arange(4), int(len(x)/4))
df = pd.DataFrame({"a": x, "b": x, "c": x, "d": x, "e": x, "Y":y, "Z": z})
Diesmal habe ich versucht, nach zwei kategorialen Variablen zu gruppieren.
Dies ist auf einfache Weise die Grundlage für den Vergleich.
%%timeit -n 1 -r 10
s = df.groupby(["Y", "Z"])["a"].transform(lambda x: x.shift(1))
# 3.25 s ± 107 ms per loop (mean ± std. dev. of 10 runs, 1 loop each)
Dies ist eine Methode zum Kombinieren von Variablen, die im Voraus gruppiert werden sollen. Es ist schneller, aber das Beitreten dauert länger, sodass es für häufige Gruppierungen geeignet ist.
dg = df.copy()
dg["YZ"] = dg["Y"].astype("str") + dg["Z"].astype("str")
# 13.7 s ± 964 ms per loop (mean ± std. dev. of 10 runs, 1 loop each)
%%timeit -n 1 -r 10
s = dg.groupby(["YZ"])["a"].transform(lambda x: x.shift(1))
# 2.62 s ± 25.1 ms per loop (mean ± std. dev. of 10 runs, 1 loop each)
Dies ist eine Methode zum Erstellen und Ausführen einer Numpy-Shift-Funktion anstelle der Pandas-Shift-Methode. Es scheint, dass sich die Geschwindigkeit nicht so sehr ändert.
Referenz: Python - Shift-Elemente in einem Numpy-Array - Stapelüberlauf
def shift2(arr, num):
result = np.empty(arr.shape[0])
if num > 0:
result[:num] = np.nan
result[num:] = arr[:-num]
elif num < 0:
result[-num:] = np.nan
result[:num] = arr[-num:]
else:
result = arr
return result
%%timeit -n 1 -r 10
s = df.groupby(["Y", "Z"])["a"].transform(lambda x: shift2(x, 1))
# 3.2 s ± 15.1 ms per loop (mean ± std. dev. of 10 runs, 1 loop each)
Es ist eine Methode, um jede Gruppe durch Iteration nach der Gruppierung zu verarbeiten. Selbst mit dieser Methode ändert sich die Geschwindigkeit nicht so stark, und es kann eine flexiblere Verarbeitung angewendet werden, so dass dies eine sehr beliebte Methode ist.
%%timeit -n 1 -r 10
l = [group["a"].shift(1) for _, group in df.groupby(["Y", "Z"])]
dh = pd.concat(l, axis=0).sort_index()
# 3.12 s ± 14.4 ms per loop (mean ± std. dev. of 10 runs, 1 loop each)
Tatsächlich ist "transformieren" nicht notwendig. Dies ist der schnellste.
%%timeit -n 1 -r 10
s = df.groupby(["Y", "Z"])["a"].shift(1)
# 983 ms ± 10.9 ms per loop (mean ± std. dev. of 10 runs, 1 loop each)
Methode | Erläuterung | time(per loop) |
---|---|---|
Methode 1 | Standardmethode | 3.25 s ± 0.107 s |
Methode 2 | Pre-Join | 2.62 s ± 0.0251 s |
Methode 3 | numpy shift | 3.2 s ± 0.0151 s |
Methode 4 | Wiederholung | 3.12 s ± 0.0144 s |
Methode 5 | Keine Transformation | 0.983 s ± 0.0109 s |
Verwenden Sie nicht "transform" (Gebot)
Recommended Posts