wake-up-neo.com

Pandas: Richtige Methode zum Festlegen von Werten basierend auf der Bedingung für die Teilmenge des Multiindex-Datenrahmens

Ich bin mir nicht sicher, wie ich das ohne verkettete Zuweisungen machen soll (was wahrscheinlich sowieso nicht funktionieren würde, weil ich eine Kopie erstellen würde).

Ich werde keine Teilmenge eines Multiindex pandas dataframe) nehmen, auf Werte unter Null testen und sie auf Null setzen.

Beispielsweise:

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

df[df['A']<0] = 0.0

gibt

In [37]:

df

Out[37]:
    A   B
    a   b   a   b
0   -1  0   -20 -200
1   -1  1   -10 -100
2   0   2   0   0
3   10  3   10  100
4   12  -1  20  200

Was zeigt, dass es aufgrund der Bedingung nicht eingestellt werden konnte. Alternativ, wenn ich eine verkettete Aufgabe gemacht habe:

df.loc[:,'A'][df['A']<0] = 0.0

Dies ergibt das gleiche Ergebnis (und Einstellung mit Kopierwarnung)

Ich könnte jede Spalte auf der Grundlage der Bedingung durchlaufen, dass die erste Stufe diejenige ist, die ich möchte:

for one,two in df.columns.values:
    if one == 'A':
        df.loc[df[(one,two)]<0, (one,two)] = 0.0

was das gewünschte Ergebnis ergibt:

In [64]:

df

Out[64]:
    A   B
    a   b   a   b
0   0   0   -20 -200
1   0   1   -10 -100
2   0   2   0   0
3   10  3   10  100
4   12  0   20  200

Aber irgendwie gibt es meines Erachtens einen besseren Weg, als die Spalten zu durchlaufen. Was ist der beste Weg, um dies bei Pandas zu tun?

17
pbreach

Dies ist eine Anwendung von (und eine der Hauptmotive für die Verwendung von MultiIndex-Slicern), siehe docs hier

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

In [21]: df
Out[21]: 
    A      B     
    a  b   a    b
0  -1  0 -20 -200
1  -1  1 -10 -100
2   0  2   0    0
3  10  3  10  100
4  12 -1  20  200

In [22]: idx = pd.IndexSlice

In [23]: mask = df.loc[:,idx['A',:]]<0

In [24]: mask
Out[24]: 
       A       
       a      b
0   True  False
1   True  False
2  False  False
3  False  False
4  False   True

In [25]: df[mask] = 0

In [26]: df
Out[26]: 
    A      B     
    a  b   a    b
0   0  0 -20 -200
1   0  1 -10 -100
2   0  2   0    0
3  10  3  10  100
4  12  0  20  200

Da Sie mit der ersten Ebene des Spaltenindex arbeiten, funktioniert auch Folgendes. Das obige Beispiel ist allgemeiner. Nehmen wir an, Sie wollten dies für 'a' tun.

In [30]: df[df[['A']]<0] = 0

In [31]: df
Out[31]: 
    A      B     
    a  b   a    b
0   0  0 -20 -200
1   0  1 -10 -100
2   0  2   0    0
3  10  3  10  100
4  12  0  20  200
17
Jeff