Используя pandas, как объединить две таблицы по индексу переменной? - PullRequest
4 голосов
/ 10 июля 2020

Есть две таблицы, записи могут иметь разные типы id. Мне нужно объединить две таблицы на основе id_type df1 и правильного столбца df2. В качестве фона проблемы идентификаторы - это идентификатор безопасности в финансовом мире, тип идентификатора может быть CUSIP, ISIN, RI C et c ..

print(df1)
   id id_type  value
0  11  type_A    0.1
1  22  type_B    0.2
2  13  type_A    0.3

print(df2)
  type_A type_B type_C
0     11     21     xx
1     12     22     yy
2     13     23     zz

Желаемый результат -

  type_A type_B type_C  value
0     11     21     xx    0.1
1     12     22     yy    0.2
2     13     23     zz    0.3

Ответы [ 2 ]

1 голос
/ 28 июля 2020

Вот альтернативный подход, который распространяется на многие типы безопасности (CUSIP, ISIN, RI C, SEDOL, и т. Д. c.).

Сначала создайте df1 и df2 по строкам исходного примера:

import numpy as np
import pandas as pd

df1 = pd.DataFrame({'sec_id': [11, 22, 33],
                    'sec_id_type': ['CUSIP', 'ISIN', 'RIC'], 
                    'value': [100, 200, 300]})

df2 = pd.DataFrame({'CUSIP': [11, 21, 31],
                    'ISIN': [21, 22, 23],
                    'RIC': [31, 32, 33],
                    'SEDOL': [41, 42, 43]})

Во-вторых, создайте промежуточный фрейм данных x1. Мы будем использовать первый столбец для одного соединения, а второй и третий столбцы для другого соединения:

index = [idx for idx in df2.index for _ in df2.columns]
sec_id_types = df2.columns.to_list() * df2.shape[0]
sec_ids = df2.values.ravel()

data = [
    (idx, sec_id_type, sec_id)
    for idx, sec_id_type, sec_id in zip(index, sec_id_types, sec_ids)
]

x1 = pd.DataFrame.from_records(data, columns=['index', 'sec_id_type', 'sec_id'])

Join df1 и x1 для извлечения значений из df1:

x2 = (x1.merge(df1, on=['sec_id_type', 'sec_id'], how='left')
      .dropna()
      .set_index('index'))

Наконец, объедините df2 и x1 (из предыдущего шага), чтобы получить окончательный результат

print(df2.merge(x2, left_index=True, right_index=True, how='left'))

   CUSIP  ISIN  RIC  SEDOL sec_id_type  sec_id  value
0     11    21   31     41       CUSIP      11  100.0
1     21    22   32     42        ISIN      22  200.0
2     31    23   33     43         RIC      33  300.0

Столбцы sec_id_type и sec_id показывают, что объединения работают должным образом.

0 голосов
/ 11 июля 2020

НОВОЕ Решение 1. Создайте временный столбец, который определяет идентификатор с помощью np.where

df2['id'] = np.where(df2['type_A'] == df1['id'], df2['type_A'], df2['type_B'])
df = pd.merge(df2,df1[['id','value']],how='left',on='id').drop('id', axis=1)

НОВОЕ Решение 2. Можно ли просто выполнить слияние по индексу? Если не go с решением № 1.

df = pd.merge(df2, df1['value'], how ='left', left_index=True, right_index=True)

вывод:

    type_A  type_B  type_C  value
0   11      21      xx      0.1
1   12      22      yy      0.2
2   13      23      zz      0.3

СТАРОЕ Решение: с помощью комбинации pd.merge, pd.melt и pd.concat, I нашел решение, хотя мне интересно, есть ли более короткий путь (вероятно):

df_A_B = pd.merge(df2[['type_A']], df2[['type_B']], how='left', left_index=True, right_index=True) \
           .melt(var_name = 'id_type', value_name='id')
df_C = pd.concat([df2[['type_C']]] * 2).reset_index(drop=True)
df_A_B_C = pd.merge(df_A_B, df_C, how='left', left_index=True, right_index=True)
df3 = pd.merge(df_A_B_C, df1, how='left', on=['id_type', 'id']).dropna().drop(['id_type', 'id'], axis=1)
df4 = pd.merge(df2, df3, how='left', on=['type_C'])
df4

вывод:

    type_A  type_B  type_C  value
0   11      21      xx      0.1
1   12      22      yy      0.2
2   13      23      zz      0.3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...