首页 > 解决方案 > 通过具有重复索引的索引合并(或连接)两个数据帧

问题描述

我有两个数据框 A 和 B,A 和 B 具有公共索引。这些公共索引对于 A 和 B 可能出现多次(重复)。

我想以这 3 种方式合并 A 和 B:

  1. 案例 0:如果出现一次的索引i和 出现A一次的(i1)索引i,我希望我的按索引数据框合并以添加行B(i1)A(i1), B(i1)
  2. 案例 1:如果索引i出现A一次(i1),索引i出现B 两次(i1 and i2),我希望我的按索引合并的数据框添加行A(i1), B(i1) and A(i1), B(i2)
  3. 情况2:如果索引按此i顺序出现两次A(i1, i2)并且索引按此顺序i出现B两次:(i1 and i2),我希望我的索引数据框合并以添加行A(i1), B(i1) and A(i2), B(i2)

这 3 种情况都是可能出现在我的数据中的所有情况。

使用 pandas.merge 时,案例 0 和案例 1 有效。但是对于情况 2,返回的数据框将添加行 A(i1), B(i1) and A(i1), B(i2) and A(i2), B(i1) and A(i2), B(i2)而不是A(i1), B(i1) and A(i2), B(i2).

我可以使用 pandas.merge 方法,然后删除不需要的合并行,但是有没有办法同时组合这 3 个案例?

A = pd.DataFrame([[1, 2], [4, 2], [5,5], [5,5], [1,1]], index=['a', 'a', 'b', 'c', 'c'])
B = pd.DataFrame([[1, 5], [4, 8], [7,7], [5,5]], index=['b', 'c', 'a', 'a'])
pd.merge(A,B, left_index=True, right_index=True, how='inner')

例如,在上面的数据框中,我完全希望它没有第二个和第三个 index 'a'

标签: pythonpandasdataframe

解决方案


Basically, your 3 cases can be summarized into 2 cases:

  1. Index i occur the same times (1 or 2 times) in A and B, merge according to the order.
  2. Index i occur 2 times in A and 1 time in B, merge using B content for all rows.

Prep code:

def add_secondary_index(df):
    df.index.name = 'Old'
    df['Order'] = df.groupby(df.index).cumcount()
    df.set_index('Order', append=True, inplace=True)
    return df
import pandas as pd
A = pd.DataFrame([[1, 2], [4, 2], [5,5], [5,5], [1,1]], index=['a', 'a', 'b', 'c', 'c'])
B = pd.DataFrame([[1, 5], [4, 8], [7,7], [5,5]], index=['b', 'c', 'a', 'a'])
index_times = A.groupby(A.index).count() == B.groupby(B.index).count()

For case 1 is easy to solve, you just need to add the secondary index:

same_times_index = index_times[index_times[0].values].index
A_same = A.loc[same_times_index].copy()
B_same = B.loc[same_times_index].copy()
add_secondary_index(A_same)
add_secondary_index(B_same)
result_merge_same = pd.merge(A_same,B_same,left_index=True,right_index=True)

For case 2, you need to seprately consider:

not_same_times_index = index_times[~index_times.index.isin(same_times_index)].index
A_notsame = A.loc[not_same_times_index].copy()
B_notsame = B.loc[not_same_times_index].copy()
result_merge_notsame = pd.merge(A_notsame,B_notsame,left_index=True,right_index=True)

You could consider whether to add secondary index for result_merge_notsame, or drop it for result_merge_same.


推荐阅读