как выполнить внутреннее или внешнее объединение DataFrames с Pandas по не-упрощенному критерию

Даны два кадра данных, как показано ниже:

>>> import pandas as pd

>>> df_a = pd.DataFrame([{"a": 1, "b": 4}, {"a": 2, "b": 5}, {"a": 3, "b": 6}])
>>> df_b = pd.DataFrame([{"c": 2, "d": 7}, {"c": 3, "d": 8}])
>>> df_a
   a  b
0  1  4
1  2  5
2  3  6

>>> df_b
   c  d
0  2  7
1  3  8

мы хотели бы создать объединение в стиле SQL обоих фреймов данных, используя не упрощенные критерии, скажем, «df_b.c> df_a.a». Из того, что я могу сказать, покаmerge() безусловно, является частью решения, я не могу использовать его напрямую, так как он не принимает произвольные выражения для критериев «ВКЛ» (разве я что-то упустил?).

В SQL результаты выглядят так:

# inner join
sqlite> select * from df_a join df_b on c > a;
1|4|2|7
1|4|3|8
2|5|3|8

# outer join
sqlite> select * from df_a left outer join df_b on c > a;
1|4|2|7
1|4|3|8
2|5|3|8
3|6||

Мой текущий подход к внутреннему объединению состоит в том, чтобы получить декартово произведение df_a и df_b, добавив столбец «1» к обоим, затем используя merge () к столбцу «1», затем применив «c> a» критерии.

>>> import numpy as np
>>> df_a['ones'] = np.ones(3)
>>> df_b['ones'] = np.ones(2)
>>> cartesian = pd.merge(df_a, df_b, left_on='ones', right_on='ones')
>>> cartesian
   a  b  ones  c  d
0  1  4     1  2  7
1  1  4     1  3  8
2  2  5     1  2  7
3  2  5     1  3  8
4  3  6     1  2  7
5  3  6     1  3  8
>>> cartesian[cartesian.c > cartesian.a]
   a  b  ones  c  d
0  1  4     1  2  7
1  1  4     1  3  8
3  2  5     1  3  8

Что касается внешнего объединения, я не уверен в том, что лучше идти, пока я играл с получением внутреннего соединения, затем применяя отрицание критериев, чтобы получить все остальные строки, затем пытаясь редактировать это "отрицание". "установить на оригинал, но на самом деле это не работает.

редактировать, HYRY ответил на конкретный вопрос здесь, но мне нужно что-то более общее и более в рамках API Pandas, поскольку моим критерием объединения может быть что угодно, а не только это сравнение. Для externaljoin сначала я добавляю дополнительный индекс в «левую» сторону, который будет поддерживать себя после того, как я выполню внутреннее соединение:

df_a['_left_index'] = df_a.index

тогда мы делаем декартово и получаем внутреннее соединение:

cartesian = pd.merge(df_a, df_b, left_on='ones', right_on='ones')
innerjoin = cartesian[cartesian.c > cartesian.a]

затем я получаю дополнительные идентификаторы индекса в "df_a", которые нам понадобятся, и получаю строки из "df_a":

remaining_left_ids = set(df_a['_left_index']).\
                    difference(innerjoin['_left_index'])
remaining = df_a.ix[remaining_left_ids]

затем мы используем прямой concat (), который заменяет отсутствующие столбцы на «NaN» для левой стороны (я думал, что раньше этого не делалось, но, думаю, так и есть):

outerjoin = pd.concat([innerjoin, remaining]).reset_index()

Идея HYRY сделать декартову только по тем столбцам, с которыми нам нужно сравнивать, является в основном правильным ответом, хотя в моем конкретном случае это может быть немного сложно реализовать (обобщенно и все).

вопросов:

Как бы вы произвели «соединение» df_1 и df_2 на «c> a»? Вы бы использовали тот же подход «декартово произведение, фильтр» или есть какой-то лучший способ?

Как бы вы произвели «левое внешнее соединение»?

Ответы на вопрос(2)

Ваш ответ на вопрос