Этого можно добиться, используя melt, lambda, sort_values, drop_dulicates
, как показано ниже
df3 = df2.melt(id_vars = ['A', 'B', 'C'], var_name='date')
df3[['A', 'B']] = df3[['A', 'B']].astype(float)
df3['Diff'] = df3.apply(lambda row: abs(datetime.strptime(row['date'], '%Y-%m') - datetime.strptime(row['C'], '%Y-%m-%d')), axis=1)
df3.sort_values(['Diff'], ascending=[True], inplace=True)
df3.drop_duplicates(subset=['A', 'B', 'date'], keep='first', inplace=True)
df3.drop(['C', 'Diff'], 1, inplace=True)
df4 = df1.merge(df3, on=['A', 'B', 'date'], how='left')
, вывод равен
A B date value
0 1.0 1.0 2015-02 0.200
1 1.0 1.0 2015-03 0.120
2 2.0 2.0 2017-01 0.150
3 2.0 2.0 2017-02 0.245
, полный пример приведен ниже.
import pandas as pd
from datetime import datetime
df1 = pd.DataFrame(columns = ['A', 'B', 'date'])
df1.loc[len(df1)] = [1, 1, '2015-02']
df1.loc[len(df1)] = [1, 1, '2015-03']
df1.loc[len(df1)] = [2, 2, '2017-01']
df1.loc[len(df1)] = [2, 2, '2017-02']
df1[['A', 'B']] = df1[['A', 'B']].astype(float)
df2 = pd.DataFrame(columns = ['A', 'B', 'C', '2015-02', '2015-03', '2017-01', '2017-02'])
df2.loc[len(df2)] = [1, 1, '2013-07-01', 0.10, 0.22, 0.55, 0.77]
df2.loc[len(df2)] = [1, 1, '2015-01-01', 0.20, 0.12, 0.99, 0.125]
df2.loc[len(df2)] = [2, 2, '2016-12-01', 0.13, 0.15, 0.15, 0.245]
df2.loc[len(df2)] = [2, 2, '2016-01-01', 0.33, 0.1, 0.888, 0.64]
df3 = df2.melt(id_vars = ['A', 'B', 'C'], var_name='date')
df3[['A', 'B']] = df3[['A', 'B']].astype(float)
df3['Diff'] = df3.apply(lambda row: abs(datetime.strptime(row['date'], '%Y-%m') - datetime.strptime(row['C'], '%Y-%m-%d')), axis=1)
df3.sort_values(['Diff'], ascending=[True], inplace=True)
df3.drop_duplicates(subset=['A', 'B', 'date'], keep='first', inplace=True)
df3.drop(['C', 'Diff'], 1, inplace=True)
df4 = df1.merge(df3, on=['A', 'B', 'date'], how='left')
print(df4)