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.
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