https://pandas.pydata.org/docs/user_guide/merging.html#dataframe-join
当仅使用 MultiIndex 的某些级别连接 DataFrame 时,多余的级别将从结果连接中删除。要保留这些级别,请在这些级别名称上使用 DataFrame.reset_index() 将这些级别移动到连接之前的列。
这段话该如何理解?
上面提到了使用子集时的连接示例,其中索引 --- 'num' 仍然存在并广播,这让我觉得很奇怪。如果右索引不是左索引的子集,那么就会报错,这个试过了,即使使用on来指定公共索引也不行
In [109]: leftindex = pd.MultiIndex.from_product(
.....: [list("abc"), list("xy"), [1, 2]], names=["abc", "xy", "num"]
.....: )
.....:
In [110]: left = pd.DataFrame({"v1": range(12)}, index=leftindex)
In [111]: left
Out[111]:
v1
abc xy num
a x 1 0
2 1
y 1 2
2 3
b x 1 4
2 5
y 1 6
2 7
c x 1 8
2 9
y 1 10
2 11
In [112]: rightindex = pd.MultiIndex.from_product(
.....: [list("abc"), list("xy")], names=["abc", "xy"]
.....: )
.....:
In [113]: right = pd.DataFrame({"v2": [100 * i for i in range(1, 7)]}, index=rightindex)
In [114]: right
Out[114]:
v2
abc xy
a x 100
y 200
b x 300
y 400
c x 500
y 600
In [115]: left.join(right, on=["abc", "xy"], how="inner")
Out[115]:
v1 v2
abc xy num
a x 1 0 100
2 1 100
y 1 2 200
2 3 200
b x 1 4 300
2 5 300
y 1 6 400
2 7 400
c x 1 8 500
2 9 500
y 1 10 600
2 11 600
那么,这段话该如何理解呢?
这只适用于合并列和索引级别的组合。
例如,如果我们扩展您的示例并在
'v1'
上添加一列 right
,然后 merge
on=["abc", "xy", "v1"]
,结果将删除索引 'num'
:
# ...keeping all else unchanged
right = pd.DataFrame(
{"v1": range(1, 7), "v2": [100 * i for i in range(1, 7)]}, index=rightindex
)
left.merge(right, on=["abc", "xy", "v1"], how="left")
v1 v2
abc xy
a x 0 NaN
x 1 100.0
y 2 200.0
y 3 NaN
b x 4 NaN
x 5 NaN
y 6 NaN
y 7 NaN
c x 8 NaN
x 9 NaN
y 10 NaN
y 11 NaN
请注意为什么添加此警告,但对我来说似乎不正确。
如果您不提供
on
,则会在普通关卡上自动与 join
对齐关卡,并且不会掉落任何关卡。
让我们假设一个更复杂的示例,其中存在不同级别的项目以更好地欣赏:
leftindex = pd.MultiIndex.from_product(
[list("abc"), list("xy"), [1, 2]], names=["abc", "xy", "num"]
)
left = pd.DataFrame({"v1": range(12)}, index=leftindex)
rightindex = pd.MultiIndex.from_product(
[list("abx"), list("cy"), list('z')], names=["xy", "abc", 'Z']
)
right = pd.DataFrame({"v2": [100 * i for i in range(1, 7)]}, index=rightindex)
left.join(right, how='inner')
# v1 v2
# abc xy num Z
# c x 1 z 8 500
# 2 z 9 500
如果您使用
merge
,现在正确的级别会被删除:
left.merge(right, left_index=True, right_index=True)
# v1 v2
# abc xy num
# c x 1 8 500
# 2 9 500