Skip to content

Benennung zurückgegebener Spalten in Pandas Aggregatfunktion?

Willkommen auf unserer Website, auf dieser Website finden Sie die Antwort auf das, wonach Sie suchen.

Lösung:

Für Pandas >= 0.25

Die Funktionalität, zurückgegebene Aggregatspalten zu benennen, wurde im Master-Zweig wieder eingeführt und ist für pandas 0.25 vorgesehen. Die neue Syntax lautet .agg(new_col_name=('col_name', 'agg_func'). Detailliertes Beispiel aus dem oben verlinkten PR:

In [2]: df = pd.DataFrame({'kind': ['cat', 'dog', 'cat', 'dog'],
   ...:                    'height': [9.1, 6.0, 9.5, 34.0],
   ...:                    'weight': [7.9, 7.5, 9.9, 198.0]})
   ...:

In [3]: df
Out[3]:
  kind  height  weight
0  cat     9.1     7.9
1  dog     6.0     7.5
2  cat     9.5     9.9
3  dog    34.0   198.0

In [4]: df.groupby('kind').agg(min_height=('height', 'min'), 
                               max_weight=('weight', 'max'))
Out[4]:
      min_height  max_weight
kind
cat          9.1         9.9
dog          6.0       198.0

Es wird auch möglich sein, mehrere Lambda-Ausdrücke mit dieser Syntax und der zweistufigen Umbenennungssyntax zu verwenden, die ich früher (unten) vorgeschlagen habe (siehe diesen PR). Wiederum aus dem Beispiel im PR kopiert:

In [2]: df = pd.DataFrame({"A": ['a', 'a'], 'B': [1, 2], 'C': [3, 4]})

In [3]: df.groupby("A").agg({'B': [lambda x: 0, lambda x: 1]})
Out[3]:
         B
   
A
a        0          1

und dann .rename(), oder in einem Schritt:

In [4]: df.groupby("A").agg(b=('B', lambda x: 0), c=('B', lambda x: 1))
Out[4]:
   b  c
A
a  0  0

Für Pandas <0>,25

Die derzeit akzeptierte Antwort von unutbu beschreibt einen guten Weg, dies in Pandas-Versionen <= 0.20 zu tun. Ab pandas 0.20 führt die Verwendung dieser Methode jedoch zu einer Warnung, die darauf hinweist, dass die Syntax in zukünftigen Versionen von pandas nicht mehr verfügbar sein wird.

Serie:

FutureWarning: Die Verwendung eines Diktats für eine Serie zur Aggregation ist veraltet und wird in einer zukünftigen Version entfernt.

DataFrames:

FutureWarning: Die Verwendung eines Diktats mit Umbenennung ist veraltet und wird in einer zukünftigen Version entfernt werden

Laut dem Changelog von Pandas 0.20 ist die empfohlene Methode zum Umbenennen von Spalten beim Aggregieren wie folgt.

# Create a sample data frame
df = pd.DataFrame({'A': [1, 1, 1, 2, 2],
                   'B': range(5),
                   'C': range(5)})

# ==== SINGLE COLUMN (SERIES) ====
# Syntax soon to be deprecated
df.groupby('A').B.agg({'foo': 'count'})
# Recommended replacement syntax
df.groupby('A').B.agg(['count']).rename(columns={'count': 'foo'})

# ==== MULTI COLUMN ====
# Syntax soon to be deprecated
df.groupby('A').agg({'B': {'foo': 'sum'}, 'C': {'bar': 'min'}})
# Recommended replacement syntax
df.groupby('A').agg({'B': 'sum', 'C': 'min'}).rename(columns={'B': 'foo', 'C': 'bar'})
# As the recommended syntax is more verbose, parentheses can
# be used to introduce line breaks and increase readability
(df.groupby('A')
    .agg({'B': 'sum', 'C': 'min'})
    .rename(columns={'B': 'foo', 'C': 'bar'})
)

Bitte lesen Sie das Changelog der Version 0.20 für weitere Details.

Update 2017-01-03 als Antwort auf den Kommentar von @JunkMechanic.

Mit dem alten Stil der Wörterbuchsyntax war es möglich, mehrere lambda Funktionen an .aggzu übergeben, da diese mit dem Schlüssel des übergebenen Wörterbuchs umbenannt werden würden:

>>> df.groupby('A').agg({'B': {'min': lambda x: x.min(), 'max': lambda x: x.max()}})

    B    
  max min
A        
1   2   0
2   4   3

Mehrere Funktionen können auch als Liste an eine einzelne Spalte übergeben werden:

>>> df.groupby('A').agg({'B': [np.min, np.max]})

     B     
  amin amax
A          
1    0    2
2    3    4

Dies funktioniert jedoch nicht mit Lambda-Funktionen, da diese anonym sind und alle zurückgeben zurückgeben, was eine Namenskollision verursacht:

>>> df.groupby('A').agg({'B': [lambda x: x.min(), lambda x: x.max]})
SpecificationError: Function names must be unique, found multiple named 

Um die SpecificationErrorzu vermeiden, können benannte Funktionen a priori definiert werden, anstatt sie mit lambda. Geeignete Funktionsnamen vermeiden auch den Aufruf von .rename auf den Datenrahmen zu vermeiden. Diese Funktionen können mit der gleichen Listensyntax wie oben übergeben werden:

>>> def my_min(x):
>>>     return x.min()

>>> def my_max(x):
>>>     return x.max()

>>> df.groupby('A').agg({'B': [my_min, my_max]})

       B       
  my_min my_max
A              
1      0      2
2      3      4

Damit wird die äußerste Ebene aus dem hierarchischen Spaltenindex entfernt:

df = data.groupby(...).agg(...)
df.columns = df.columns.droplevel(0)

Wenn Sie die äußerste Ebene beibehalten möchten, können Sie die Funktion ravel() auf die mehrstufige Spalte anwenden, um neue Bezeichnungen zu bilden:

df.columns = ["_".join(x) for x in df.columns.ravel()]

Zum Beispiel:

import pandas as pd
import pandas.rpy.common as com
import numpy as np

data = com.load_data('Loblolly')
print(data.head())
#     height  age Seed
# 1     4.51    3  301
# 15   10.89    5  301
# 29   28.72   10  301
# 43   41.74   15  301
# 57   52.70   20  301

df = data.groupby('Seed').agg(
    {'age':['sum'],
     'height':['mean', 'std']})
print(df.head())
#       age     height           
#       sum        std       mean
# Seed                           
# 301    78  22.638417  33.246667
# 303    78  23.499706  34.106667
# 305    78  23.927090  35.115000
# 307    78  22.222266  31.328333
# 309    78  23.132574  33.781667

df.columns = df.columns.droplevel(0)
print(df.head())

Ergibt

      sum        std       mean
Seed                           
301    78  22.638417  33.246667
303    78  23.499706  34.106667
305    78  23.927090  35.115000
307    78  22.222266  31.328333
309    78  23.132574  33.781667

Alternativ kann auch die erste Ebene des Indexes beibehalten werden:

df = data.groupby('Seed').agg(
    {'age':['sum'],
     'height':['mean', 'std']})
df.columns = ["_".join(x) for x in df.columns.ravel()]

ergibt

      age_sum   height_std  height_mean
Seed                           
301        78    22.638417    33.246667
303        78    23.499706    34.106667
305        78    23.927090    35.115000
307        78    22.222266    31.328333
309        78    23.132574    33.781667

Ich stimme mit dem OP überein, dass es natürlicher und konsistenter erscheint, die Ausgabespalten an derselben Stelle zu benennen und zu definieren (z.B. wie es mit tidyverse's summarize in R), aber ein Workaround in Pandas ist es, die neuen Spalten mit den gewünschten Namen über assignvor die Aggregation durchführt:

data.assign(
    f=data['column1'],
    mean=data['column2'],
    std=data['column2']
).groupby('Country').agg(dict(f=sum, mean=np.mean, std=np.std)).reset_index()

(Mit reset_index wird . 'Country', 'f', 'mean', und 'std' alle in reguläre Spalten mit einem separaten ganzzahligen Index).

Wenn Sie irgendwelche Unsicherheiten oder Möglichkeiten haben, unsere Bewertung zu klären, können Sie eine Notiz schreiben und wir werden uns diese mit großem Vergnügen ansehen.



Nutzen Sie unsere Suchmaschine

Suche
Generic filters

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.