【问题标题】:Using fillna with two multi-index dataframes throws InvalidIndexError将 fillna 与两个多索引数据帧一起使用会引发 InvalidIndexError
【发布时间】:2020-10-28 13:55:11
【问题描述】:

我有两个这样的数据框:

import pandas as pd
import numpy as np


df1 = pd.DataFrame({
    'key1': list('ABAACCA'),
    'key2': list('1675987'),
    'prop1': list('xyzuynb'),
    'prop2': list('mnbbbas')
}).set_index(['key1', 'key2'])

df2 = pd.DataFrame({
    'key1': list('ABCCADD'),
    'key2': list('1598787'),
    'prop1': [np.nan] * 7,
    'prop2': [np.nan] * 7
}).set_index(['key1', 'key2'])

          prop1 prop2
key1 key2            
A    1        x     m
B    6        y     n
A    7        z     b
     5        u     b
C    9        y     b
     8        n     a
A    7        b     s

           prop1  prop2
key1 key2              
A    1       NaN    NaN
B    5       NaN    NaN
C    9       NaN    NaN
     8       NaN    NaN
A    7       NaN    NaN
D    8       NaN    NaN
     7       NaN    NaN

现在想用df1 填充df2 使用

df2.fillna(df1)

但是,我明白了

site-packages/pandas/core/generic.py in _where(self, cond, other, 就地、轴、级别、错误、try_cast)8694
other._get_axis(i).equals(ax) for i, ax in enumerate(self.axes)
8695): -> 8696 raise InvalidIndexError 8697 8698 # 把我从其他人中分割出来

无效索引错误:

我过去成功地使用了这种方法,但我真的不明白为什么会失败。任何想法如何使它工作?

编辑

这是一个非常相似并且工作得很好的例子:

filler1 = pd.DataFrame({
    'key': list('AAABCCDD'),
    'prop1': list('xyzuyasj'),
    'prop2': list('mnbbbqwo')
})

tobefilled1 = pd.DataFrame({
    'key': list('AAABBCACDF'),
    'keep_me': ['stuff'] * 10,
    'prop1': [np.nan] * 10,
    'prop2': [np.nan] * 10,
    
})

filler1['g'] = filler1.groupby('key').cumcount()
tobefilled1['g'] = tobefilled1.groupby('key').cumcount()

filler1 = filler1.set_index(['key', 'g'])
tobefilled1 = tobefilled1.set_index(['key', 'g'])

print(tobefilled1.fillna(filler1))

prints

key g                    
A   0   stuff     x     m
    1   stuff     y     n
    2   stuff     z     b
B   0   stuff     u     b
    1   stuff   NaN   NaN
C   0   stuff     y     b
A   3   stuff   NaN   NaN
C   1   stuff     a     q
D   0   stuff     s     w
F   0   stuff   NaN   NaN

