Ich glaube nicht, dass es ein schneller, einzeiliger Weg, um diese Art der Sache zu tun, aber ich glaube der beste Ansatz es auf diese Weise zu tun ist:
fügen Sie eine Spalte df1
mit dem am nächsten Tag aus der entsprechenden Gruppe df2
in
Anruf ein Standard-Merge auf diesen
Da die Größe Ihrer Daten zunimmt, kann diese Operation für den "nächsten Termin" ziemlich teuer werden, es sei denn, Sie tun etwas Hochentwickeltes. Ich verwende gerne den Code NearestNeighbor
von scikit-learn für diese Art von Dingen.
Ich habe einen Ansatz für diese Lösung zusammengestellt, der relativ gut skalieren sollte. Zuerst haben wir ein paar einfache Daten erzeugen können:
import pandas as pd
import numpy as np
dates = pd.date_range('2015', periods=200, freq='D')
rand = np.random.RandomState(42)
i1 = np.sort(rand.permutation(np.arange(len(dates)))[:5])
i2 = np.sort(rand.permutation(np.arange(len(dates)))[:5])
df1 = pd.DataFrame({'Code': rand.randint(0, 2, 5),
'Date': dates[i1],
'val1':rand.rand(5)})
df2 = pd.DataFrame({'Code': rand.randint(0, 2, 5),
'Date': dates[i2],
'val2':rand.rand(5)})
Lassen Sie uns diese Besuche:
>>> df1
Code Date val1
0 0 2015-01-16 0.975852
1 0 2015-01-31 0.516300
2 1 2015-04-06 0.322956
3 1 2015-05-09 0.795186
4 1 2015-06-08 0.270832
>>> df2
Code Date val2
0 1 2015-02-03 0.184334
1 1 2015-04-13 0.080873
2 0 2015-05-02 0.428314
3 1 2015-06-26 0.688500
4 0 2015-06-30 0.058194
Lassen Sie uns jetzt eine apply
Funktion schreiben, die eine Spalte des nächsten Datums df1
mit fügt Scikit-Learn:
from sklearn.neighbors import NearestNeighbors
def find_nearest(group, match, groupname):
match = match[match[groupname] == group.name]
nbrs = NearestNeighbors(1).fit(match['Date'].values[:, None])
dist, ind = nbrs.kneighbors(group['Date'].values[:, None])
group['Date1'] = group['Date']
group['Date'] = match['Date'].values[ind.ravel()]
return group
df1_mod = df1.groupby('Code').apply(find_nearest, df2, 'Code')
>>> df1_mod
Code Date val1 Date1
0 0 2015-05-02 0.975852 2015-01-16
1 0 2015-05-02 0.516300 2015-01-31
2 1 2015-04-13 0.322956 2015-04-06
3 1 2015-04-13 0.795186 2015-05-09
4 1 2015-06-26 0.270832 2015-06-08
Schließlich können wir diese zusammen mit einem einfachen Aufruf an pd.merge
:
0 zusammenführen
>>> pd.merge(df1_mod, df2, on=['Code', 'Date'])
Code Date val1 Date1 val2
0 0 2015-05-02 0.975852 2015-01-16 0.428314
1 0 2015-05-02 0.516300 2015-01-31 0.428314
2 1 2015-04-13 0.322956 2015-04-06 0.080873
3 1 2015-04-13 0.795186 2015-05-09 0.080873
4 1 2015-06-26 0.270832 2015-06-08 0.688500
Beachten Sie, dass Zeilen 0 und 1 beide übereinstimmten val2
; Dies wird erwartet, wenn Sie Ihre gewünschte Lösung beschreiben.
damit verbundene Frage: http://stackoverflow.com/questions/24614474/pandas-merge-on-name-and-closest-date – jakevdp
Hier ist eine bessere Antwort: http://stackoverflow.com/questions/21201618/pandas-merge-match-the-nearest-time-stamp-the-series-of-timestamps – jakevdp
@jakevdp: Danke, aber wie kann ich es mit der Zusammenführung von Code kombinieren? Soll ich zuerst "searchsorted" verwenden und dann "mask = idx> = 0 & ..." eingeben? –