多重索引无重叠时内连接失败

7 投票
3 回答
1868 浏览
提问于 2025-04-17 16:01

我在使用多重索引时,无法让“空”的内连接正常工作。在0.10.1版本中,我有:

d1 = pd.DataFrame({
    'i1': [1, 2, 2],
    'i2': [1, 1, 2],
     'a': [10,20,30]}).set_index(['i1', 'i2'])
d2 = pd.DataFrame({
    'i1': [3, 3],
    'i2': [1, 2],
    'b': [40, 50]}).set_index(['i1', 'i2'])
d1.join(d2, how='inner')

这段代码给我返回了

Exception: Cannot infer number of levels from empty list

有没有什么好的解决办法呢?我想提前知道交集是否为空,这样我就可以避免出现异常。

3 个回答

1

在这个问题中,我通过逐块合并来自HDFstore的多重索引节点来解决了for循环中的问题。虽然我的解决办法看起来不太优雅,但可能对其他人将来会有帮助。

import pandas as pd
d1 = pd.DataFrame({
    'i1': [1, 2, 2],
    'i2': [1, 1, 2],
     'a': [10,20,30]}).set_index(['i1', 'i2'])
d2 = pd.DataFrame({
    'i1': [3, 3],
    'i2': [1, 2],
    'b': [40, 50]}).set_index(['i1', 'i2'])
for x in y:
    try:
        d3 = d1.join(d2, how='inner')
    except Exception:            
        print "no merge possible between rows, but let's continue"
        d3 = d1.join(d2, how='outer').dropna()
    if len(d3)
        print "there's a merge"
        #action
    print "fail, but still in the race"
2

我不是百分之百确定,但做一个外连接然后去掉空值(NAs),其实和做一个内连接是一样的。所以如果没有匹配的索引,你得到的就是一个空的数据框。如果我们把你的例子改一下,加入一个匹配的记录,这种情况就很明显了:

import pandas as pd
d1 = pd.DataFrame({
    'i1': [1, 2, 2],
    'i2': [1, 1, 2],
    'a': [10,20,30]}).set_index(['i1', 'i2'])
d2 = pd.DataFrame({
    'i1': [1, 3],
    'i2': [1, 2],
    'b': [40, 50]}).set_index(['i1', 'i2'])
d3 = d1.join(d2, how='outer').dropna()
d4 = d1.join(d2, how='inner')

这样就得到了:

In [9]: d3
Out[9]: 
        a   b
i1 i2        
1  1   10  40

In [10]: d4
Out[10]: 
        a   b
i1 i2        
1  1   10  40

所以在进行外连接加上 dropna() 之后,你可以看到 d3 有多少行,然后再继续处理。用你最初的例子来看:

import pandas as pd
d1 = pd.DataFrame({
    'i1': [1, 2, 2],
    'i2': [1, 1, 2],
     'a': [10,20,30]}).set_index(['i1', 'i2'])
d2 = pd.DataFrame({
    'i1': [3, 3],
    'i2': [1, 2],
    'b': [40, 50]}).set_index(['i1', 'i2'])
d3 = d1.join(d2, how='outer').dropna()
print(d3.shape) # no error, shows "(0, 2)"
5

这句话的意思是,有时候直接去做事情比事先请求允许要简单得多。换句话说,如果你想尝试某个操作,不如先去做了再说,万一出错了再找办法解决。这个理念在编程中也很常见,很多时候我们会选择先执行代码,然后处理可能出现的错误,而不是在执行之前先检查所有条件。

import pandas as pd
d1 = pd.DataFrame({'i1': [1, 2, 2], 'i2': [1, 1, 2], 'a': [10, 20, 30]}
                  ).set_index(['i1', 'i2'])
d2 = pd.DataFrame(
    {'i1': [3, 3], 'i2': [1, 2], 'b': [40, 50]}).set_index(['i1', 'i2'])
try:
    d1.join(d2, how='inner')
except Exception as err:
    # Change this to however you wish to handle this case.
    print(err)

撰写回答