Провел некоторые проверки синхронизации для 3 методов, упомянутых в других ответах.
fri =pd.DataFrame (columns =['security', 'price'], index = range(3), data =[['a',2],['b',4],['c',6]] )
sat =pd.DataFrame (columns =['security', 'price'], index = range(2), data =[['a',3],['c',5]] )
In [90]: %timeit out = sat.merge(fri, how='outer', on=['security', 'price']).drop_duplicates()
5.19 ms ± 150 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [91]: %timeit result_1 = pd.concat([sat,fri],ignore_index=True).drop_duplicates(subset=['security'], keep='first')
1.82 ms ± 26.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [92]: %timeit result_2 = pd.concat([sat, fri[~fri.security.isin(sat.security)]], ignore_index=True)
1.19 ms ± 113 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [93]: %timeit out = sat.merge(fri, how='outer', on=['security', 'price']).drop_duplicates()
5.02 ms ± 181 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Похоже, что фильтрация, а затем конкатенация - самая быстрая, тогда как concat и дедупликация не так уж и плохи. Слияние довольно медленное по сравнению.