2017-02-27 27 views
1

我想給我的DF添加一個新的等級(以便我可以使用pd.reindex來做其他事情)。我的DF主要有這樣的事情:在熊貓中添加等級到DF的中間

df = pd.DataFrame({('A','a'): [-1,-1,0,10,12], 
        ('A','b'): [0,1,2,3,-1], 
        ('A','c'): [-1,1,0,10,12], 
        ('A','d'): [1,1,2,3,-1], 
        ('B','a'): [-20,-10,0,10,20], 
        ('B','b'): [-200,-100,0,-1,200], 
        ('B','c'): [-20,-10,0,10,20], 
        ('B','d'): [-200,-100,0,100,200] 
}) 

##df 
    A    B 
    a b c d a b  c  d 
0 -1 0 1 1 -20 -200 -20 -200 
1 -1 1 -1 1 -10 -100 -10 -100 
2 0 2 0 2 0 0  0  0 
3 10 3 10 3 10 -1 10 100 
4 12 -1 12 -1 20 200 20 200 

我要指派新的水平鍵L1 = a + b,並L2 = c + d。我該怎麼做呢?

所需的輸出將

##df 
    A    B 
    L1  L2  L1  L2 
    a b c d a b  c  d 
0 -1 0 1 1 -20 -200 -20 -200 
1 -1 1 -1 1 -10 -100 -10 -100 
2 0 2 0 2 0 0  0  0 
3 10 3 10 3 10 -1 10 100 
4 12 -1 12 -1 20 200 20 200 

編輯:客觀是實現類似於被要求在here東西。這意味着對於同一個KEY,某些行將有NA s,具體取決於其他列的值。 例如如果我想通過分別檢測是否列過濾列acbd是否定的:

##df 
    A    B 
    L1  L2  L1  L2 
    a b c d a b  c  d 
0 -1 0 1 1 NA NA NA NA 
1 -1 1 -1 1 NA NA NA NA 
2 0 2 0 2 0 0  0  0 
3 10 3 10 3 NA NA 10 100 
4 NA NA NA NA 20 200 20 200 
+0

「,使然後我可以使用PD .reindex做其他事情「:或許我們可以更好地幫助你,如果你說明你的最終目的是什麼。 – Wli

+0

那麼,最終目的是非常相似,我在這裏問((http://stackoverflow.com/questions/42246373/replacing-values-in-a-2nd-level-column-on-multiindex-df-in -pandas)。現在的區別是,我必須對列「a」和「b」進行解析(正如我在前一篇文章中所做的那樣),對於'c'和'd'也是如此。 – Sosi

+0

我要改變工作示例以反映此評論 – Sosi

回答

2

您需要創建新的arraymap然後分配:

d = {'a':'L1','b':'L1','c':'L2','d':'L2'} 
a = df.columns.get_level_values(1).map(lambda x: d[x]) 
print (a) 
['L1' 'L1' 'L2' 'L2' 'L1' 'L1' 'L2' 'L2'] 

df.columns = [df.columns.get_level_values(0),a,df.columns.get_level_values(1)] 
#same as 
df.columns = pd.MultiIndex.from_arrays([df.columns.get_level_values(0), 
             df.columns.get_level_values(1).map(lambda x: d[x]), 
             df.columns.get_level_values(1)]) 
print (df) 
    A    B    
    L1  L2  L1  L2  
    a b c d a b c d 
0 -1 0 -1 1 -20 -200 -20 -200 
1 -1 1 1 1 -10 -100 -10 -100 
2 0 2 0 2 0 0 0 0 
3 10 3 10 3 10 -1 10 100 
4 12 -1 12 -1 20 200 20 200 

第二輸出是非常複雜,對我來說作品:

#filter columns 
idx = pd.IndexSlice 
mask = df.loc[:, idx[:,:,['b','d']]] < 0 
print (mask) 
     A    B  
     L1  L2  L1  L2 
     b  d  b  d 
0 False False True True 
1 False False True True 
2 False False False False 
3 False False True False 
4 True True False False 

#create mask to columns a,c 
mask1 = mask.reindex(columns=df.columns) 
mask1 = mask1.groupby(level=[0,1], axis=1).apply(lambda x: x.bfill(axis=1)) 
print (mask1) 
     A       B      
     L1   L2   L1   L2  
     a  b  c  d  a  b  c  d 
0 False False False False True True True True 
1 False False False False True True True True 
2 False False False False False False False False 
3 False False False False True True False False 
4 True True True True False False False False 

print (df.mask(mask1)) 
     A      B      
    L1   L2   L1   L2  
     a b  c d  a  b  c  d 
0 -1.0 0.0 -1.0 1.0 NaN NaN NaN NaN 
1 -1.0 1.0 1.0 1.0 NaN NaN NaN NaN 
2 0.0 2.0 0.0 2.0 0.0 0.0 0.0 0.0 
3 10.0 3.0 10.0 3.0 NaN NaN 10.0 100.0 
4 NaN NaN NaN NaN 20.0 200.0 20.0 200.0 

reindexmethod='bfill'另一種解決方案,但需要雙轉(我認爲這是錯誤 - 只在indexMultiIndexMultiIndexcolumns工作,沒有):

idx = pd.IndexSlice 
mask = df.loc[:, idx[:,['b','d']]] < 0 
print (mask) 
     A    B  
     b  d  b  d 
0 False False True True 
1 False False True True 
2 False False False False 
3 False False True False 
4 True True False False 

mask1 = mask.T.reindex(df.columns, method='bfill').T 
print (mask1) 
     A       B      
     a  b  c  d  a  b  c  d 
0 False False False False True True True True 
1 False False False False True True True True 
2 False False False False False False False False 
3 False False False False True True False False 
4 True True True True False False False False 

print (df.mask(mask1)) 
     A      B      
     a b  c d  a  b  c  d 
0 -1.0 0.0 -1.0 1.0 NaN NaN NaN NaN 
1 -1.0 1.0 1.0 1.0 NaN NaN NaN NaN 
2 0.0 2.0 0.0 2.0 0.0 0.0 0.0 0.0 
3 10.0 3.0 10.0 3.0 NaN NaN 10.0 100.0 
4 NaN NaN NaN NaN 20.0 200.0 20.0 200.0 
+0

我收到以下錯誤時設置'mask = df.loc [:, idx [:,:['b','d']]] <0':'KeyError:'MultiIndex Slicing要求索引完全放大tuple len(3), lexsort深度(2)''。將您的'mask'改爲'mask = df.loc [:, idx [:,['b','d']]] <0'解決了您的工作示例中的問題,併產生了正確的「print」。然而,在我的真實例子中,我也得到了一個類似的錯誤:「索引要完全排列的元組len(3),lexsort depth(1)'',並且我無法解決它並獲得正確的打印 – Sosi

+1

我想你首先需要'df = df.sort_index(axis = 1)',檢查[docs](http://pandas.pydata.org/pandas-docs/stable/advanced.html#sorting-a-multiindex) – jezrael

+0

謝謝很多@jezrael,我學到了很多這個和你以前的回答我的文章!我真的很感激! – Sosi