2013-07-17 17 views
10

Ho un dataframe panda come questo:Pandas dataframe: Verificare se i dati sono monotonicamente decrescente

Balance  Jan  Feb  Mar  Apr 
0 9.724135 0.389376 0.464451 0.229964 0.691504 
1 1.114782 0.838406 0.679096 0.185135 0.143883 
2 7.613946 0.960876 0.220274 0.788265 0.606402 
3 0.144517 0.800086 0.287874 0.223539 0.206002 
4 1.332838 0.430812 0.939402 0.045262 0.388466 

Vorrei raggruppare le righe per capire se i valori di Jan attraverso a aprile sono monotona decrescente (come nelle righe indicizzate 1 e 3) o meno, e quindi sommare i saldi per ciascun gruppo, cioè alla fine vorrei finire con due numeri (1.259299 per le serie temporali decrescenti e 18.670919 per gli altri).

Penso che se potessi aggiungere una colonna "sta diminuendo" contando i booleani potrei fare le somme usando i panda "groupby", ma come creo questa colonna?

Grazie, Anna

+0

Stavi pensando a una colonna di booleani per ogni mese? Hai il passaggio da decrescere a crescente accadimento su diverse file. – TomAugspurger

+0

Ah non importa. Intendi decrescente di mese in mese. Attraverso le colonne. – TomAugspurger

risposta

9

Si potrebbe utilizzare una delle funzioni da is_monotonic Algos:

In [10]: months = ['Jan', 'Feb', 'Mar', 'Apr'] 

In [11]: df.loc[:, months].apply(lambda x: pd.algos.is_monotonic_float64(-x)[0], 
             axis=1) 
Out[11]: 
0 False 
1  True 
2 False 
3  True 
4 False 
dtype: bool 

I is_monotonic verifica se un array è diminuendo quindi il-x.values.

(Questo sembra sostanzialmente più veloce rispetto alla soluzione di Tom, anche utilizzando il piccolo dataframe disponibile.)

+2

@TomAugspurger Penso che la parola che stai cercando sia "pandastic" ... \ * ahem \ *. –

+0

Grazie Andy, funziona perfettamente. Ho una domanda un po 'stupida - ho cercato di trovare la documentazione sulla funzione is_monotonic e non riesco a trovarla online. Ti capita di avere un link? – Anne

+0

Un'altra domanda: non posso semplicemente scrivere '-x' invece di' -x.values' in 'df.loc [:, mesi] .apply (lambda x: pd.algos.is_monotonic_float64 (-x.valori) [0], l'asse = 1) '? L'ho provato e * sembrava * funzionare. – Anne

5
months = ['Jan', 'Feb', 'Mar', 'Apr'] 

Trasposizione modo che possiamo usare il metodo diff (che non prende un argomento asse). Compiliamo la prima riga (gennaio) con 0. Altrimenti è NaN.

In [77]: df[months].T.diff().fillna(0) <= 0 
Out[77]: 
     0  1  2  3  4 
Jan True True True True True 
Feb False True True True False 
Mar True True False True True 
Apr False True True True False 

Per verificare se è monotonicamente decrescente, utilizzare il metodo .all(). Di default questo va oltre l'asse 0, le righe (mesi).

In [78]: is_decreasing = (df[months].T.diff().fillna(0) <= 0).all() 

In [79]: is_decreasing 
Out[79]: 
0 False 
1  True 
2 False 
3  True 
4 False 
dtype: bool 

In [80]: df['is_decreasing'] = is_decreasing 

In [81]: df 
Out[81]: 
    Balance  Jan  Feb  Mar  Apr is_decreasing 
0 9.724135 0.389376 0.464451 0.229964 0.691504   False 
1 1.114782 0.838406 0.679096 0.185135 0.143883   True 
2 7.613946 0.960876 0.220274 0.788265 0.606402   False 
3 0.144517 0.800086 0.287874 0.223539 0.206002   True 
4 1.332838 0.430812 0.939402 0.045262 0.388466   False 

E come da te suggerito, possiamo GroupBy is_decreasing e somma:

In [83]: df.groupby('is_decreasing')['Balance'].sum() 
Out[83]: 
is_decreasing 
False   18.670919 
True    1.259299 
Name: Balance, dtype: float64 

E 'in momenti come questi quando amo i panda.

0

Pandas 0.19 aggiunto un pubblico Series.is_monotonic API (come detto, il modulo algos è documentato e non in grado di conservare.) .

Ci sono anche is_monotonic_increasing e is_monotonic_decreasing. Tutti e 3 non sono rigidi (ad esempio is_monotonic_decreasing verificare se la sequenza è decrescente o uguale a), ma è possibile combinarli con is_unqiue se è necessario il rigore.

my_df = pd.DataFrame({'A':[1,2,3],'B':[1,1,1],'C':[3,2,1]}) 
my_df 
Out[32]: 
    A B C 
0 1 1 3 
1 2 1 2 
2 3 1 1 

my_df.apply(lambda x: x.is_monotonic) 
Out[33]: 
A  True 
B  True 
C False 
dtype: bool