2012-04-04 19 views
21

Tôi có chuỗi thời gian với nhiệt độ và bức xạ trong gấu trúc dataframe. Độ phân giải thời gian là 1 phút theo các bước thông thường.Làm cách nào để lấy mẫu lại một khung dữ liệu với các chức năng khác nhau được áp dụng cho mỗi cột?

import datetime 
import pandas as pd 
import numpy as np 

date_times = pd.date_range(datetime.datetime(2012, 4, 5, 8, 0), 
          datetime.datetime(2012, 4, 5, 12, 0), 
          freq='1min') 
tamb = np.random.sample(date_times.size) * 10.0 
radiation = np.random.sample(date_times.size) * 10.0 
frame = pd.DataFrame(data={'tamb': tamb, 'radiation': radiation}, 
        index=date_times) 
frame 
<class 'pandas.core.frame.DataFrame'> 
DatetimeIndex: 241 entries, 2012-04-05 08:00:00 to 2012-04-05 12:00:00 
Freq: T 
Data columns: 
radiation 241 non-null values 
tamb   241 non-null values 
dtypes: float64(2) 

Làm thế nào tôi có thể xuống mẫu dataframe này để độ phân giải của một giờ, tính toán giờ nghĩa cho nhiệt độ và giờ tổng đối với bức xạ?

Trả lời

41

Với gấu trúc 0,18 API mẫu lại thay đổi (xem docs). Vì vậy, cho gấu trúc> = 0,18 câu trả lời là:

In [31]: frame.resample('1H').agg({'radiation': np.sum, 'tamb': np.mean}) 
Out[31]: 
         tamb radiation 
2012-04-05 08:00:00 5.161235 279.507182 
2012-04-05 09:00:00 4.968145 290.941073 
2012-04-05 10:00:00 4.478531 317.678285 
2012-04-05 11:00:00 4.706206 335.258633 
2012-04-05 12:00:00 2.457873 8.655838 

Cũ Trả lời:

tôi trả lời câu hỏi của tôi để phản ánh các chuỗi thời gian thay đổi liên quan trong pandas >= 0.8 (tất cả các câu trả lời khác là lỗi thời).

Sử dụng gấu trúc> = 0,8 câu trả lời là:

In [30]: frame.resample('1H', how={'radiation': np.sum, 'tamb': np.mean}) 
Out[30]: 
         tamb radiation 
2012-04-05 08:00:00 5.161235 279.507182 
2012-04-05 09:00:00 4.968145 290.941073 
2012-04-05 10:00:00 4.478531 317.678285 
2012-04-05 11:00:00 4.706206 335.258633 
2012-04-05 12:00:00 2.457873 8.655838 
+2

Điều này có thể được mở rộng đến một danh sách các hàm cho mỗi cột: 'frame.resample ('1H', how = {'radiation': [np.sum, np.min], 'tamb': np.mean})'.DataFrame kết quả có một MultiIndex trên các cột của nó, với tên cột ban đầu là cấp 0 và tên hàm là cấp 1. –

+1

Để thêm vào nhận xét trước của tôi: thay vì danh sách hàm cho mỗi cột, bạn cũng có thể sử dụng từ điển, trong đó khóa là tên cột mới và giá trị là hàm để sử dụng: 'frame.resample ('1H', how = {'radiation': {'sum_rad': np.sum, 'min_rad': np.min} , 'tamb': np.mean}) ' –

+0

nói nếu bạn muốn thêm cột MỚI vào kết quả, chẳng hạn như count() của mỗi hàng trong khoảng thời gian mẫu lại. – codingknob

0

Bạn cần phải sử dụng groupby như vậy:

grouped = frame.groupby(lambda x: x.hour) 
grouped.agg({'radiation': np.sum, 'tamb': np.mean}) 
# Same as: grouped.agg({'radiation': 'sum', 'tamb': 'mean'}) 

với sản lượng hạnh phúc:

 radiation  tamb 
key_0      
8  298.581107 4.883806 
9  311.176148 4.983705 
10  315.531527 5.343057 
11  288.013876 6.022002 
12  5.527616 8.507670 

Vì vậy, trong bản chất tôi tách trên giá trị giờ và sau đó tính toán giá trị trung bình của tamb và tổng của radiation và trả lại số DataFrame (cách tiếp cận tương tự với R's ddply). Để biết thêm thông tin, tôi sẽ kiểm tra trang tài liệu cho groupby cũng như bài đăng trên blog this.

Edit: Để làm cho quy mô này tốt hơn một chút bạn có thể nhóm trên cả ban ngày và thời gian như vậy:

grouped = frame.groupby(lambda x: (x.day, x.hour)) 
grouped.agg({'radiation': 'sum', 'tamb': 'mean'}) 
      radiation  tamb 
key_0       
(5, 8) 298.581107 4.883806 
(5, 9) 311.176148 4.983705 
(5, 10) 315.531527 5.343057 
(5, 11) 288.013876 6.022002 
(5, 12) 5.527616 8.507670 
3

Bạn cũng có thể sử dụng phương pháp downsample asof của pandas.DateRange objects.

In [21]: hourly = pd.DateRange(datetime.datetime(2012, 4, 5, 8, 0), 
...       datetime.datetime(2012, 4, 5, 12, 0), 
...       offset=pd.datetools.Hour()) 

In [22]: frame.groupby(hourly.asof).size() 
Out[22]: 
key_0 
2012-04-05 08:00:00 60 
2012-04-05 09:00:00 60 
2012-04-05 10:00:00 60 
2012-04-05 11:00:00 60 
2012-04-05 12:00:00 1 
In [23]: frame.groupby(hourly.asof).agg({'radiation': np.sum, 'tamb': np.mean}) 
Out[23]: 
        radiation tamb 
key_0         
2012-04-05 08:00:00 271.54  4.491 
2012-04-05 09:00:00 266.18  5.253 
2012-04-05 10:00:00 292.35  4.959 
2012-04-05 11:00:00 283.00  5.489 
2012-04-05 12:00:00 0.5414  9.532 
+0

+1 cho sử dụng 'DateRange.asof' – diliop

3

Để khơi gợi bạn, trong gấu trúc 0.8.0 (đang được phát triển nặng trong timeseries chi nhánh trên GitHub), bạn sẽ có thể làm:

In [5]: frame.convert('1h', how='mean') 
Out[5]: 
        radiation  tamb 
2012-04-05 08:00:00 7.840989 8.446109 
2012-04-05 09:00:00 4.898935 5.459221 
2012-04-05 10:00:00 5.227741 4.660849 
2012-04-05 11:00:00 4.689270 5.321398 
2012-04-05 12:00:00 4.956994 5.093980 

Các phương pháp nêu trên là đúng sự chiến lược với phiên bản sản xuất gấu trúc hiện tại.

+0

Cảm ơn, nhưng những gì tôi muốn có một cái gì đó sẽ như' frame.convert ('1h', how = {'radiation': 'sum,' tamb ':' mean '}) '. Đây có phải là một lựa chọn trong 0.8? – bmu

+0

@ Wes McKinney điều này sẽ là 'resample' trong 0,8, phải không? – bmu

+0

Nếu bạn cập nhật câu trả lời, tôi sẽ chấp nhận nó. nếu không, bạn nên loại bỏ nó, tôi nghĩ, bởi vì nó sẽ hướng người dùng đến sai hướng. – bmu

Các vấn đề liên quan