data1 = {
'alias_cd': ['12345', '12345', '12345'],
'country_cd': ['AU', 'AU', 'AU2'],
'pos_name': ['st1', 'Jh', 'Jh'],
'ts_allocated': [100, 100, 100],
'tr_id': ['None', 'None', 'None'],
'ty_name': ['E2E', 'E2E', 'E2E']
}
data2 = {
'alias_cd': ['12345', '12345'],
'country_cd': ['AU', 'AU3'],
'pos_name': ['st1', 'st2'],
'ts_allocated': [200, 100],
'tr_id': ['None', 'None'],
'ty_name': ['E2E', 'E2E']
}
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)
вывод должен быть
alias_cd country_cd pos_name ts_allocated tr_id ty_name etl_flag
1 12345 AU st1 200 None E2E U
2 12345 AU3 st2 100 None E2E D
3 12345 AU st1 100 None E2E I
4 12345 AU Jh 100 None E2E I
5 12345 AU2 Jh 100 None E2E I
Потому что:
Комбинация alias_cd и Country_cd действует как первичный ключ.
1. Если комбинация существует в df2 и df1 (12345 AU
), она будет помечена как «Обновить» в df2, а все соответствующие строки в df1 для той же комбинации будут отмечены как «Вставить». в приведенном выше примере для записей 12345 AU
в df2 будет etl_flag= «Обновить» и добавить записи для той же комбинации от df1 до df2 с etl_flag как «Вставить».
2.12345 AU3
существует в df2, но не в df1, поэтому в столбце etl_flag он будет помечен как «DELETE».
3. Любая новая комбинация, которая появляется в df1 и отсутствует в df2, будет помечена как «Вставка» в столбце etl_flag.
Как я могу достичь этого эффективно? Это то, что я пробовал, но он не дает правильного вывода:
df2['etl_flag'] = 'U'
to_insert = df1[~df1.apply(lambda x: (df2['alias_cd'] == x['alias_cd']) & (df2['country_cd'] == x['country_cd']), axis=1)]
to_insert['etl_flag'] = 'I'
df2 = pd.concat([df2, to_insert], ignore_index=True)
to_delete = df2[~df2.apply(lambda x: (df1['alias_cd'] == x['alias_cd']) & (df1['country_cd'] == x['country_cd']), axis=1)]
to_delete['etl_flag'] = 'D'
final_df = pd.concat([df2, to_delete], ignore_index=True)
final_df.sort_values(by=['alias_cd', 'country_cd'], inplace=True)
print(final_df[['alias_cd', 'country_cd', 'pos_name', 'ts_allocated', 'tr_id', 'ty_name', 'etl_flag']])
@mozway 12345/AU2 будет «I», потому что этого нет в df2, это новая комбинация.
Хорошо, значит, любая строка в df1
всегда будет иметь I
IIUC, вы можете сначала выполнить слияние слева-с включенным индикатором df2
, чтобы определить статус U/D, а затем конкат. df1
всегда получает I
:
# columns used as primary key
cols = ['alias_cd', 'country_cd']
out = pd.concat(
[df2.assign(etl_flag=df2.merge(df1[cols].drop_duplicates(),
on=cols, how='left', indicator=True)
['_merge'].map({'left_only': 'D', 'both': 'U'})
.values),
df1.assign(etl_flag='I')]
)
Выход:
alias_cd country_cd pos_name ts_allocated tr_id ty_name etl_flag
0 12345 AU st1 200 None E2E U
1 12345 AU3 st2 100 None E2E D
0 12345 AU st1 100 None E2E I
1 12345 AU Jh 100 None E2E I
2 12345 AU2 Jh 100 None E2E I
логика неясна, почему
12345/AU2
присвоенI
?