panda dataframe groupoleh datetime month

91

Pertimbangkan file 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

Saya dapat membaca ini, dan memformat ulang kolom tanggal ke dalam format tanggal waktu:

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

Saya telah mencoba mengelompokkan data berdasarkan bulan. Sepertinya harus ada cara yang jelas untuk mengakses bulan dan mengelompokkannya. Tapi sepertinya aku tidak bisa melakukannya. Apakah ada yang tahu caranya?

Apa yang saat ini saya coba adalah mengindeks ulang pada tanggal:

b.index=b['date']

Saya dapat mengakses bulan seperti ini:

b.index.month

Namun saya tidak bisa menemukan fungsi untuk disatukan berdasarkan bulan.

atomh33ls
sumber

Jawaban:

175

Berhasil melakukannya:

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

Atau

b.groupby(pd.Grouper(freq='M'))  # update for v0.21+
atomh33ls
sumber
52
Saya pikir cara yang lebih pandonik adalah menggunakan resample(bila menyediakan fungsionalitas yang Anda butuhkan) atau menggunakan TimeGrouper:df.groupby(pd.TimeGrouper(freq='M'))
Karl D.
10
untuk mendapatkan hasil jumlah atau rata-rata DataFrame, df.groupby(pd.TimeGrouper(freq='M')).sum()ataudf.groupby(pd.TimeGrouper(freq='M')).mean()
Alexandre
9
pd.TimeGroupertelah ditinggalkan dalam mendukung pd.Grouper, yang sedikit lebih fleksibel tetapi masih membutuhkan freqdan levelargumen.
BallpointBen
metode pertama tampaknya tidak berhasil. Ini memberikan kesalahan, 'Objek Seri tidak memiliki atribut' bulan '' untuk Seri yang dibuat melalui to_datetime.
ely
1
@ely Jawabannya secara implisit bergantung pada baris dalam pertanyaan asli byang diberi indeks setelah dibaca dari CSV. Tambahkan b.index = pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')setelah garis b = pd.read_csv('b.dat'). [Saya baru saja mengedit jawabannya.]
selamat tinggal
72

(update: 2018)

Catatan yang pd.Timegrouperdisusutkan dan akan dihapus. Gunakan sebagai gantinya:

 df.groupby(pd.Grouper(freq='M'))
PandasRocks
sumber
2
Temukan dokumen Kerapu di sini dan spesifikasi frekuensi ( freq=...) di sini . Beberapa contoh freq=Duntuk hari , freq=Buntuk hari kerja , freq=Wselama berminggu - minggu atau bahkan freq=Quntuk kuartal .
Kim
1
Saya merasa berguna untuk menggunakan 'kunci' untuk menghindari keharusan mengindeks ulang df, sebagai berikut: df.groupby (pd.Grouper (key = 'your_date_column', freq = 'M'))
Edward
10

Salah satu solusi yang menghindari MultiIndex adalah membuat datetimekolom baru dengan pengaturan hari = 1. Kemudian kelompokkan berdasarkan kolom ini. Contoh sepele di bawah ini.

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

Manfaat halus dari solusi ini adalah, tidak seperti pd.Grouper, indeks kerapu dinormalisasi ke awal setiap bulan, bukan di akhir, dan oleh karena itu Anda dapat dengan mudah mengekstrak grup melalui get_group:

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

Menghitung hari terakhir bulan Oktober sedikit lebih rumit. pd.Grouper, mulai v0.23, memang mendukung conventionparameter, tetapi ini hanya berlaku untuk PeriodIndexkerapu.

jpp
sumber
8

Solusi sedikit alternatif untuk @ jpp tetapi mengeluarkan YearMonthstring:

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()
tsando
sumber