ermöglicht die Angabe einer “groupby-Anweisung für ein Zielobjekt”. Insbesondere können Sie damit nach Datum gruppieren, auch wenn df.index ist kein DatetimeIndex:
df.groupby(pd.Grouper(freq='2D', level=-1))
Der level=-1 erzählt pd.Grouper um nach den Daten in der letzten Ebene des MultiIndex zu suchen. Darüber hinaus können Sie dies in Verbindung mit anderen Stufenwerten aus dem Index verwenden:
level_values = df.index.get_level_values
result = (df.groupby([level_values(i) for i in [0,1]]
+[pd.Grouper(freq='2D', level=-1)]).sum())
Sieht etwas komisch aus, aber using_Grouper erweist sich als viel schneller als mein ursprünglicher Vorschlag, using_reset_index:
import numpy as np
import pandas as pd
import datetime as DT
def using_Grouper(df):
level_values = df.index.get_level_values
return (df.groupby([level_values(i) for i in [0,1]]
+[pd.Grouper(freq='2D', level=-1)]).sum())
def using_reset_index(df):
df = df.reset_index(level=[0, 1])
return df.groupby(['State','City']).resample('2D').sum()
def using_stack(df):
# http://stackoverflow.com/a/15813787/190597
return (df.unstack(level=[0,1])
.resample('2D').sum()
.stack(level=[2,1])
.swaplevel(2,0))
def make_orig():
values_a = range(16)
values_b = range(10, 26)
states = ['Georgia']*8 + ['Alabama']*8
cities = ['Atlanta']*4 + ['Savanna']*4 + ['Mobile']*4 + ['Montgomery']*4
dates = pd.DatetimeIndex([DT.date(2012,1,1)+DT.timedelta(days = i) for i in range(4)]*4)
df = pd.DataFrame(
{'value_a': values_a, 'value_b': values_b},
index = [states, cities, dates])
df.index.names = ['State', 'City', 'Date']
return df
def make_df(N):
dates = pd.date_range('2000-1-1', periods=N)
states = np.arange(50)
cities = np.arange(10)
index = pd.MultiIndex.from_product([states, cities, dates],
names=['State', 'City', 'Date'])
df = pd.DataFrame(np.random.randint(10, size=(len(index),2)), index=index,
columns=['value_a', 'value_b'])
return df
df = make_orig()
print(using_Grouper(df))
ergibt
value_a value_b
State City Date
Alabama Mobile 2012-01-01 17 37
2012-01-03 21 41
Montgomery 2012-01-01 25 45
2012-01-03 29 49
Georgia Atlanta 2012-01-01 1 21
2012-01-03 5 25
Savanna 2012-01-01 9 29
2012-01-03 13 33
Hier ist ein Benchmark-Vergleich using_Grouper, using_reset_index, using_stack auf einem 5000-Zeilen-DataFrame:
In [30]: df = make_df(10)
In [34]: len(df)
Out[34]: 5000
In [32]: %timeit using_Grouper(df)
100 loops, best of 3: 6.03 ms per loop
In [33]: %timeit using_stack(df)
10 loops, best of 3: 22.3 ms per loop
In [31]: %timeit using_reset_index(df)
1 loop, best of 3: 659 ms per loop
Tut mir leid, ich habe nicht genug Erfahrung mit Pandas, um das zu sagen. Das obige ist eher ein Workaround als eine Lösung. df.reset_index kann eine langsame Operation sein und es wäre viel schöner, wenn dies ohne sie getan werden könnte.
– unutbu
4. Apr. ’13 um 13:26
Interessanterweise ist dies performanter als das Stapeln und Entstapeln: In [561]: timeit.timeit(“von hauptsächlich df importieren; df.reset_index(level=[0,1]).gruppiere nach([‘State’, ‘City’]).resample(‘2D’, how=’sum’)”, number=1000) Out[561]: 7.496185064315796 Zoll [562]: timeit.timeit(“von hauptsächlich df importieren; df.unstack(level=[0,1]).resample(‘2D’, how=’sum’).stack(level=[2,1]).swaplevel(2,0)”, Zahl=1000) Aus[562]: 10.618878841400146
– Schlangen McGee
4. Apr. ’13 um 15:43
Ich denke, die wahre Antwort hier lautet: “Wenn Sie diese Art von Berechnungen durchführen, sollten Sie mit einem Groupby-Objekt arbeiten, nicht mit einem hierarchischen Index.”
– Schlangen McGee
4. Apr. ’13 um 15:44
@unutbu “Entschuldigung, ich habe nicht genug Erfahrung mit Pandas, um das zu sagen.” Lustig das zu lesen, 1000+ Antworten später…
– Def_Os
16. September ’16 um 1:45
@Def_Os: Glücklicherweise 1000+ Antworten später kann ich sagen, dass es eine schnellere Lösung gibt – verwenden Sie pd.Grouper.
– unutbu
16. Sep. ’16 um 9:19
fpersyn
Du brauchst die groupby() Methode und versehen sie mit a pd.Grouper für jede Ebene Ihres MultiIndex, die Sie im resultierenden DataFrame beibehalten möchten. Sie können dann eine Operation Ihrer Wahl anwenden.
Um Datums- oder Zeitstempelebenen neu abzutasten, müssen Sie die freq Argument mit der Häufigkeit der Wahl — ein ähnlicher Ansatz mit pd.TimeGrouper() wird zu Gunsten von verworfen pd.Grouper() mit dem freq Argumente gesetzt.
Dies sollte Ihnen den DataFrame geben, den Sie benötigen:
… eine zeitbasierte groupby, gefolgt von einer Reduktionsmethode für jede ihrer Gruppen.
Daher verwenden groupby() sollte technisch der gleiche Vorgang sein wie bei der Verwendung .resample() auf einem DataFrame mit einem einzelnen Index.
Der gleiche Absatz weist auf die Kochbuchabschnitt zum Resampling für fortgeschrittene Beispiele, bei denen der Eintrag ‘Gruppierung mit einem MultiIndex’ für diese Frage sehr relevant ist. Hoffentlich hilft das.
Im Gegensatz zu vielen verworrenen Antworten auf dieses Problem ist dies eine leicht verständliche Lösung, die zu leicht lesbarem Code führt.
– Der McG
23. Mai ’19 um 15:59
Die beste Antwort.
– dsugasa
11. September ’19 um 15:45 Uhr
Eine Alternative mit Stack/Unstack
df.unstack(level=[0,1]).resample('2D', how='sum').stack(level=[2,1]).swaplevel(2,0)
value_a value_b
State City Date
Georgia Atlanta 2012-01-01 1 21
Alabama Mobile 2012-01-01 17 37
Montgomery 2012-01-01 25 45
Georgia Savanna 2012-01-01 9 29
Atlanta 2012-01-03 5 25
Alabama Mobile 2012-01-03 21 41
Montgomery 2012-01-03 29 49
Georgia Savanna 2012-01-03 13 33
Anmerkungen:
Keine Ahnung vom Leistungsvergleich
Möglicher Panda-Bug – stack(level=[2,1]) hat funktioniert, aber stack(level=[1,2]) fehlgeschlagen
Das war wirklich hilfreich!
– jarandaf
1. Apr. ’16 um 10:20
Ich hatte Probleme mit der Berechnung pct_change gleich danach. Ähnliches Problem wie hier. Am Ende habe ich folgendes gemacht: reset_index, sort_values, groupby, pct_change (wie im Link)
– Shadi
3. August ’17 um 9:58
Kamil Sindi
Das funktioniert:
df.groupby(level=[0,1]).apply(lambda x: x.set_index('Date').resample('2D', how='sum'))
value_a value_b
State City Date
Alabama Mobile 2012-01-01 17 37
2012-01-03 21 41
Montgomery 2012-01-01 25 45
2012-01-03 29 49
Georgia Atlanta 2012-01-01 1 21
2012-01-03 5 25
Savanna 2012-01-01 9 29
2012-01-03 13 33
Wenn die Spalte Datum Zeichenfolgen enthält, konvertieren Sie sie vorher in Datum/Uhrzeit:
df['Date'] = pd.to_datetime(df['Date'])
Josh D
Ich hatte das gleiche Problem, brach mir eine Weile den Kopf, aber dann las ich die Dokumentation der .resample Funktion in der 0.19.2 Dokumente, und ich sehe, es gibt ein neues kwarg namens “level”, die Sie verwenden können, um eine Ebene in einem MultiIndex anzugeben.
Beantwortet nicht wirklich die Frage, wann Sie ein Resampling durchführen müssen, während mehrere Indizes beibehalten werden. In den Dokumenten muss level kwarg ein datetime-ähnlicher Parameter sein und die Frage bezog sich auf sekundäre Gruppierungsspalten, die nicht auf Datetime basieren
– nachonachoman
1. Juni ’17 um 17:50
Geoff
Ich weiß, dass diese Frage ein paar Jahre alt ist, aber ich hatte das gleiche Problem und bin zu einer einfacheren Lösung gekommen, die 1 Zeile erfordert:
ts.unstack().T.resample('W', how='sum').T.stack() ist alles was es braucht! Sehr einfach und scheint ziemlich performant zu sein. Die Gurke, die ich einlese, ist 331M, also ist dies eine ziemlich kräftige Datenstruktur; Das Resampling dauert auf meinem MacBook Pro nur ein paar Sekunden.
Beantwortet nicht wirklich die Frage, wann Sie ein Resampling durchführen müssen, während mehrere Indizes beibehalten werden. In den Dokumenten muss level kwarg ein datetime-ähnlicher Parameter sein und die Frage bezog sich auf sekundäre Gruppierungsspalten, die nicht auf Datetime basieren
– nachonachoman
1. Juni ’17 um 17:50
LondonRob
Ich habe die Effizienz davon nicht überprüft, aber meine instinktive Art, Datetime-Operationen für einen Multi-Index durchzuführen, war eine Art manuellen “Split-Apply-Combine”-Prozess unter Verwendung eines Wörterbuchverständnisses.
Angenommen, Ihr DataFrame ist nicht indiziert. (Du kannst tun .reset_index() zuerst) funktioniert das wie folgt:
Nach den Spalten ohne Datum gruppieren
Setze “Datum” als Index und sample jedes Stück neu
Zusammenbau mit pd.concat
Der endgültige Code sieht wie folgt aus:
pd.concat({g: x.set_index("Date").resample("2D").mean()
for g, x in house.groupby(["State", "City"])})
.
2263500cookie-checkResampling innerhalb eines Pandas MultiIndexyes