Ich verbinde zwei Tabellen mit Daten von zwei Systemen. Eine einfache Pandas Merge zwischen zwei df wird nicht kompliziertere Regeln zu ehren (es sei denn, ich verwende es falsch, verstehe nicht, die Prozess-Merge implementiert - sehr möglich).Was ist eine effizientere Möglichkeit, Zeilen aus DataFrames Zeile für Zeile mit Bedingungen zusammenzuführen?
Ich habe zusammengeschustert eine Spielzeug Lösung, die mich zwei df die mit itertuples
entpacken können, validieren Einstimmungen basierend auf Werten, und dann einpacken in einem Datenrahmen:
df1: df2:
A X B Y
0 1 10 0 2 10
1 5 15 1 4 15
2 6 15
.
df1 = pd.DataFrame(data1,columns=['A','X'])
df2 = pd.DataFrame(data2,columns=['B','Y'])
df3 = pd.DataFrame(index=['A','X','B','Y'])
i = -1
for rowA in df1.itertuples(index=False):
i += 1
for rowB in df2.itertuples(index=False):
A,X = rowA
B,Y = rowB
if (B > A) & (X==Y):
df3[i] = list(rowA+rowb)
else:
continue
print(df3.transpose())
.
A X B Y
0 1 10 2 10
1 5 15 6 15
Mein naiver Ansatz ist ineffizient
Die verschachtelte for()
Schleife ineffizient ist, weil ich für jeden Eintrag von data1 über Daten2/df2 Iterieren bin. Sobald ich eine gute Übereinstimmung mit data2/df2 gefunden habe, sollte die Zeile entfernt werden.
// UPDATE (zeigt den Ursprung meiner Frage)
Ein Beispiel für die Art von Daten, die ich mit verschmilzt zwei unabhängigen Systemen gerade arbeitete, die keine Schlüssel oder andere serialisierten IDs gemeinsam nutzen. Da ich keine exakte Übereinstimmung herstellen kann, muss ich mich auf logische/arithmetische Operationen und den Eliminierungsprozess verlassen.
Im folgenden Beispiel schlägt eine einfache pandas.merge
auf Line3, weil die Time1 < Time2.
Time1, Total1 ... Time2, Total2, error
1, 2017-02-19 08:03:00, 15.00 ... 2017-02-19 08:02:00, 15.00, 0
2, 2017-02-19 08:28:00, 33.00 ... 2017-02-19 08:27:00, 33.00, 0
3, 2017-02-19 08:40:00, 20.00 ... 2017-02-19 10:06:00, 20.00, 1
4, 2017-02-19 10:08:00, 20.00 ... 2017-02-19 10:16:00, 20.00, 1
[...]
Was passieren soll, ist so etwas wie dieses:
Time1, Total1 ... Time2, Total2, error
1, 2017-02-19 08:03:00, 15.00 ... 2017-02-19 08:02:00, 15.00, 0
2, 2017-02-19 08:28:00, 33.00 ... 2017-02-19 08:27:00, 33.00, 0
3, 2017-02-19 08:40:00, 20.00 ... NaN, NaN, NaN
4, 2017-02-19 10:08:00, 20.00 ... 2017-02-19 10:06:00, 20.00, 0
[...]
// UPDATE2 ich auf mehrere Permutationen von merge_asof()
und join()
in Antworten empfohlen gearbeitet habe. Jede Methode wurde auch so sortiert, wie es von Dokumenten angewiesen wurde. Angenommen, ich habe jede korrekt implementiert sind folgende Prozent True
Streichhölzer der Regeln ((time1> = time2) & (Total1 == Total2) von 53 Datensätze) in meinem Test-Set jeweils drei Methoden:
| type | 'date' | 'total' | both |
|-----------------------|----------|-----------|--------|
| merg_asof sort (time) | .7924 | .9245 | .7169 |
| merg_asof (time,total)| .7735 | .6981 | .6226 |
| intertup (time,total) | .8301 | .8301 | .8301 |
| join ind (time) | na | na | na |
Die Join benötigt einen gemeinsamen Schlüssel, richtig? Die on
Klausel in der Dokumentation besagt, "Spalte (n) im Aufrufer, um auf den Index in anderen beizutreten, andernfalls verbindet Index-on-Index. Wenn mehrere Spalten angegeben, muss die übergebene DataFrame einen MultiIndex haben."
Ich versuchte join
mit einem Multi-Index von (Zeit, insgesamt) und nur (Zeit). Das Problem ist, die Join Clobbers, was auch immer Sie beitreten. Es bleibt nichts mehr übrig, um die Fehleranalyse durchzuführen, da diese Indizes zu einem zusammengeführt werden.
Meine naive intertuple
Lösung (oben) produziert nur perfekte Übereinstimmungen, aber die Lösung braucht noch einen Sammler für verpasste Übereinstimmungen.
ich diese Frage mehrmals gelesen habe und ich versuche immer noch zu verstehen, wo Dinge wie "total" kommen von. Angesichts Ihrer ursprünglichen (vor dem Update) Frage würde ich einfach etwas tun wie 'pd.merge_asof (df1, df2, linkes_on = 'A', right_on = 'B', left_by = 'X', right_by = 'Y', allow_exact_matches = Falsch, Richtung = 'vorwärts') '. Beachten Sie, dass der 'direction' Parameter erst nach Pandas 0,20.0 erscheint, also müssen Sie Pandas aus der Quelle bauen oder für den Moment fest sitzen. – chrisaycock
@chrisaycock, du musst deine Vorstellungskraft ein wenig benutzen, um die Beziehung zwischen meinem naiven Algorithmus und den ursprünglichen Daten zu verstehen, die ich oben kurz umschreibe. Total war genau das - die Summe einer einzelnen Transaktion, die sich zwischen nicht integrierten Transaktionssystemen ausbreitet. Um meinen Code zu vereinfachen, wählte ich A/B als geordnet und X/Y als Übereinstimmung. 'merge_asof()' kam bei meinen Suchen zuvor nicht vor. Der 'direction' Parameter ist sehr wichtig, und ich habe gerade den' tolerance' Parameter bemerkt, machen 'merge_asof' einen großen Kandidaten für eine Lösung. Weitere Tests – xtian