64 votes

Renommer les colonnes de résultat de Pandas agrégation ("FutureWarning: à l'aide d'un dict avec le renommage est obsolète")

Je vais essayer de faire des agrégations sur une pandas bloc de données. Voici un exemple de code:

import pandas as pd

df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1"],
                  "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0]})

df.groupby(["User"]).agg({"Amount": {"Sum": "sum", "Count": "count"}})

Out[1]: 
      Amount      
         Sum Count
User              
user1   18.0     2
user2   20.5     3
user3   10.5     1

Qui génère le message d'avertissement suivant:

FutureWarning: à l'aide d'un dict avec le renommage est obsolète et sera supprimée dans une version future de retour super(DataFrameGroupBy, l'auto).agrégation(arg, *args, **kwargs)

Comment puis-je éviter cela?

94voto

Ted Petrou Points 20559

Utilisation groupby apply et le retour d'une Série de renommer des colonnes

Utiliser le groupby apply méthode pour effectuer une agrégation

  • Renomme les colonnes
  • Permet pour des espaces dans les noms
  • Vous permet d'ordonner le retour de l'colonnes de la manière que vous choisissez
  • Permet des interactions entre les colonnes
  • Renvoie un seul indice de niveau et PAS un MultiIndex

Pour ce faire:

  • créer une fonction personnalisée qui vous passent apply
  • Cette fonction personnalisée est transmis chaque groupe comme un DataFrame
  • De retour d'une Série
  • L'indice de la Série seront les nouvelles colonnes

Créer de fausses données

df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1", "user3"],
                  "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0, 9],
                  'Score': [9, 1, 8, 7, 7, 6, 9]})

enter image description here

créer une fonction qui retourne une Série
La variable x à l'intérieur de l' my_agg est un DataFrame

def my_agg(x):
    names = {
        'Amount mean': x['Amount'].mean(),
        'Amount std':  x['Amount'].std(),
        'Amount range': x['Amount'].max() - x['Amount'].min(),
        'Score Max':  x['Score'].max(),
        'Score Sum': x['Score'].sum(),
        'Amount Score Sum': (x['Amount'] * x['Score']).sum()}

    return pd.Series(names, index=['Amount range', 'Amount std', 'Amount mean',
                                   'Score Sum', 'Score Max', 'Amount Score Sum'])

Pass cette fonction personnalisée à l'égard du groupe - apply méthode

df.groupby('User').apply(my_agg)

enter image description here

Le gros inconvénient, c'est que cette fonction sera beaucoup plus lent que l' agg pour les agrégations cythonized

À l'aide d'un dictionnaire avec groupby agg méthode

À l'aide d'un dictionnaire de dictionnaires a été retiré en raison de sa complexité et quelque peu ambiguë. Il y a un débat en cours sur la façon d'améliorer cette fonctionnalité dans le futur sur github Ici, vous pouvez directement accéder à l'agrégation de colonne après l'égard du groupe d'appel. Tout simplement passer à une liste de tous les agréger les fonctions que vous souhaitez appliquer.

df.groupby('User')['Amount'].agg(['sum', 'count'])

Sortie

       sum  count
User              
user1  18.0      2
user2  20.5      3
user3  10.5      1

Il est toujours possible d'utiliser un dictionnaire explicitement désigner les différentes agrégations dans les différentes colonnes, comme ici, si il y avait une autre colonne numérique nommée Other.

df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1"],
              "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0],
              'Other': [1,2,3,4,5,6]})

df.groupby('User').agg({'Amount' : ['sum', 'count'], 'Other':['max', 'std']})

Sortie

      Amount       Other          
         sum count   max       std
User                              
user1   18.0     2     6  3.535534
user2   20.5     3     5  1.527525
user3   10.5     1     4       NaN

17voto

Jacob Stevenson Points 1553

Si vous remplacez le dictionnaire interne avec une liste de tuples, il se débarrasse de la message d'avertissement

import pandas as pd

df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1"],
                  "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0]})

df.groupby(["User"]).agg({"Amount": [("Sum", "sum"), ("Count", "count")]})

3voto

Jyothsna Harithsa Points 151

C'est ce que j'ai fait:

Créer un faux dataset:

import pandas as pd
df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1", "user3"],
                  "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0, 9],
                  'Score': [9, 1, 8, 7, 7, 6, 9]})
df

O/P:

    Amount  Score   User
0   10.0    9   user1
1   5.0 1   user2
2   8.0 8   user2
3   10.5    7   user3
4   7.5 7   user2
5   8.0 6   user1
6   9.0 9   user3

J'ai d'abord réalisé à l'Utilisateur de l'index, puis un groupby:

ans = df.set_index('User').groupby(level=0)['Amount'].agg([('Sum','sum'),('Count','count')])
ans

Solution:

    Sum Count
User        
user1   18.0    2
user2   20.5    3
user3   19.5    2

0voto

plankthom Points 26

Remplacer l'intérieur des dictionnaires avec une liste de correctement les fonctions nommées.

Pour renommer la fonction que j'utilise cette fonction d'utilité:

def aliased_aggr(aggr, name):
    if isinstance(aggr,str):
        def f(data):
            return data.agg(aggr)
    else:
        def f(data):
            return aggr(data)
    f.__name__ = name
    return f

Le groupe-par déclaration devient alors:


df.groupby(["User"]).agg({"Amount": [ 
    aliased_aggr("sum","Sum"),
    aliased_aggr("count","Count")
]

Si vous avez plus de, réutilisable agrégation spécifications, vous pouvez les convertir avec

def convert_aggr_spec(aggr_spec):
    return {
        col : [ 
            aliased_aggr(aggr,alias) for alias, aggr in aggr_map.items() 
        ]  
        for col, aggr_map in aggr_spec.items() 
    }

Donc on peut dire que

df.groupby(["User"]).agg(convert_aggr_spec({"Amount": {"Sum": "sum", "Count": "count"}}))

Voir aussi https://github.com/pandas-dev/pandas/issues/18366#issuecomment-476597674

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X