web-dev-qa-db-fra.com

Python Pandas: comment ajouter une toute nouvelle colonne à un bloc de données à l'intérieur d'une opération groupby / transform

Je veux marquer certains quantiles dans mes données, et pour chaque ligne du DataFrame, je voudrais l'entrée dans une nouvelle colonne appelée par ex. "xtile" pour conserver cette valeur.

Par exemple, supposons que je crée un bloc de données comme celui-ci:

import pandas, numpy as np
dfrm = pandas.DataFrame({'A':np.random.Rand(100), 
                         'B':(50+np.random.randn(100)), 
                         'C':np.random.randint(low=0, high=3, size=(100,))})

Et disons que j'écris ma propre fonction pour calculer le quintile de chaque élément d'un tableau. J'ai ma propre fonction pour cela, mais par exemple, je me réfère simplement à scipy.stats.mstats.mquantile.

import scipy.stats as st
def mark_quintiles(x, breakpoints):
    # Assume this is filled in, using st.mstats.mquantiles.
    # This returns an array the same shape as x, with an integer for which
    # breakpoint-bucket that entry of x falls into.

Maintenant, la vraie question est de savoir comment utiliser transform pour ajouter une nouvelle colonne aux données. Quelque chose comme ça:

def transformXtiles(dataFrame, inputColumnName, newColumnName, breaks):
    dataFrame[newColumnName] = mark_quintiles(dataFrame[inputColumnName].values, 
                                              breaks)
    return dataFrame

Puis:

dfrm.groupby("C").transform(lambda x: transformXtiles(x, "A", "A_xtile", [0.2, 0.4, 0.6, 0.8, 1.0]))

Le problème est que le code ci-dessus n'ajoutera pas la nouvelle colonne "A_xtile". Il retourne simplement ma trame de données inchangée. Si j'ajoute d'abord une colonne pleine de valeurs fictives, comme NaN, appelée "A_xtile", alors elle fait écrase avec succès cette colonne pour inclure les marques de quintile correctes.

Mais il est extrêmement gênant d'avoir à écrire d'abord dans la colonne pour quelque chose comme ça que je pourrais vouloir ajouter à la volée.

Notez qu'un simple apply ne fonctionnera pas ici, car il ne saura pas donner un sens aux tableaux de résultats éventuellement de taille différente pour chaque groupe.

32
ely

Quels problèmes rencontrez-vous avec apply? Cela fonctionne pour cet exemple de jouet ici et les longueurs de groupe sont différentes:

In [82]: df
Out[82]: 
   X         Y
0  0 -0.631214
1  0  0.783142
2  0  0.526045
3  1 -1.750058
4  1  1.163868
5  1  1.625538
6  1  0.076105
7  2  0.183492
8  2  0.541400
9  2 -0.672809

In [83]: def func(x):
   ....:     x['NewCol'] = np.nan
   ....:     return x
   ....: 

In [84]: df.groupby('X').apply(func)
Out[84]: 
   X         Y  NewCol
0  0 -0.631214     NaN
1  0  0.783142     NaN
2  0  0.526045     NaN
3  1 -1.750058     NaN
4  1  1.163868     NaN
5  1  1.625538     NaN
6  1  0.076105     NaN
7  2  0.183492     NaN
8  2  0.541400     NaN
9  2 -0.672809     NaN
37
Chang She