「问题」官方文档中关于merge和join 一个note引起的疑问

在官方文档 — Merge, join, concatenate and compare中,在介绍完join的常用方法后,在后续的note中有这样一段话。

When DataFrame are joined using only some of the levels of a MultiIndex, the extra levels will be dropped from the resulting join. To preserve those levels, use DataFrame.reset_index() on those level names to move those levels to columns prior to the join.

DataFrame 仅使用 MultiIndex 中的部分级别进行连接时,额外的级别将从连接结果中删除。要保留这些层级,请在这些层级名称上使用 DataFrame.reset_index() 将这些层级移动到连接前的列中。

也是我阅读的问题,没有注意到它的位置。现在再回头去看,这一节是在 「Merging on a combination of columns and index levels」这一栏下面的,因此其实这个注释是给merge的,但当时大标题是join因此我以为是针对join的。

因此产生了一个疑问,join并不会抛弃 「extra level」 啊,在官方文档的上面还有一个例子,就是关于join处理 MultiIndex 时,右侧的表的index必须是左侧表index的子集。

然后在下面的例子中,连接的过程中,extra level 并没有删除。如下所示,可以很直观的看到 num 列被保存了下来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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

因此我对这个注释产生了疑问,并在stackoverflow上发起了这个回答How is this description understood in the pandas documentation?

得到的回复就是,drop extra level这个特性是merge的而不是join的,并在测试答者提供的代码后发现果然如此 — 我闹乌龙了。

如下代码,只是简单的将join改为merge,结果截然不同,num列没了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
left_index = pd.MultiIndex.from_product(  
[list("abc"), list("xy"), [1, 2]], names=["abc", "xy", "num"]
)

left = pd.DataFrame({"v1": range(12)}, index=left_index)



right_index = pd.MultiIndex.from_product(
[list("abc"), list("xy")], names=["abc", "xy"]
)

right = pd.DataFrame({"v2": [100 * i for i in range(1, 7)]}, index=right_index)


print(left.merge(right, on=["abc", "xy"], how="inner"))

'''
v1 v2
abc xy
a x 0 100
x 1 100
y 2 200
y 3 200
b x 4 300
x 5 300
y 6 400
y 7 400
c x 8 500
x 9 500
y 10 600
y 11 600
'''

随后,我也根据note中描述,使用reset_index处理右边的表,然后再merge。 yes,完全正确。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
print(left.reset_index().merge(right, on=["abc", "xy"], how="inner"))

'''
abc xy num v1 v2
0 a x 1 0 100
1 a x 2 1 100
2 a y 1 2 200
3 a y 2 3 200
4 b x 1 4 300
5 b x 2 5 300
6 b y 1 6 400
7 b y 2 7 400
8 c x 1 8 500
9 c x 2 9 500
10 c y 1 10 600
11 c y 2 11 600
'''

写在最后

这段时间使用stackoverflow,emmm,不得不承认,环境差距真的很大,国内没有一个比较好的社区。V2ex可能还行,但是居然是被墙的,至于其他的。

CSDN最近copy的事也是沸沸扬扬,难评!

-------------已经到底啦!-------------

欢迎关注我的其它发布渠道