2017-06-29 4 views
3

Ich studierte Pandas Indexierung und Auswahl und stieß auf Funktion pandas.DataFrame.where(). Diese Funktion hat axis und level für Ausrichtungszwecke. Zum Beispiel:pandas.DataFrame.where Ausrichtung

In [21]: df = pd.DataFrame(np.random.randn(8,4), index = pd.date_range('20000101',periods=8), columns = list('ABCD')) 

In [22]: df 
Out[22]: 
        A   B   C   D 
2000-01-01 -0.222193 0.764096 -2.000947 -1.162589 
2000-01-02 -0.387643 -0.497687 0.868227 -0.939663 
2000-01-03 1.001708 -0.761496 0.179564 -0.403473 
2000-01-04 0.469317 -0.161929 -0.844448 -0.211096 
2000-01-05 0.580083 -0.952382 0.105044 -0.648209 
2000-01-06 -0.312277 -0.762257 -0.894456 -1.169686 
2000-01-07 -1.446776 -1.276171 -1.466667 0.800513 
2000-01-08 -0.659035 -0.006725 -1.475503 0.353150 

In [23]: df.where(df>0, df.A, axis = 1) 
Out[23]: 
        A   B   C   D 
2000-01-01  NaN 0.764096  NaN  NaN 
2000-01-02  NaN  NaN 0.868227  NaN 
2000-01-03 1.001708  NaN 0.179564  NaN 
2000-01-04 0.469317  NaN  NaN  NaN 
2000-01-05 0.580083  NaN 0.105044  NaN 
2000-01-06  NaN  NaN  NaN  NaN 
2000-01-07  NaN  NaN  NaN 0.800513 
2000-01-08  NaN  NaN  NaN 0.353150 

In [24]: df.where(df>0, df.A, axis = 0) 
Out[24]: 
        A   B   C   D 
2000-01-01 -0.222193 0.764096 -0.222193 -0.222193 
2000-01-02 -0.387643 -0.387643 0.868227 -0.387643 
2000-01-03 1.001708 1.001708 0.179564 1.001708 
2000-01-04 0.469317 0.469317 0.469317 0.469317 
2000-01-05 0.580083 0.580083 0.105044 0.580083 
2000-01-06 -0.312277 -0.312277 -0.312277 -0.312277 
2000-01-07 -1.446776 -1.446776 -1.446776 0.800513 
2000-01-08 -0.659035 -0.659035 -0.659035 0.353150 

ich nicht die Verwendung von axis hier verstanden habe (ehrlich gesagt ich nicht das Konzept der Ausrichtung erhalten hat.) Ich weiß, dass Achse = 0 wird als „spaltenweise“ sein und Achse = 1 "zeilenweise". Könnte mir jemand die Ausgabe erklären (Konzept der Ausrichtung), auch die Verwendung von level Parameter.

Antwort

1

Beispiel für erklären:

np.random.seed(12) 
df = pd.DataFrame(np.random.randn(8,4), 
        index = pd.date_range('20000101',periods=8), 
        columns = list('ABCD')) 
print (df) 
        A   B   C   D 
2000-01-01 0.472986 -0.681426 0.242439 -1.700736 
2000-01-02 0.753143 -1.534721 0.005127 -0.120228 
2000-01-03 -0.806982 2.871819 -0.597823 0.472457 
2000-01-04 1.095956 -1.215169 1.342356 -0.122150 
2000-01-05 1.012515 -0.913869 -1.029530 1.209796 
2000-01-06 0.501872 0.138846 0.640761 0.527333 
2000-01-07 -1.154360 -2.213333 -1.681757 -1.788094 
2000-01-08 -2.218535 -0.647431 -0.528404 -0.039209 

#boolean mask by condition 
print (df>0) 
       A  B  C  D 
