Объединение Pandas данных на основе логической функции - PullRequest
3 голосов
/ 18 февраля 2020

Я ищу эффективный способ объединения двух pandas фреймов данных на основе функции, которая принимает в качестве входных столбцов оба фрейма данных и возвращает True или False. Например, предположим, у меня есть следующие «таблицы»:

import pandas as pd

df_1 = pd.DataFrame(data=[1, 2, 3])
df_2 = pd.DataFrame(data=[4, 5, 6])


def validation(a, b):
    return ((a + b) % 2) == 0

Я хотел бы объединить df1 и df2 в каждой строке, где сумма первого столбца является четным числом. Результирующая таблица будет иметь вид

       1 5
df_3 = 2 4
       2 6
       3 5

. Пожалуйста, подумайте об этом, как об общей проблеме, а не как о задаче возврата только df_3. Решение должно принимать любую функцию, которая проверяет комбинацию столбцов и возвращает True или False.

THX Lazloo

Ответы [ 3 ]

2 голосов
/ 18 февраля 2020

Вы можете сделать с merge по четности:

(df_1.assign(parity=df_1[0]%2)
     .merge(df_2.assign(parity=df_2[0]%2), on='dummy')
     .drop('parity', axis=1)
)

, вывод:

   0_x  0_y
0    1    5
1    3    5
2    2    4
3    2    6
1 голос
/ 18 февраля 2020

Вы можете использовать широковещательную передачу или функции outer, чтобы сравнить все строки. Вы столкнетесь с проблемами, когда длина станет большой.

import pandas as pd
import numpy as np

def validation(a, b):
    """a,b : np.array"""
    arr = np.add.outer(a, b)     # How to combine rows
    i,j = np.where(arr % 2 == 0) # Condition

    return pd.DataFrame(np.stack([a[i], b[j]], axis=1))

validation(df_1[0].to_numpy(), df_2[0].to_numpy())

   0  1
0  1  5
1  2  4
2  2  6
3  3  5

В этом конкретном случае вы можете использовать тот факт, что четные числа поддерживают четность при добавлении к четным числам, а нечетные числа изменяют четность при добавлении к нечетным числам, поэтому определите этот столбец и объедините его это.

df_1['parity'] = df_1[0]%2
df_2['parity'] = df_2[0]%2

df_3 = df_1.merge(df_2, on='parity')

   0_x  parity  0_y
0    1       1    5
1    3       1    5
2    2       0    4
3    2       0    6
0 голосов
/ 18 февраля 2020

Это базовое c решение, но не очень эффективное, если вы работаете с большими фреймами данных

df_1.index *= 0
df_2.index *= 0
df = df_1.join(df_2, lsuffix='_2')
df = df[df.sum(axis=1) % 2 == 0]

Правка, вот лучшее решение

df_1.index = df_1.iloc[:,0] % 2
df_2.index = df_2.iloc[:,0] % 2
df = df_1.join(df_2, lsuffix='_2')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...