2016-10-26 9 views
1

Вопрос: Как фильтровать строки таким образом, что я возвращаю только строки, в которых инъекция не равна 0 или NaN, и не теряет значения других столбцов?Использование IndexSlice для фильтрации данных мультииндекса с помощью Pandas

У меня есть dataframe, созданный с помощью следующего кода:

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 

ответ

1

Я думаю, что вам нужно добавить fillna с any для проверки хотя бы одного значения 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 значения.

+0

В вашем ответе отсутствуют данные из '2010-01-03' и '2010-01-05' для 'Портфолио C' – toasteez

+0

Извините, какой желаемый результат? Фильтровать строки со всеми значениями, не равными '0', или фильтровать, по крайней мере, на одно значение не равное' 0'? – jezrael

+0

Желаемый вывод состоит в том, чтобы исключить любую строку для заданной даты, которая имеет все значения, не равные '0', я думаю, что сначала необходимо заменить« NaNs »нулем. – toasteez