2000-01-01 True False True False 
2000-01-02 True False True False 
2000-01-03 False True False True 
2000-01-04 True False True False 
2000-01-05 True False False True 
2000-01-06 True True True True 
2000-01-07 False False False False 
2000-01-08 False False False False 

#without define value for replace False of mask values create NaNs 
print (df.where(df>0)) 
        A   B   C   D 
2000-01-01 0.472986  NaN 0.242439  NaN 
2000-01-02 0.753143  NaN 0.005127  NaN 
2000-01-03  NaN 2.871819  NaN 0.472457 
2000-01-04 1.095956  NaN 1.342356  NaN 
2000-01-05 1.012515  NaN  NaN 1.209796 
2000-01-06 0.501872 0.138846 0.640761 0.527333 
2000-01-07  NaN  NaN  NaN  NaN 
2000-01-08  NaN  NaN  NaN  NaN 

Für ersetzen False der Maske durch eine Series (Reihe) müssen axis=1 - Zeile wiederholt (broadcasting):

print (df.loc['2000-01-01']) 
A 0.472986 
B -0.681426 
C 0.242439 
D -1.700736 
Name: 2000-01-01 00:00:00, dtype: float64 

print (df.where(df>0, df.loc['2000-01-01'], axis = 1)) 
        A   B   C   D 
2000-01-01 0.472986 -0.681426 0.242439 -1.700736 
2000-01-02 0.753143 -0.681426 0.005127 -1.700736 
2000-01-03 0.472986 2.871819 0.242439 0.472457 
2000-01-04 1.095956 -0.681426 1.342356 -1.700736 
2000-01-05 1.012515 -0.681426 0.242439 1.209796 
2000-01-06 0.501872 0.138846 0.640761 0.527333 
2000-01-07 0.472986 -0.681426 0.242439 -1.700736 
2000-01-08 0.472986 -0.681426 0.242439 -1.700736 

Und für ersetzen durch Series (Spalte) brauchen axis=0 - Spalte wiederholt (broadcasting)

print (df.A) 
2000-01-01 0.472986 
2000-01-02 0.753143 
2000-01-03 -0.806982 
2000-01-04 1.095956 
2000-01-05 1.012515 
2000-01-06 0.501872 
2000-01-07 -1.154360 
2000-01-08 -2.218535 
Freq: D, Name: A, dtype: float64 

print (df.where(df>0, df.A, axis = 0)) 
        A   B   C   D 
2000-01-01 0.472986 0.472986 0.242439 0.472986 
2000-01-02 0.753143 0.753143 0.005127 0.753143 
2000-01-03 -0.806982 2.871819 -0.806982 0.472457 
2000-01-04 1.095956 1.095956 1.342356 1.095956 
2000-01-05 1.012515 1.012515 1.012515 1.209796 
2000-01-06 0.501872 0.138846 0.640761 0.527333 
2000-01-07 -1.154360 -1.154360 -1.154360 -1.154360 
2000-01-08 -2.218535 -2.218535 -2.218535 -2.218535 

Für ersetzen durch eine andere DataFrame:

df1 = pd.DataFrame(np.random.randint(10, size=(8,4)), 
        index = pd.date_range('20000101',periods=8), 
        columns = list('ABCD')) 
print (df1) 
      A B C D 
2000-01-01 5 3 5 0 
2000-01-02 2 9 6 4 
2000-01-03 7 6 2 3 
2000-01-04 2 6 4 5 
2000-01-05 0 0 5 4 
2000-01-06 0 3 7 9 
2000-01-07 6 8 6 1 
2000-01-08 4 9 6 5 

print (df.where(df>0, df1)) 
        A   B   C   D 
2000-01-01 0.472986 3.000000 0.242439 0.000000 
2000-01-02 0.753143 9.000000 0.005127 4.000000 
2000-01-03 7.000000 2.871819 2.000000 0.472457 
2000-01-04 1.095956 6.000000 1.342356 5.000000 
2000-01-05 1.012515 0.000000 5.000000 1.209796 
2000-01-06 0.501872 0.138846 0.640761 0.527333 
2000-01-07 6.000000 8.000000 6.000000 1.000000 
2000-01-08 4.000000 9.000000 6.000000 5.000000 

