Давайте начнем с import itertools
(мы будем использовать его).
Я создал тестовые фреймы данных следующим образом:
D1 = pd.DataFrame(data=[
[ 1, 0, 0, 0, 0, 91 ],
[ 0, 2, 0, 0, 0, 92 ],
[ 0, 0, 3, 0, 0, 93 ],
[ 0, 0, 0, 4, 0, 94 ],
[ 0, 0, 0, 0, 5, 95 ],
[ 0, 6, 0, 0, 0, 96 ],
[ 0, 0, 7, 0, 0, 97 ]], columns=list('ABCDEF'))
D2 = pd.DataFrame(data=[
[ 1, 71, 89 ],
[ 2, 72, 88 ],
[ 3, 73, 87 ],
[ 4, 74, 86 ],
[ 5, 75, 85 ],
[ 8, 76, 84 ]], columns=list('AXY'))
Как видите:
- D1 содержит столбцы «кандидатов на присоединение» A - E и один дополнительный столбец ( F ),
- D2 содержит один столбец объединения A и два дополнительных столбца ( X и Y ).
Тогда давайте определим функцию соединения:
def myJoin(df1, df2):
rows = itertools.product(df1.iterrows(), df2.iterrows())
df = pd.DataFrame(left.append(right.iloc[1:])
for (_, left), (_, right) in rows
if right.A in left.loc['A':'E'].tolist())
return df.reset_index(drop=True)
И единственное, что нужно сделать, это вызвать ее:
myJoin(D1, D2)
Результат:
A B C D E F X Y
0 1 0 0 0 0 91 71 89
1 0 2 0 0 0 92 72 88
2 0 0 3 0 0 93 73 87
3 0 0 0 4 0 94 74 86
4 0 0 0 0 5 95 75 85
Обратите внимание, что имена столбцов, взятые из обоих фреймов данных, должны быть уникальными , поэтому я исключил столбец A из D2 ( right.iloc [1:] ).
Редактировать
Представленная выше функция фактически внутренняя объединяет.Если вы хотите left join, тогда определите другую функцию join как:
def myJoin2(df1, df2):
res = []
for (_, left) in df1.iterrows():
found = False
for (_, right) in df2.iterrows():
if right.A in left.loc['A':'E'].tolist():
res.append(left.append(right.iloc[1:]))
found = True
if not found:
res.append(left)
df = pd.DataFrame(res)
return df.reset_index(drop=True)
и вызовите ее:
myJoin2(D1, D2)
, получив результат:
A B C D E F X Y
0 1.0 0.0 0.0 0.0 0.0 91.0 71.0 89.0
1 0.0 2.0 0.0 0.0 0.0 92.0 72.0 88.0
2 0.0 0.0 3.0 0.0 0.0 93.0 73.0 87.0
3 0.0 0.0 0.0 4.0 0.0 94.0 74.0 86.0
4 0.0 0.0 0.0 0.0 5.0 95.0 75.0 85.0
5 0.0 0.0 0.0 0.0 5.0 95.0 76.0 84.0
6 0.0 6.0 0.0 0.0 0.0 96.0 NaN NaN
7 0.0 0.0 7.0 0.0 0.0 97.0 NaN NaN
Недостатком является то, что значения int преобразуются в float , но NaN также является частным случаем float ,этого нельзя избежать.