2017-02-27 2 views
1

hinzufügen Ich möchte ein neues Level zu meinem DF hinzufügen (so dass ich dann pd.reindex verwenden kann, etwas anderes zu tun). Mein DF hat im Grunde so etwas wie dieses:Level zu Mitte von DF in Pandas

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 

Ich möchte Tasten neue Ebene L1 = a + b und L2 = c + d zuzuordnen. Wie mache ich das?

würde der gewünschte Ausgang

##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 

bearbeitet sein: Ziel ist etwas ähnliches zu erreichen, was in here gefragt wurde. Dies bedeutet, dass einige Zeilen für denselben KEY NA s haben, abhängig vom Wert anderer Spalten. Zum Beispiel wenn ich filternde Spalten a und c von jeweils geprüft wird, ob Spalten b und d sind negativ:

##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

„, so dass dann kann ich pd verwenden .reindex, etwas anderes zu tun ": Vielleicht können wir Ihnen besser helfen, wenn Sie angeben, was Ihr endgültiger Zweck ist. – Wli

+0

Nun, der endgültige Zweck ist sehr ähnlich zu dem, was ich hier gefragt hatte (http://StackOverflow.com/Questions/42246373/Replacing-Values-in-A-2nd-Level-Column-on-Multiindex-df-in -Pandas). Der Unterschied besteht nun darin, dass ich die Spalten "a" und "b" (wie im vorherigen Post) analysieren muss, und das Gleiche für "c" und "d". – Sosi

+0

Ich werde das Arbeitsbeispiel ändern, um diesen Kommentar zu reflektieren – Sosi

Antwort

2

Sie erstellen müssen neue array mit map und dann zuweisen:

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 

Zweite Ausgabe ist wirklich kompliziert , für mich funktioniert:

#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 

Eine andere Lösung mit reindex und method='bfill', ist aber notwendig Doppel transponieren (ich glaube, es Fehler ist - funktioniert nur mit MultiIndex in index, nicht mit MultiIndex in columns):

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

Ich bekomme den folgenden Fehler wenn Einstellung 'mask = df.loc [:, idx [:,:, ['b', 'd']]] <0':' KeyError: 'MultiIndex-Slicing erfordert, dass der Index vollständig lexsortiert ist tuple len (3), Lexsortiefe (2) ''. Ändern Sie Ihre 'mask' in' mask = df.loc [:, idx [:, ['b', 'd']]] <0' löst das Problem mit Ihrem Arbeitsbeispiel und ergibt den korrekten 'print'. Jedoch in meinem realen Beispiel bekomme ich auch einen ähnlichen Fehler 'der Index zu vollständig lexsortiert Tupel len (3), lexsort Tiefe (1) '', und ich bin nicht in der Lage, es zu lösen und den richtigen Druck – Sosi

+1

Ich denke, Sie brauche 'df = df.sort_index (axis = 1)' zuerst, überprüfe [docs] (http://pandas.pydata.org/pandas-docs/stable/advanced.html#sorting-a-multiindex) – jezrael

+0

Vielen Dank viel @jezrael, ich habe viel damit und deine vorherige Antwort auf meinen Beitrag gelernt! Ich bin wirklich dankbar! – Sosi

Verwandte Themen