EDIT:

Erklären Ausrichtung:

Hier where Funktion mit 2 Objekten arbeitet (Series, DataFrame) und wenn wir auf gemeinsame Spalten stoßen, dann werden die Daten der gemeinsamen Indexnamen ar e ausgerichtet und Funktion wird angewendet. Hier stimmt also nur der Index A,B in Series mit der Spalte A,B von DataFrame überein, während andere Spalten NaNs erhalten.

s = pd.Series(np.random.randint(10, size=4) , index = list('ABEF')) 
print (s) 
A 5 
B 3 
E 5 
F 0 
dtype: int32 

print (df.where(df>0, s, axis=1)) 

        A   B   C   D 
2000-01-01 0.472986 3.000000 0.242439  NaN 
2000-01-02 0.753143 3.000000 0.005127  NaN 
2000-01-03 5.000000 2.871819  NaN 0.472457 
2000-01-04 1.095956 3.000000 1.342356  NaN 
2000-01-05 1.012515 3.000000  NaN 1.209796 
2000-01-06 0.501872 0.138846 0.640761 0.527333 
2000-01-07 5.000000 3.000000  NaN  NaN 
2000-01-08 5.000000 3.000000  NaN  NaN 

EDIT1:

Probe mit level Parameter:

Wenn DataFrameMultiIndex hat, dann ist es notwendig, Parameter hinzufügen level für die Spezifizierungsniveau Multiindex ist für die Funktion where verwendet werden.

np.random.seed(12) 
mux = pd.MultiIndex.from_arrays([pd.date_range('20000101',periods=8), list('aaaabbbb')], 
           names=('date', 'par')) 
df = pd.DataFrame(np.random.randn(8,4), 
        index = mux, 
        columns = list('ABCD')) 
print (df) 
         A   B   C   D 
date  par           
2000-01-01 a 0.472986 -0.681426 0.242439 -1.700736 
2000-01-02 a 0.753143 -1.534721 0.005127 -0.120228 
2000-01-03 a -0.806982 2.871819 -0.597823 0.472457 
2000-01-04 a 1.095956 -1.215169 1.342356 -0.122150 
2000-01-05 b 1.012515 -0.913869 -1.029530 1.209796 
2000-01-06 b 0.501872 0.138846 0.640761 0.527333 
2000-01-07 b -1.154360 -2.213333 -1.681757 -1.788094 
2000-01-08 b -2.218535 -0.647431 -0.528404 -0.039209 

s = pd.Series(np.random.randint(10, size=2) , index = list('ac')) 
print (s) 
a 5 
c 3 
dtype: int32 

print (df.where(df>0, s, axis=0, level=1)) 
         A   B   C   D 
date  par           
2000-01-01 a 0.472986 5.000000 0.242439 5.000000 
2000-01-02 a 0.753143 5.000000 0.005127 5.000000 
2000-01-03 a 5.000000 2.871819 5.000000 0.472457 
2000-01-04 a 1.095956 5.000000 1.342356 5.000000 
2000-01-05 b 1.012515  NaN  NaN 1.209796 
2000-01-06 b 0.501872 0.138846 0.640761 0.527333 
2000-01-07 b   NaN  NaN  NaN  NaN 
2000-01-08 b   NaN  NaN  NaN  NaN 
+0

Was ist der Parameter 'level'? –

+0

Meiner Meinung nach ist es für Multiindex in Spalten oder in Indizes. Nicht sehr oft benutzt. Gib mir etwas Zeit, versuche ich zu erklären (Englisch ist schwer für mich;)) – jezrael

+0

@AnshKumar - vielen Dank. – jezrael