Панды объединяют два фрейма данных, используя логические или между общими столбцами - PullRequest
0 голосов
/ 23 мая 2018

У меня есть два фрейма данных панд A и B, проиндексированных с датами:

>>> A
                a      b      c
Timestamp
2018-02-19   True  False  False
2018-02-20  False   True  False
2018-02-21  False  False   True

и

>>> B
                a      b      d
Timestamp
2018-02-19  False   True   True
2018-02-20  False  False  False
2018-02-21   True   True   True

Я хочу объединить эти два фрейма данных так, чтобыобъединенный фрейм данных представляет собой логический or между каждой общей записью (индекс, столбец), а также включает в себя столбцы, которые являются уникальными для каждого фрейма данных.В этом случае вывод будет:

>>> C
                a      b      c      d
Timestamp
2018-02-19   True   True  False   True
2018-02-20  False   True  False  False
2018-02-21   True   True   True   True

Есть ли способ сделать это в пандах?

1 Ответ

0 голосов
/ 23 мая 2018

Возможно, существует более элегантное и обобщаемое решение, но оно будет работать для приведенного вами простого примера.

A = pd.DataFrame({"a":[True, False, False],
                  'b':[False, True, False],
                  'c': [False, False, True]},
                  index=['a','b','c'])

B = pd.DataFrame({"a":[False, False, True],
                  'b':[True, False, True], 
                  'd': [True, False, True]}, 
                  index=['a','b','c'])

C = pd.concat([(A | B)[['a', 'b']], A['c'], B['d']], axis=1)

print C

       a     b      c      d
a   True  True  False   True
b  False  True  False  False
c   True  True   True   True

Это ИЛИ для двух кадров, что даст правильный результат для столбцов вобычный (a, b), но Nan для столбцов c, d.Итак, мы просто нарезаем столбцы a и b, затем объединяем их с c и d, поскольку они остаются неизменными операцией OR.

EDIT: В соответствии с вашим комментарием, здесь более обобщенное решение, который избавит вас от необходимости знать и / или жестко задавать конкретные имена столбцов.

# Get all column names
all_columns = A.columns | B.columns

# Get column names in common
union = A.columns & B.columns

# Get disjoint column names
not_B = list(set(all_columns) - set(B.columns))
not_A = list(set(all_columns) - set(A.columns))

# Logical-or common columns, and concatenate disjoint columns
C = pd.concat([A[union] | B[union], A[not_B], B[not_A]], axis=1)

# If columns names get disordered because of set operations, use
# `all_columns` to reorder

print(C[all_columns])

       a     b      c      d
a   True  True  False   True
b  False  True  False  False
c   True  True   True   True

РЕДАКТИРОВАТЬ 2: За kmundnic окончательное решение, вот обновленная версия, которая работает на более чем двух фреймах данных.

# For Python 3
from functools import reduce

# A third data frame
C = pd.DataFrame({'a':[False, False, False],
                  'b':[True, True, False], 
                  'e': [True, True, True]}, 
                  index=['a','b','c'])

def logical_merge(A, B):

    # Get all column names
    all_columns = A.columns | B.columns

    # Get column names in common
    common = A.columns & B.columns

    # Get disjoint column names
    _A = [x for x in B.columns if not x in common]
    _B = [x for x in A.columns if not x in common]

    # Logical-or common columns, and concatenate disjoint columns
    return pd.concat([(A | B)[common], A[_B], B[_A]], axis=1)[all_columns]

frames = [A, B, C]

print(reduce(logical_merge, frames))

       a     b      c      d     e
a   True  True  False   True  True
b  False  True  False  False  True
c   True  True   True   True  True
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...