2013-08-16 3 views
5

J'ai quelques données d'une expérience, et dans chaque essai il y a quelques valeurs simples, entourées de NA « s, que je veux remplir à l'ensemble du procès:pandas géants: Remplissage des valeurs manquantes dans un groupe

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 

Je suis en mesure de remplir ces valeurs dans l'ensemble de l'essai en utilisant à la fois bfill() et ffill(), mais je me demande s'il existe une meilleure façon d'y parvenir.

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

Sortie prévue:

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 

Répondre

7

Une autre approche consiste à utiliser first_valid_index et 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 

Cela devrait être plus efficace, puis en utilisant ffill suivi d'un bfill. ..

Et utiliser pour changer la colonne cs_name:

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

Note: Je pense que ce serait bien mise en valeur d'avoir une méthode pour saisir le premier objet non nul dans les pandas géants, en numpy il est an open request, je ne » Je pense qu'il y a actuellement une méthode (je peux me tromper!) ...

0

Si vous voulez éviter l'erreur qui apparaît lorsque certains groupes ne contiennent que NaN, vous pouvez faire ce qui suit (notez que j'ai changé la df donc il sont seulement Nan pour le groupe ayant l'essai = 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()])` 

De cette façon, vous entrez 'Aucune valeur à agréger' (ou ce que vous voulez) quand le programme trouve tout NaN pour un groupe particulier, au lieu d'une erreur.

Hope this helps :)

Federico

Questions connexes