【问题标题】:Using pandas, how to join two tables on variable index?使用熊猫,如何在变量索引上连接两个表?
【发布时间】:2020-10-31 15:24:44
【问题描述】:

有两个表,条目可能有不同的 id 类型。我需要根据 df1 的 id_type 和 df2 的正确列连接两个表。对于问题的背景,id是金融界的证券id,id类型可能是CUSIP、ISIN、RIC等。

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

【问题讨论】:

  • 我回答你的问题了吗?你能接受作为答案吗?
  • 这看起来很复杂。我正在等待或有更好的解决方案。
  • 如果您愿意接受,将提供更简单的解决方案:)

标签: pandas merge


【解决方案1】:

这是一种替代方法,它可以推广到许多安全类型(CUSIP、ISIN、RIC、SEDOL 等)。

首先,按照原始示例的思路创建df1df2

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'])

加入df1x1 以从df1 中提取值:

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

最后,加入df2x1(来自上一步)以获得最终结果

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_typesec_id 列显示连接按预期工作。

【讨论】:

    【解决方案2】:

    新解决方案 1:创建一个临时列,确定 ID 为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:您可以简单地合并索引吗?如果没有,请使用解决方案 #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.mergepd.meltpd.concat的组合,我找到了解决方案,虽然我想知道是否有更短的方法(可能):

    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
    

    【讨论】:

      猜你喜欢
      • 2019-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-19
      • 2014-05-03
      • 1970-01-01
      • 2017-11-18
      相关资源
      最近更新 更多