【问题讨论】:

    标签: python pandas dataframe multi-index fillna


    【解决方案1】:

    这里的问题是df1中定义的重复索引:

    df1 = pd.DataFrame({
        'key1': list('ABAACCA'),
        'key2': list('1675987'),
        'prop1': list('xyzuynb'),
        'prop2': list('mnbbbas')
    }).set_index(['key1', 'key2'])
    

    注意:Key1=A Key2=7 出现两次,df1 的索引不是唯一的。

    让我们把第二个 A7 改成 A9

    df1 = pd.DataFrame({
        'key1': list('ABAACCA'),
        'key2': list('1675989'),
        'prop1': list('xyzuynb'),
        'prop2': list('mnbbbas')
    }).set_index(['key1', 'key2'])
    
    df2 = pd.DataFrame({
        'key1': list('ABCCADD'),
        'key2': list('1598787'),
        'prop1': [np.nan] * 7,
        'prop2': [np.nan] * 7
    }).set_index(['key1', 'key2'])
    

    因此在 df1 中创建唯一索引,现在尝试 df.fillna:

    df2.fillna(df1)
    

    输出:

              prop1 prop2
    key1 key2            
    A    1        x     m
    B    5      NaN   NaN
    C    9        y     b
         8        n     a
    A    7        z     b
    D    8      NaN   NaN
         7      NaN   NaN
    

    当我尝试 reindex_like 方法时,我得到了提示,首先使用唯一索引:

    df1 = pd.DataFrame({
        'key1': list('ABAACCA'),
        'key2': list('1675989'),
        'prop1': list('xyzuynb'),
        'prop2': list('mnbbbas')
    }).set_index(['key1', 'key2'])
    
    df2 = pd.DataFrame({
        'key1': list('ABCCADD'),
        'key2': list('1598787'),
        'prop1': [np.nan] * 7,
        'prop2': [np.nan] * 7
    }).set_index(['key1', 'key2'])
    print(df1.reindex_like(df2))
    

    输出:

              prop1 prop2
    key1 key2            
    A    1        x     m
    B    5      NaN   NaN
    C    9        y     b
         8        n     a
    A    7        z     b
    D    8      NaN   NaN
         7      NaN   NaN
    

    现在,让我们回到帖子中的原始数据框:

    df1 = pd.DataFrame({
        'key1': list('ABAACCA'),
        'key2': list('1675987'),
        'prop1': list('xyzuynb'),
        'prop2': list('mnbbbas')
    }).set_index(['key1', 'key2'])
    
    df2 = pd.DataFrame({
        'key1': list('ABCCADD'),
        'key2': list('1598787'),
        'prop1': [np.nan] * 7,
        'prop2': [np.nan] * 7
    }).set_index(['key1', 'key2'])
    print(df1.reindex_like(df2))
    

    输出值错误:

    ValueError: cannot handle a non-unique multi-index!
    

    另一种解决方法是通过使用 cumcount 添加另一个索引级别来创建唯一索引。

    df1 = pd.DataFrame({
        'key1': list('ABAACCA'),
        'key2': list('1675987'),
        'prop1': list('xyzuynb'),
        'prop2': list('mnbbbas')
    }).set_index(['key1', 'key2'])
    
    df2 = pd.DataFrame({
        'key1': list('ABCCADD'),
        'key2': list('1598787'),
        'prop1': [np.nan] * 7,
        'prop2': [np.nan] * 7
    }).set_index(['key1', 'key2'])
    
    df1 = df1.set_index(df1.groupby(df1.index).cumcount(), append=True)
    df2 = df2.set_index(df2.groupby(df2.index).cumcount(), append=True)
    
    df2.fillna(df1)
    

    输出:

                prop1 prop2
    key1 key2              
    A    1    0     x     m
    B    5    0   NaN   NaN
    C    9    0     y     b
         8    0     n     a
    A    7    0     z     b
    D    8    0   NaN   NaN
         7    0   NaN   NaN
    

    然后你可以删除索引级别 2:

    df2.fillna(df1).reset_index(level=2, drop=True)
    

    输出:

              prop1 prop2
    key1 key2            
    A    1        x     m
    B    5      NaN   NaN
    C    9        y     b
         8        n     a
    A    7        z     b
    D    8      NaN   NaN
         7      NaN   NaN
    

    但是,我认为 pandas 应该为 fillna 非唯一 MultiIndexes 提供更好的错误消息,就像它为 reindex_like 所做的那样。

    【讨论】:

    • 索引问题显然解释了这一点。添加 verify_integrity=True 会在此行中引发 ValueError:df1 = pd.DataFrame({...}).set_index(['key1', 'key2'], verify_integrity=True)
    • 啊,不错,没注意到这个;我在为我的实际问题创建一个最小示例时遇到了这个问题,我确实使用了cumsum 方法;所以,在我的实际用例中,我总是有唯一的索引,但在我的玩具示例中,我搞砸了...... ;) 暂时赞成,稍后将接受并奖励赏金......
    【解决方案2】:

    这是一些索引值不匹配的问题,对我来说,使用 DataFrame.combine_first 的替代解决方案:

    df = df2.combine_first(df1)
    print (df)
              prop1 prop2
    key1 key2            
    A    1        x     m
         5        u     b
         7        z     b
         7        b     s
    B    5      NaN   NaN
         6        y     n
    C    8        n     a
         9        y     b
    D    7      NaN   NaN
         8      NaN   NaN
    

    【讨论】:

    • 谢谢。但是,你知道为什么上面的例子失败了,例如this one(你自己的答案:))有效吗?
    • @Cleb - 老实说不知道,我猜差异是链接答案中索引匹配的所有值。
    • 好的。我也是这么想的,但我也有一些例子,我还剩下很多 NANs,但效果很好;这对我来说有点神秘。
    • @Cleb - 也许是错误,因为错误很奇怪,而且不清楚。
    • 看看别人有没有想法;我在我的问题中添加了一个工作示例,其中一个仍然有 NANs 。
    猜你喜欢
    • 2018-06-24
    • 1970-01-01
    • 2020-10-21
    • 2021-01-28
    • 2022-12-17
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    相关资源
    最近更新 更多