vectorial merge:
df = pd.DataFrame({'col1':["23.11.2020", "25.05.2021", "26.05.2021", "26.05.2022", "26.05.2018"]})
s = pd.Series(pd.to_datetime(special_dates, dayfirst=True)).sort_values()
df['col1'] = pd.to_datetime(df['col1'], dayfirst=True)
df = df.sort_values(by='col1').reset_index()
df['col2'] = (pd.merge_asof(df, s.rename('other'),
left_on='col1', right_on='other',
direction='forward', allow_exact_matches=True)['other']
.sub(df['col1']).dt.days
)
df['col3'] = (pd.merge_asof(df, s.rename('other'),
left_on='col1', right_on='other',
direction='backward', allow_exact_matches=True)['other']
.rsub(df['col1']).dt.days
)
df = df.set_index('index').sort_index()
output:
col1 col2 col3
index
0 2020-11-23 0.0 0.0
1 2021-05-25 7.0 5.0
2 2021-05-26 6.0 6.0
3 2022-05-26 NaN 359.0
4 2018-05-26 912.0 NaN
older answer (misunderstanding of question)
You can use numpy
broadcasting:
special_dates = ["25.11.2020", "23.11.2020", "01.06.2021", "20.05.2021"]
df['col1'] = pd.to_datetime(df['col1'], dayfirst=True)
a = pd.to_datetime(special_dates, dayfirst=True).to_numpy()
out = (df
.join(pd.DataFrame((a-df['col1'].to_numpy()[:,None]),
index=df.index,
columns=range(1, len(special_dates)+1))
.add_prefix('date_')
.clip('0')
#.apply(lambda c: c.dt.days) # uncomment for days as int
)
)
output:
col1 date_1 date_2 date_3 date_4
0 2020-11-23 2 days 0 days 190 days 178 days
1 2021-05-25 0 days 0 days 7 days 0 days
output as integers (last line uncommented):
col1 date_1 date_2 date_3 date_4
0 2020-11-23 2 0 190 178
1 2021-05-25 0 0 7 0
Variant with dates as headers:
out = (df
.join(pd.DataFrame((a-df['col1'].to_numpy()[:,None]),
index=df.index,
columns=special_dates)
.clip('0')
.apply(lambda c: c.dt.days)
)
)
output:
col1 25.11.2020 23.11.2020 01.06.2021 20.05.2021
0 2020-11-23 2 0 190 178
1 2021-05-25 0 0 7 0