nhóm khung dữ liệu gấu trúc theo ngày giờ tháng


90

Xem xét tệp 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

Tôi có thể đọc nội dung này và định dạng lại cột ngày thành định dạng ngày giờ:

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

Tôi đã cố gắng nhóm dữ liệu theo tháng. Có vẻ như cần có một cách rõ ràng để truy cập tháng và nhóm theo tháng đó. Nhưng tôi dường như không thể làm được. Có ai biết làm thế nào không?

Những gì tôi hiện đang thử là lập chỉ mục lại vào ngày:

b.index=b['date']

Tôi có thể truy cập vào tháng như vậy:

b.index.month

Tuy nhiên, tôi dường như không thể tìm thấy một chức năng kết hợp với nhau theo tháng.

Câu trả lời:


174

Được quản lý để làm điều đó:

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

Hoặc là

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

51
Tôi nghĩ rằng cách pandonic hơn là để một trong hai sử dụng resample(khi nó cung cấp các chức năng mà bạn cần) hoặc sử dụng một TimeGrouper:df.groupby(pd.TimeGrouper(freq='M'))
Karl D.

10
để lấy kết quả DataFrame tổng hoặc trung bình, df.groupby(pd.TimeGrouper(freq='M')).sum()hoặcdf.groupby(pd.TimeGrouper(freq='M')).mean()
Alexandre

9
pd.TimeGrouperđã không còn được ủng hộ nữa pd.Groupermà có lợi hơn, linh hoạt hơn một chút nhưng vẫn có freqlevelđối số.
BallpointBen

phương pháp đầu tiên dường như không hoạt động. Nó đưa ra lỗi 'Đối tượng Dòng không có thuộc tính' tháng '' cho Dòng được tạo qua to_datetime.
ely

1
@ely Câu trả lời hoàn toàn dựa vào các dòng trong câu hỏi ban đầu, nơi bđược cung cấp một chỉ mục sau khi được đọc từ CSV. Thêm vào b.index = pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')sau dòng b = pd.read_csv('b.dat'). [Tôi cũng vừa chỉnh sửa câu trả lời.]
rowide

71

(cập nhật: 2018)

Lưu ý rằng pd.Timegrouperđược khấu hao và sẽ bị loại bỏ. Sử dụng thay thế:

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

2
Tìm tài liệu về Grouper tại đây và thông số tần số ( freq=...) tại đây . Một số ví dụ là freq=Dcho ngày , freq=Bcho ngày làm việc , freq=Wtrong tuần hoặc thậm chí freq=Qcho quý .
Kim

1
Tôi thấy hữu ích khi sử dụng 'key' để tránh phải lập chỉ mục lại df, như sau: df.groupby (pd.Grouper (key = 'your_date_column', freq = 'M'))
Edward

10

Một giải pháp tránh MultiIndex là tạo một datetimengày thiết lập cột mới = 1. Sau đó nhóm theo cột này. Ví dụ nhỏ dưới đây.

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

Lợi ích tinh tế của giải pháp này là, không giống như pd.Grouper, chỉ số cá mú được bình thường hóa vào đầu mỗi tháng chứ không phải cuối tháng, và do đó bạn có thể dễ dàng trích xuất các nhóm thông qua get_group:

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

Tính ra ngày cuối tháng 10 hơi rườm rà. pd.Grouper, kể từ v0.23, có hỗ trợ một conventiontham số, nhưng điều này chỉ áp dụng cho PeriodIndexcá mú.


8

Giải pháp hơi thay thế cho @ jpp nhưng xuất ra một YearMonthchuỗi:

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()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.