[PYTHON] Geschwindigkeitsvergleich beim Umschalten nach Gruppen nach Pandas

Einführung

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.

Umgebung

--OS Name Microsoft Windows 10 Home

Verfahren

Datenaufbereitung

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})

image.png

Experiment

Diesmal habe ich versucht, nach zwei kategorialen Variablen zu gruppieren.

Methode 1

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)

Methode 2

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)

Methode 3

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)

Methode 4

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)

Methode 5

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)

Ergebnis

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

abschließend

Verwenden Sie nicht "transform" (Gebot)

Recommended Posts

Geschwindigkeitsvergleich beim Umschalten nach Gruppen nach Pandas
Standardisieren Sie nach Gruppen mit Pandas
Vergleich der Stapelverarbeitungsgeschwindigkeit nach Sprache
Bearbeiten von Strings mit Pandas gruppieren nach
Feature-Generierung mit Pandas gruppieren nach
Geschwindigkeitsvergleich bei der Suche mit mehreren Schlüsseln in Pandas (MultiIndex vs Others)
Bei to_csv mit Pandas wurde es Zeile für Zeile
Nach Pandas sortieren
Geschwindigkeitsvergleich jeder Sprache nach der Monte-Carlo-Methode