Python pandas中pd.join(how=';left';)的意外结果

Python pandas中pd.join(how=';left';)的意外结果,python,sql,pandas,Python,Sql,Pandas,在计算机上使用jupyter笔记本 3.6.3 |蟒蛇定制(64位)|(默认,2017年10月15日,03:27:45)[MSC v.1900 64位(AMD64)] 考虑下面的简单示例: left = pd.DataFrame({'k': ['K0', 'K1', 'K2'], 'v': [1, 2, 3]}).set_index('k') right = pd.DataFrame({'k': ['K0', 'K0', 'K3'], 'v': [4, 5, 6]}).set_index('k'

在计算机上使用jupyter笔记本 3.6.3 |蟒蛇定制(64位)|(默认,2017年10月15日,03:27:45)[MSC v.1900 64位(AMD64)]

考虑下面的简单示例:

left = pd.DataFrame({'k': ['K0', 'K1', 'K2'], 'v': [1, 2, 3]}).set_index('k')
right = pd.DataFrame({'k': ['K0', 'K0', 'K3'], 'v': [4, 5, 6]}).set_index('k')
right2 = pd.DataFrame({'v': [7, 8, 9]}, index=['K1', 'K1', 'K3'])
left
right
right2
left.join(right,how='left',lsuffix='_L',rsuffix='_R')
pd.merge(left,right,how='left',right_index=True,left_index=True)
到目前为止,一切都很好!最后两行产生了与预期相同的结果,但下面的行结果对我来说是相当意外的,因为它包含不属于
left
数据帧的索引(结果似乎是外部联接):

我注意到它也使用了
.merge
默认后缀,而不是我为
.join
指定的后缀,我没有收到任何错误。为什么呢

当连接两个以上的数据帧时,也可以这样做,如下所示:

left.join([right,right2])
我不明白为什么结果包含不属于
left
数据帧的索引,即使这是一个左连接

这可以在有关的pandas文档中看到


非常感谢

对于问题的第一部分(即:我注意到它也使用了.merge默认后缀,而不是我为.join指定的后缀,而且我没有收到任何错误。这是为什么?)我不知道为什么,但根据文档,它似乎是正确的:

Notes
-----
on, lsuffix, and rsuffix options are not supported when passing a list
of DataFrame objects

那么你问题的最后一部分我有点不知道。如果您检查
df.join()
的代码,则在使用列表时似乎是这样的…

。您将看到,如果
other
不是
数据帧
系列
,即
列表
,在某个时候会发生这种情况:

        # join indexes only using concat
        if how == 'left':   
            how = 'outer'
            join_axes = [self.index]
        else:
            join_axes = None

        frames = [self] + list(other)

        can_concat = all(df.index.is_unique for df in frames)

        if can_concat:
            return concat(frames, axis=1, join=how, join_axes=join_axes,
                          verify_integrity=True)

        joined = frames[0]

        for frame in frames[1:]:
            joined = merge(joined, frame, how=how, left_index=True,
                           right_index=True)

        return joined
因此,
how='left'
更改为
how='outer'
。我不知道为什么要这样做,但似乎是为了(正如评论所暗示的)做一些准备;concat只能处理“内部”或“外部”。但是在您的情况下,索引不是唯一的,代码底部的for循环被执行(但仍然使用how='outer')。这解释了您所看到的情况(与外部联接类似合并的行为)

当然,您也可以使用相同的策略,但如何在代码中直接使用='left'来执行一系列左连接:

joined = left
for frame in [right, right2]:
    joined = pd.merge(joined, frame, how='left', left_index=True, right_index=True)

这是一种意想不到的行为,现已作为一种行为提交。
joined = left
for frame in [right, right2]:
    joined = pd.merge(joined, frame, how='left', left_index=True, right_index=True)