webentwicklung-frage-antwort-db.com.de

Ergebnisspalten aus Pandas-Aggregation umbenennen ("FutureWarning: Verwendung eines Diktats mit Umbenennung ist veraltet")

Ich versuche, einige Aggregationen in einem Pandas-Datenrahmen durchzuführen. Hier ist ein Beispielcode:

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

Welches die folgende Warnung erzeugt:

FutureWarning: Die Verwendung eines Diktiers mit Umbenennung ist veraltet und wird .__ sein. Wird in einer zukünftigen Version entfernt. Rückgabe (DataFrameGroupBy, self) .aggregate (arg, * args, ** kwargs)

Wie kann ich das vermeiden?

32
Victor Mayrink

Verwenden Sie groupby apply und geben Sie eine Reihe zurück, um die Spalten umzubenennen

Verwenden Sie die groupby apply-Methode, um eine Aggregation durchzuführen 

  • Benennt die Spalten um
  • Erlaubt Leerzeichen in den Namen
  • Damit können Sie die zurückgegebenen Spalten auf beliebige Weise anordnen
  • Ermöglicht Interaktionen zwischen Spalten
  • Gibt einen einstufigen Index und NICHT einen MultiIndex zurück

Um dies zu tun:

  • erstellen Sie eine benutzerdefinierte Funktion, die Sie an apply übergeben.
  • Diese benutzerdefinierte Funktion wird jeder Gruppe als DataFrame übergeben
  • Gib eine Serie zurück
  • Der Index der Serie werden die neuen Spalten sein

Falsche Daten erstellen

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

Benutzerdefinierte Funktion erstellen, die eine Serie zurückgibt
Die Variable x innerhalb von my_agg ist ein 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'])

Diese benutzerdefinierte Funktion an die groupby apply-Methode übergeben

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

 enter image description here

Der große Nachteil ist, dass diese Funktion für die cythonisierten Aggregationen viel langsamer ist als agg

Verwenden eines Wörterbuchs mit der Methode groupby agg

Die Verwendung eines Wörterbuchs von Wörterbüchern wurde aufgrund seiner Komplexität und etwas mehrdeutigen Natur entfernt. Es gibt eine laufende Diskussion darüber, wie Sie diese Funktionalität in Zukunft auf github verbessern können. Hier können Sie nach dem Group-by-Aufruf direkt auf die Aggregationsspalte zugreifen. Übergeben Sie einfach eine Liste aller Aggregationsfunktionen, die Sie anwenden möchten.

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

Ausgabe

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

Es ist immer noch möglich, ein Wörterbuch zu verwenden, um explizit unterschiedliche Aggregationen für verschiedene Spalten zu bezeichnen, wie hier, wenn es eine andere numerische Spalte mit dem Namen Other gab.

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']})

Ausgabe

      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
60
Ted Petrou

Wenn Sie das interne Wörterbuch durch eine Liste von Tupeln ersetzen, wird die Warnmeldung gelöscht

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")]})
8
Jacob Stevenson

Update für Pandas 0.25+ Aggregation Relabeling

import pandas as pd

print(pd.__version__)
#0.25.0

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")['Amount'].agg(Sum='sum', Count='count')

Ausgabe:

        Sum  Count
User              
user1  18.0      2
user2  20.5      3
user3  10.5      1
3
Scott Boston

Das habe ich gemacht:

Erstellen Sie ein gefälschtes 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

Ich habe zuerst den Benutzer zum Index gemacht und dann eine Gruppierung:

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

Lösung:

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

Ersetzen Sie die inneren Wörterbücher durch eine Liste korrekt benannter Funktionen.

So benennen Sie die Funktion um:

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
    return f

Die group-by-Anweisung wird dann zu:


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

Wenn Sie größere, wiederverwendbare Aggregationsspezifikationen haben, können Sie diese mit konvertieren

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() 
    }

So kann man sagen

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

Siehe auch https://github.com/pandas-dev/pandas/issues/18366#issuecomment-476597674

0
plankthom