【问题标题】:Using IndexSlice to filter MultiIndex Dataframes with Pandas使用 IndexSlice 通过 Pandas 过滤 MultiIndex 数据帧
【发布时间】:2017-03-08 23:04:46
【问题描述】:

问题:如何过滤行,以便只返回注入不等于 0 或 NaN 的行而不丢失其他列的值?

我有一个使用以下代码创建的数据框:

import pandas as pd

df=pd.DataFrame(
               [
               [5777, 100, 5385, 200, 5419, 4887, 100, 200],
               [4849, 0, 4539, 0, 3381, 0, 0, ],
               [4971, 0, 3824, 0, 4645, 3424, 0, 0, ],
               [4827, 200, 3459, 300, 4552, 3153, 100, 200, ],
               [5207, 0, 3670, 0, 4876, 3358, 0, 0, ],
               ],
               index=pd.to_datetime(['2010-01-01',
                                     '2010-01-02',
                                     '2010-01-03',
                                     '2010-01-04',
                                     '2010-01-05']),
               columns=pd.MultiIndex.from_tuples(
                                                [('Portfolio A', 'GBP', 'amount'),
                                                 ('Portfolio A', 'GBP', 'injection'),
                                                 ('Portfolio B', 'EUR', 'amount'),                                           ('Portfolio B', 'EUR', 'injection'),
                                                 ('Portfolio C', 'USD', 'amount'),                                           ('Portfolio C', 'USD', 'injection'),
                                                 ('Portfolio D', 'JPY', 'amount'),                                           ('Portfolio D', 'JPY', 'injection')])
                                   ).sortlevel(axis=1)

接下来我可以使用数据切片创建一个 DataFrame(在本例中是所有数据)

df1=df.loc[pd.IndexSlice[:], pd.IndexSlice[:,:, ['amount', 'injection']]]

接下来创建一个新的 DataFrame,其中注入为 != 0

df2=df1[df1.loc[pd.IndexSlice[:], pd.IndexSlice[:, :, 'injection']]!=0]

问题:为什么这会将“金额”列中的所有值重置为 NaN?

一旦金额可用,下一步就是删除所有为 NaN 的行

df3=df2.dropna(axis=0, how='all', thresh=None, subset=None, inplace=False)

所需的输出是跨行索引的所有数据:

2010-01-01
2010-01-03
2010-01-04
2010-01-05

【问题讨论】:

    标签: python pandas slice nan multi-index


    【解决方案1】:

    我认为您需要添加fillnaany 以检查至少一个True 值,如果需要boolean indexing,它与boolean Series 一起使用掩码:

    print (df1.loc[:, pd.IndexSlice[:, :, 'injection']].fillna(0) != 0)
               Portfolio A Portfolio B Portfolio C Portfolio D
                       GBP         EUR         USD         JPY
                 injection   injection   injection   injection
    2010-01-01        True        True        True        True
    2010-01-02       False       False       False       False
    2010-01-03       False       False        True       False
    2010-01-04        True        True        True        True
    2010-01-05       False       False        True       False
    
    mask = (df1.loc[:, pd.IndexSlice[:, :, 'injection']].fillna(0) != 0).any(axis=1)
    print (mask)
    2010-01-01     True
    2010-01-02    False
    2010-01-03     True
    2010-01-04     True
    2010-01-05     True
    dtype: bool
    
    print (df1[mask])
               Portfolio A           Portfolio B           Portfolio C            \
                       GBP                   EUR                   USD             
                    amount injection      amount injection      amount injection   
    2010-01-01        5777       100        5385       200        5419      4887   
    2010-01-03        4971         0        3824         0        4645      3424   
    2010-01-04        4827       200        3459       300        4552      3153   
    2010-01-05        5207         0        3670         0        4876      3358   
    
               Portfolio D            
                       JPY            
                    amount injection  
    2010-01-01         100     200.0  
    2010-01-03           0       0.0  
    2010-01-04         100     200.0  
    2010-01-05           0       0.0  
    

    如果使用掩码作为boolean DataFrame 得到NaN 其中False 值。

    【讨论】:

    • 您的答案缺少“投资组合 C”的“2010-01-03”和“2010-01-05”中的数据
    • 抱歉,需要什么输出?过滤所有值不等于0 的行或至少过滤一个不等于0 值的行?
    • 期望的输出是排除给定日期的所有值不等于0的任何行,我认为有必要先用零替换NaNs
    • 抱歉,所需的输出是排除给定日期的所有“注入”值等于0 的任何行,我还认为需要先将NaNs 替换为零。
    • 我编辑答案 - 还添加fillna(0),添加一个False 值到布尔掩码。
    猜你喜欢
    • 2021-12-01
    • 1970-01-01
    • 2017-08-25
    • 2020-07-13
    • 2022-12-07
    • 2018-08-20
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    相关资源
    最近更新 更多