pandy grupa dataframe według daty i godziny


90

Rozważ plik CSV:

string,date,number
a string,2/5/11 9:16am,1.0
a string,3/5/11 10:44pm,2.0
a string,4/22/11 12:07pm,3.0
a string,4/22/11 12:10pm,4.0
a string,4/29/11 11:59am,1.0
a string,5/2/11 1:41pm,2.0
a string,5/2/11 2:02pm,3.0
a string,5/2/11 2:56pm,4.0
a string,5/2/11 3:00pm,5.0
a string,5/2/14 3:02pm,6.0
a string,5/2/14 3:18pm,7.0

Mogę to przeczytać i przeformatować kolumnę z datą na format daty i godziny:

b=pd.read_csv('b.dat')
b['date']=pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')

Próbowałem pogrupować dane według miesięcy. Wygląda na to, że powinien istnieć oczywisty sposób dostępu do miesiąca i grupowania według niego. Ale nie mogę tego zrobić. Czy ktoś wie jak?

To, czego obecnie próbuję, to ponowne indeksowanie według daty:

b.index=b['date']

Mam dostęp do miesiąca w następujący sposób:

b.index.month

Jednak wydaje mi się, że nie mogę znaleźć funkcji, która mogłaby łączyć się w całość według miesiąca.

Odpowiedzi:


174

Udało się to zrobić:

b = pd.read_csv('b.dat')
b.index = pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')
b.groupby(by=[b.index.month, b.index.year])

Lub

b.groupby(pd.Grouper(freq='M'))  # update for v0.21+

51
Myślę, że bardziej pandoniczne sposoby to albo użycie resample(gdy zapewnia potrzebną funkcjonalność), albo użycie TimeGrouper:df.groupby(pd.TimeGrouper(freq='M'))
— Karl D.

10
aby uzyskać wynik sumę lub średnią DataFrame, df.groupby(pd.TimeGrouper(freq='M')).sum()lubdf.groupby(pd.TimeGrouper(freq='M')).mean()
— Alexandre

9
pd.TimeGrouperzostał uznany za przestarzały na korzyść pd.Grouper, który jest nieco bardziej elastyczny, ale nadal przyjmuje freqi levelargumentuje.
— BallpointBen

pierwsza metoda wydaje się nie działać. Daje błąd „Obiekt serii nie ma atrybutu„ miesiąc ”” dla serii utworzonej za pośrednictwem to_datetime.
— ely

1
@ely Odpowiedź niejawnie opiera się na wierszach z pierwotnego pytania, w których bpo odczytaniu z pliku CSV nadawany jest indeks. Dodaj b.index = pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')po linii b = pd.read_csv('b.dat'). [Właśnie zredagowałem odpowiedź.]
— goodside

71

(aktualizacja: 2018)

Pamiętaj, że pd.Timegrouperjest to amortyzowane i zostanie usunięte. Użyj zamiast tego:

 df.groupby(pd.Grouper(freq='M'))

2
Znajdź dokumentację Grouper tutaj i specyfikacje częstotliwości ( freq=...) tutaj . Niektóre przykłady są freq=Dza dni , freq=Bza dni roboczych , freq=Wdla tygodni lub nawet freq=Qna kwartały .
— Kim,

1
Uważam, że przydatne jest użycie `` klucza '', aby uniknąć konieczności ponownego zindeksowania df, w następujący sposób: df.groupby (pd.Grouper (key = 'your_date_column', freq = 'M'))
— Edward

10

Jednym z rozwiązań pozwalających uniknąć MultiIndex jest utworzenie nowej datetimekolumny ustawiania dnia = 1. Następnie pogrupuj według tej kolumny. Trywialny przykład poniżej.

df = pd.DataFrame({'Date': pd.to_datetime(['2017-10-05', '2017-10-20']),
                   'Values': [5, 10]})

# normalize day to beginning of month
df['YearMonth'] = df['Date'] - pd.offsets.MonthBegin(1)

# two alternative methods
df['YearMonth'] = df['Date'] - pd.to_timedelta(df['Date'].dt.day-1, unit='D')
df['YearMonth'] = df['Date'].map(lambda dt: dt.replace(day=1))

g = df.groupby('YearMonth')

res = g['Values'].sum()

# YearMonth
# 2017-10-01    15
# Name: Values, dtype: int64

Subtelną zaletą tego rozwiązania jest w przeciwieństwie do tego pd.Grouper, że indeks groupera jest normalizowany do początku każdego miesiąca, a nie do końca, dlatego można łatwo wyodrębnić grupy za pomocą get_group:

some_group = g.get_group('2017-10-01')

Obliczenie ostatniego dnia października jest nieco bardziej kłopotliwe. pd.Grouperod wersji 0.23 obsługuje conventionparametr, ale ma to zastosowanie tylko do PeriodIndexgroupera.


8

Nieco alternatywne rozwiązanie dla @ jpp, ale wyprowadzanie YearMonthciągu:

df['YearMonth'] = pd.to_datetime(df['Date']).apply(lambda x: '{year}-{month}'.format(year=x.year, month=x.month))

res = df.groupby('YearMonth')['Values'].sum()
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.