2014-10-09 8 views
11

Ho un dataframe di Pandas e voglio creare una nuova colonna i cui valori sono quelli di un'altra colonna, spostati in basso di una riga. L'ultima riga dovrebbe mostrare NaN.Panda: sposta i valori di una riga all'interno di un gruppo

Il problema è che voglio farlo per gruppo, con l'ultima riga di ogni gruppo che mostra NaN. NON avere l'ultima riga di un gruppo "rubare" un valore da un gruppo che si trova adiacente nel dataframe.

Il mio tentativo di implementazione è stato piuttosto vergognosamente infranto, quindi sto chiaramente fraintendendo qualcosa di fondamentale.

df['B_shifted'] = df.groupby(['A'])['B'].transform(lambda x:x.values[1:]) 
+3

Funziona così: 'df ['B_shifted'] = df.groupby (['A']) ['B']. Transform (lambda x: x.shift())'? – EdChum

+3

Ogni volta che c'è qualcosa di leggermente complicato che voglio fare in Panda, c'è già una funzione scritta che fa proprio questo. Tranne che non so mai che esiste o come trovarlo! – jeffalstott

risposta

6

Spostamento lavora sull'uscita della clausola GroupBy:

>>> df = pandas.DataFrame(numpy.random.randint(1,3, (10,5)), columns=['a','b','c','d','e']) 
>>> df 
    a b c d e 
0 2 1 2 1 1 
1 2 1 1 1 1 
2 1 2 2 1 2 
3 1 2 1 1 2 
4 2 2 1 1 2 
5 2 2 2 2 1 
6 2 2 1 1 1 
7 2 2 2 1 1 
8 2 2 2 2 1 
9 2 2 2 2 1 


for k, v in df.groupby('a'): 
    print k 
    print 'normal' 
    print v 
    print 'shifted' 
    print v.shift(1) 

1 
normal 
    a b c d e 
2 1 2 2 1 2 
3 1 2 1 1 2 
shifted 
    a b c d e 
2 NaN NaN NaN NaN NaN 
3 1 2 2 1 2 
2 
normal 
    a b c d e 
0 2 1 2 1 1 
1 2 1 1 1 1 
4 2 2 1 1 2 
5 2 2 2 2 1 
6 2 2 1 1 1 
7 2 2 2 1 1 
8 2 2 2 2 1 
9 2 2 2 2 1 
shifted 
    a b c d e 
0 NaN NaN NaN NaN NaN 
1 2 1 2 1 1 
4 2 1 1 1 1 
5 2 2 1 1 2 
6 2 2 2 2 1 
7 2 2 1 1 1 
8 2 2 2 1 1 
9 2 2 2 2 1 
+0

il parametro predefinito per shift è 1 quindi non è necessario impostare 'shift (1)' sebbene sia un codice più chiaro specificandolo – EdChum

9

@ commento di EdChum è una risposta migliore a questa domanda, quindi sto postando qui per i posteri:

df['B_shifted'] = df.groupby(['A'])['B'].transform(lambda x:x.shift())

né parimenti

df['B_shifted'] = df.groupby(['A'])['B'].transform('shift').

La notazione precedente è più flessibile, ovviamente (ad es. Se si desidera passare da 2).

15

versioni più recenti di panda possono ora eseguire una shift su un gruppo:

df['B_shifted'] = df.groupby(['A'])['B'].shift(1) 

Si noti che quando si sposta verso il basso , è la fila prima che ha NaN.

Problemi correlati