[PYTHON] Eine Geschichte, die Schwierigkeiten hatte, 3 Millionen ID-Daten in einer Schleife zu verarbeiten

Fortsetzung von Artikel von gestern

■ Zweck

Für jede der 3 Millionen IDs werden Daten im Wert von einem Monat erstellt Der Inhalt der Daten besteht aus einer erklärenden Variablen und einer objektiven Variablen. Mit anderen Worten, die Tabelle enthält drei Spalten: ID, erklärende Variable und objektive Variable. Die Anzahl der Datensätze beträgt 3 Millionen x 30 Tage - 90 Millionen

Zu diesem Zeitpunkt wurde für jede der 3 Millionen IDs eine einfache Regression der erklärenden Variablen und objektiven Variablen für 30 Tage durchgeführt. Ich möchte den Korrelationskoeffizienten, die Steigung und den p-Wert für jede ID als Ausgabe speichern.

■ Richtlinien

Regressiert in einer for-Schleife 3 Millionen IDs und speichert die Ergebnisse als Liste Kombinieren Sie schließlich die Listen zu einem Datenrahmen

■ Umgebung

EC2-Instanz (Ubuntu: r5d.4xlarge) JupyterLab 0.35.3

■ Herausforderungen

Extraktion mit df.loc [] mit ID als Index + Die Verarbeitung ist selbst bei Verwendung des Dask-Datenrahmens langsam (dauert 2 Monate).

■ Lösung

Eine Tabelle mit der folgenden Form

ID x y
01 x.xx y.yy
01 x.xx y.yy
・ ・ ・ ・ ・ ・ ・ ・ ・
01 x.xx y.yy
02 x.xx y.yy
02 x.xx y.yy
・ ・ ・ ・ ・ ・ ・ ・ ・
02 x.xx y.yy

In das folgende Formular konvertieren

ID monthly_x monthly_y
01 [x.xx, x.xx ,....] [y.yy, y.yy ,....]
02 [x.xx, x.xx ,....] [y.yy, y.yy ,....]
03 [x.xx, x.xx ,....] [y.yy, y.yy ,....]
04 [x.xx, x.xx ,....] [y.yy, y.yy ,....]
05 [x.xx, x.xx ,....] [y.yy, y.yy ,....]
06 [x.xx, x.xx ,....] [y.yy, y.yy ,....]

Der Umwandlungsfluss besteht aus den folgenden zwei Stufen

code1.py



import pandas as pd
#Ein Zustand, in dem eine Spalte, die das Datum darstellt, zum ursprünglichen Datenrahmen hinzugefügt wird (hier "Datum")._Der Spaltenname lautet
pivot_df = pd.pivot_table(df, index="ID",columns="date_")

Damit werden die Werte von x und y für jedes Datum horizontal gehalten.

code2.py



pivot_df["x"] = [list(pivot_df.x.loc[i,:]) for i in pivot_df.index]
pivot_df["y"] = [list(pivot_df.y.loc[i,:]) for i in pivot_df.index]

Dieser Prozess dauert ** ungefähr 0,2 ms ** pro ID, ** ungefähr 10 ~ 15 min ** mit 3 Millionen IDs (** starke Notation **)

Versuchen Sie, eine Regressionsverarbeitung für die konvertierte Tabelle durchzuführen Diese Regression verwendet eine robuste Regression unter Berücksichtigung der Ausreißer. (Informationen zur robusten Regression finden Sie hier [https://qiita.com/ryskiwt/items/43e9bbc895bb7d33cb17).) (Ich habe die Angewohnheit, den Bestimmungskoeffizienten R ^ 2 für eine robuste Regression abzuleiten, daher werde ich ihn zusammenfassen, wenn ich Zeit habe. Er ist geplant.)

code3.py


import statsmodels.api as sm

pivot_df["model"] = [sm.RLM(i, sm.add_constant(j)) for i,j in zip(pivot_df.x ,pivot_df.y)]
pivot_df["result"] = [i.fit() for i in pivot_df.model]

Mit dem obigen Code ** ca. 8,8 ms ** pro ID Wenn Sie das "Modell" nicht speichern und mit einem Liner arbeiten, ** ca. 7,9 ms ** pro ID Bisher insgesamt ** ca. 9ms ** pro ID

Im vorherigen Artikel dauerte es 1,7 Sekunden, um nur 1 ID zu extrahieren Selbst unter Einbeziehung der Regression wurde die Verarbeitungszeit auf 1/200 reduziert, und die Verarbeitungszeit wurde im Vergleich zu der Zeit bis zur Vorverarbeitung der Regression auf ** 1/10000 ** reduziert.

■ Fazit

** Stärkste Einschlussnotation ** Die Verarbeitungszeit für jede der 3 Millionen IDs wurde lächerlich berechnet, um ehrlich zu sein, mehr als ein Jahr, aber mit ein wenig Einfallsreichtum war es möglich, sie für ungefähr 8 Stunden zu drehen.

(Ich würde es begrüßen, wenn Sie mir andere gute Methoden beibringen könnten)

■ Zukunftspläne

In Bezug auf die Regression wurden in diesem Artikel lediglich StatsModels verwendet, aber der Bestimmungskoeffizient der robusten Regression kann (soweit ich weiß) nicht einfach aus einer Bibliothek wie StatsModels abgeleitet werden, sodass ein gewisser Einfallsreichtum erforderlich ist. Ich bin flauschig und denke, dass es schön wäre, wenn ich dies zusammenfassen könnte (~~ denke nur ~~)

Recommended Posts

Eine Geschichte, die Schwierigkeiten hatte, 3 Millionen ID-Daten in einer Schleife zu verarbeiten
Eine Geschichte über das Problem, 3 Millionen ID-Daten in einer Schleife zu verarbeiten
Eine Geschichte, von der ich bei np.where süchtig war
Eine Geschichte, die ich süchtig danach war, Lambda von AWS Lambda anzurufen.
Eine Geschichte, der ich nach der SFTP-Kommunikation mit Python verfallen war
Eine Geschichte, die Seaborn einfach, bequem und beeindruckt war
Eine Geschichte, die schrecklich war, wenn SELinux richtig deaktiviert war
So schreiben Sie einen Test für die Verarbeitung mit BigQuery
Ein Python-Skript, das Oracle-Datenbankdaten in CSV konvertiert
[Python] Eine Geschichte, die in eine Rundungsfalle zu geraten schien
Die Geschichte, dass die Version von Python 3.7.7 nicht an Heroku angepasst wurde
Eine Geschichte, die Qiita unbedingt in einer Proxy-Umgebung sehen wollte
Die Geschichte, dass der Wachmann eingesperrt war, als das Labor auf IoT umgestellt wurde
Erstellt einen Dienst, mit dem Sie J-League-Daten durchsuchen können
Eine Geschichte, die von Azure Pipelines abhängig ist
Eine Geschichte, die ich süchtig danach war, eine Video-URL mit Tweepy zu bekommen
Eine Geschichte, die unter einem Unterschied im Betriebssystem litt, als sie versuchte, ein Papier zu implementieren