2013-08-16 51 views
5

ho alcuni dati da un esperimento, e all'interno di ogni prova ci sono alcuni valori singoli, circondata da NA 's, che voglio compilare per l'intero processo:panda: riempimento valori mancanti all'interno di un gruppo

df = pd.DataFrame({'trial': [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3], 
    'cs_name': [np.nan, 'A1', np.nan, np.nan, np.nan, np.nan, 'B2', 
       np.nan, 'A1', np.nan, np.nan, np.nan]}) 
Out[177]: 
    cs_name trial 
0  NaN  1 
1  A1  1 
2  NaN  1 
3  NaN  1 
4  NaN  2 
5  NaN  2 
6  B2  2 
7  NaN  2 
8  A1  3 
9  NaN  3 
10  NaN  3 
11  NaN  3 

Sono in grado di inserire questi valori nell'intero processo utilizzando sia bfill() sia ffill(), ma mi chiedo se esiste un modo migliore per raggiungere questo obiettivo.

df['cs_name'] = df.groupby('trial')['cs_name'].ffill() 
df['cs_name'] = df.groupby('trial')['cs_name'].bfill() 

uscita prevista:

cs_name trial 
0  A1  1 
1  A1  1 
2  A1  1 
3  A1  1 
4  B2  2 
5  B2  2 
6  B2  2 
7  B2  2 
8  A1  3 
9  A1  3 
10  A1  3 
11  A1  3 

risposta

7

Un approccio alternativo consiste nell'utilizzare first_valid_index e un transform:

In [11]: g = df.groupby('trial') 

In [12]: g['cs_name'].transform(lambda s: s.loc[s.first_valid_index()]) 
Out[12]: 
0  A1 
1  A1 
2  A1 
3  A1 
4  B2 
5  B2 
6  B2 
7  B2 
8  A1 
9  A1 
10 A1 
11 A1 
Name: cs_name, dtype: object 

Questo dovrebbe essere più efficiente quindi utilizzando ffill seguita da una bfill. ..

E utilizzare questa opzione per modificare la colonna cs_name:

df['cs_name'] = g['cs_name'].transform(lambda s: s.loc[s.first_valid_index()]) 

Nota: Penso che sarebbe bello valorizzazione avere un metodo per afferrare il primo oggetto non nullo nei panda, in NumPy è an open request, I don' Penso che esista un metodo (potrei sbagliarmi!) ...

0

Se vuoi evitare l'errore che appare quando alcuni gruppi contengono solo NaN puoi fare quanto segue (nota che ho cambiato il df così da sono solo Nan per il gruppo che ha trial = 1):

df = pd.DataFrame({'trial': [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,1,1], 
'cs_name': [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, 'B2', np.nan, 
'A3', np.nan, np.nan, np.nan, np.nan,np.nan]}) 

g = data.groupby('trial') 

g['cs_name'].transform(lambda s: 'No values to aggregate' if 
    pd.isnull(s).all() == True else s.loc[s.first_valid_index()]) 

df['cs_name'] = g['cs_name'].transform(lambda s: 'No values to aggregate' if 
    pd.isnull(s).all() == True else s.loc[s.first_valid_index()])` 

In questo modo si introduce "Nessun valore da aggregare" (o qualsiasi altra cosa si desideri) quando il programma trova tutto il NaN per un determinato gruppo, invece di un errore.

Spero che questo aiuti :)

Federico

Problemi correlati