So gruppieren Sie Pandas DataFrame-Einträge nach Datum in einer nicht eindeutigen Spalte

82

Ein Pandas DataFrameenthält eine Spalte mit dem Namen "date", die nicht eindeutige datetimeWerte enthält. Ich kann die Zeilen in diesem Rahmen gruppieren mit:

data.groupby(data['date'])

Dies teilt die Daten jedoch durch die datetimeWerte auf. Ich möchte diese Daten nach dem in der Spalte "Datum" gespeicherten Jahr gruppieren. Diese Seite zeigt, wie in Fällen, in denen der Zeitstempel als Index verwendet wird, nach Jahr gruppiert wird, was in meinem Fall nicht der Fall ist.

Wie erreiche ich diese Gruppierung?

Boris Gorelik
quelle
Für diejenigen, die 2017+ hierher kommen, gibt es mehrere neue Möglichkeiten, um nach einer bestimmten Zeitspanne zu gruppieren. Siehe diese Antwort unten
Ted Petrou

Antworten:

90

Ich benutze Pandas 0.16.2. Dies hat eine bessere Leistung bei meinem großen Datensatz:

data.groupby(data.date.dt.year)

Mit Hilfe der dtOption und dem Spiel mit weekofyear, dayofweekusw. wird viel einfacher.

DACW
quelle
Stimmen Sie überein, dies scheint die pandaische Art zu sein, auf Datumsattribute für eine Serie zuzugreifen.
Dan Nguyen
73

Die Lösung von ecatmur wird gut funktionieren. Dies ist jedoch eine bessere Leistung bei großen Datenmengen:

data.groupby(data['date'].map(lambda x: x.year))
Wes McKinney
quelle
9
Warum kartieren statt bewerben?
Gus
1
Afaik hat mapnormalerweise einige gute Effizienzqualitäten bei der Anwendung beliebiger Funktionen im Vergleich zur einfachen Verwendung apply.
Coolio2654
24

Dies ist möglicherweise einfacher mit einem Beispieldatensatz zu erklären.

Beispieldaten erstellen

Nehmen wir an, wir haben eine einzelne Spalte mit Zeitstempeln dateund eine weitere Spalte, für die wir eine Aggregation durchführen möchten a.

df = pd.DataFrame({'date':pd.DatetimeIndex(['2012-1-1', '2012-6-1', '2015-1-1', '2015-2-1', '2015-3-1']),
                   'a':[9,5,1,2,3]}, columns=['date', 'a'])

df

        date  a
0 2012-01-01  9
1 2012-06-01  5
2 2015-01-01  1
3 2015-02-01  2
4 2015-03-01  3

Es gibt verschiedene Möglichkeiten, nach Jahr zu gruppieren

  • Verwenden Sie den dt-Accessor mit yearEigenschaft
  • Geben Sie einen dateIndex ein und verwenden Sie die anonyme Funktion, um auf das Jahr zuzugreifen
  • Verwenden Sie die resampleMethode
  • In Pandas konvertieren Periode

.dtAccessor mit yearEigentum

Wenn Sie eine Spalte (und keinen Index) von Pandas-Zeitstempeln haben, können Sie mit dem dtAccessor auf viele weitere Eigenschaften und Methoden zugreifen . Zum Beispiel:

df['date'].dt.year

0    2012
1    2012
2    2015
3    2015
4    2015
Name: date, dtype: int64

Wir können dies verwenden, um unsere Gruppen zu bilden und einige Aggregationen für eine bestimmte Spalte zu berechnen:

df.groupby(df['date'].dt.year)['a'].agg(['sum', 'mean', 'max'])

      sum  mean  max
date                
2012   14     7    9
2015    6     2    3

Setzen Sie das Datum in den Index und verwenden Sie die anonyme Funktion, um auf das Jahr zuzugreifen

Wenn Sie die Datumsspalte als Index festlegen, wird sie zu einem DateTimeIndex mit denselben Eigenschaften und Methoden wie der dtAccessor normale Spalten

df1 = df.set_index('date')
df1.index.year

Int64Index([2012, 2012, 2015, 2015, 2015], dtype='int64', name='date')

Interessanterweise können Sie bei Verwendung der groupby-Methode eine Funktion übergeben. Diese Funktion wird implizit an den DataFrame-Index übergeben. So können wir das gleiche Ergebnis von oben mit folgendem erhalten:

df1.groupby(lambda x: x.year)['a'].agg(['sum', 'mean', 'max'])

      sum  mean  max
2012   14     7    9
2015    6     2    3

Verwenden Sie die resampleMethode

Wenn sich Ihre Datumsspalte nicht im Index befindet, müssen Sie die Spalte mit dem onParameter angeben . Sie müssen auch den Offset-Alias als Zeichenfolge angeben .

df.resample('AS', on='date')['a'].agg(['sum', 'mean', 'max'])

             sum  mean  max
date                       
2012-01-01  14.0   7.0  9.0
2013-01-01   NaN   NaN  NaN
2014-01-01   NaN   NaN  NaN
2015-01-01   6.0   2.0  3.0

In Pandas konvertieren Periode

Sie können die Datumsspalte auch in ein Pandas Period-Objekt konvertieren. Wir müssen den Offset-Alias ​​als Zeichenfolge übergeben, um die Länge der Periode zu bestimmen.

df['date'].dt.to_period('A')

0   2012
1   2012
2   2015
3   2015
4   2015
Name: date, dtype: object

Wir können dies dann als Gruppe verwenden

df.groupby(df['date'].dt.to_period('Y'))['a'].agg(['sum', 'mean', 'max'])


      sum  mean  max
2012   14     7    9
2015    6     2    3
Ted Petrou
quelle
to_period('A')Wofür ist das ('A') in der letzten Methode, die Sie verwenden ?
Shiv_90
2
@ Shiv_90 das 'A'ist ein Zeitreihen-Offset-Alias: pandas.pydata.org/pandas-docs/stable/…
ptim
Welche Methode würden Sie empfehlen, wenn eine separate Spalte "Datum" ebenfalls gespeichert werden soll? Wenn ich beispielsweise die einfache .dt.yearMethode ausführe und sie in einem neuen Datenrahmen speichere, werden die Daten als Indizes gespeichert. Dies wird problematisch, wenn ich die Daten plotten muss, da die Spalte "Datumsangaben" nicht wirklich vorhanden ist, sondern nur die drei bereitgestellt in.agg()
Shiv_90
13

Das sollte funktionieren:

data.groupby(lambda x: data['date'][x].year)
ecatmur
quelle
0

das wird auch funktionieren

data.groupby(data['date'].dt.year)

Chetan Kabra
quelle
Sollte funktionieren, gibt aber bei Ausführung die Position des Objekts im Speicher aus, aber keine echte Ausgabe. <pandas.core.groupby.DataFrameGroupBy object at 0x10d7f6438>ist das, was ich bekomme, wenn ich hingerichtet werde.
Shiv_90