python - 通过具有重复索引的索引合并(或连接)两个数据帧
问题描述
我有两个数据框 A 和 B,A 和 B 具有公共索引。这些公共索引对于 A 和 B 可能出现多次(重复)。
我想以这 3 种方式合并 A 和 B:
- 案例 0:如果出现一次的索引
i
和 出现A
一次的(i1)
索引i
,我希望我的按索引数据框合并以添加行B
(i1)
A(i1), B(i1)
- 案例 1:如果索引
i
出现A
一次(i1)
,索引i
出现B
两次(i1 and i2)
,我希望我的按索引合并的数据框添加行A(i1), B(i1) and A(i1), B(i2)
。 - 情况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'
。
解决方案
Basically, your 3 cases can be summarized into 2 cases:
- Index i occur the same times (1 or 2 times) in A and B, merge according to the order.
- 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
.
推荐阅读
- javascript - 当滚动间谍下拉菜单没有监视任何默认文本时,有没有办法更新它的文本?
- windows - FC 命令找不到现有目录
- c++ - 需要 C++ 索引队列数据结构
- c - 使用 rewind 或 fgets 使用大小为 8 的未初始化值
- unity3d - 统一广告在 Playstore 上不起作用但在测试中起作用?
- firebase - 在颤动中显示屏幕列表中的数据的方法是什么?
- java - 如何为不同的 API 获取不同的参数,如下所述
- python - 在 Jupyter 中由 Python 创建 .txt 文件的问题
- mysql - 如何配置 rails 控制台以显示执行 sql 的代码行?
- python - python程序打印从用户输入的数字开始的7个数字序列