Vâng, tôi có thể nghĩ ra một vài cách khác nhau. (1) về cơ bản thổi lên các khung dữ liệu bằng cách hợp nhất trên company
và sau đó lọc trên các cửa sổ 30 ngày sau khi hợp nhất. Điều này nên được nhanh chóng nhưng có thể sử dụng rất nhiều bộ nhớ. (2) Di chuyển việc hợp nhất và lọc trên cửa sổ 30 ngày thành một nhóm. Điều này dẫn đến một hợp nhất đối với từng nhóm vì vậy nó sẽ chậm hơn nhưng nó phải sử dụng ít bộ nhớ
Lựa chọn # 1
Giả sử dữ liệu của bạn trông giống như sau (tôi mở rộng dữ liệu mẫu của bạn):
print df
company date measure
0 0 2010-01-01 10
1 0 2010-01-15 10
2 0 2010-02-01 10
3 0 2010-02-15 10
4 0 2010-03-01 10
5 0 2010-03-15 10
6 0 2010-04-01 10
7 1 2010-03-01 5
8 1 2010-03-15 5
9 1 2010-04-01 5
10 1 2010-04-15 5
11 1 2010-05-01 5
12 1 2010-05-15 5
print windows
company end_date
0 0 2010-02-01
1 0 2010-03-15
2 1 2010-04-01
3 1 2010-05-15
Tạo một ngày đầu cho các cửa sổ 30 ngày:
windows['beg_date'] = (windows['end_date'].values.astype('datetime64[D]') -
np.timedelta64(30,'D'))
print windows
company end_date beg_date
0 0 2010-02-01 2010-01-02
1 0 2010-03-15 2010-02-13
2 1 2010-04-01 2010-03-02
3 1 2010-05-15 2010-04-15
Bây giờ làm một hợp nhất và sau đó chọn dựa o n nếu date
thác trong vòng beg_date
và end_date
:
df = df.merge(windows,on='company',how='left')
df = df[(df.date >= df.beg_date) & (df.date <= df.end_date)]
print df
company date measure end_date beg_date
2 0 2010-01-15 10 2010-02-01 2010-01-02
4 0 2010-02-01 10 2010-02-01 2010-01-02
7 0 2010-02-15 10 2010-03-15 2010-02-13
9 0 2010-03-01 10 2010-03-15 2010-02-13
11 0 2010-03-15 10 2010-03-15 2010-02-13
16 1 2010-03-15 5 2010-04-01 2010-03-02
18 1 2010-04-01 5 2010-04-01 2010-03-02
21 1 2010-04-15 5 2010-05-15 2010-04-15
23 1 2010-05-01 5 2010-05-15 2010-04-15
25 1 2010-05-15 5 2010-05-15 2010-04-15
Bạn có thể tính toán số tiền khoảng thời gian 30 ngày bằng cách nhóm trên company
và end_date
:
print df.groupby(['company','end_date']).sum()
measure
company end_date
0 2010-02-01 20
2010-03-15 30
1 2010-04-01 10
2010-05-15 15
Lựa chọn # 2 Move tất cả sáp nhập vào một groupby.Điều này nên được tốt hơn vào bộ nhớ nhưng tôi sẽ nghĩ chậm hơn nhiều:
windows['beg_date'] = (windows['end_date'].values.astype('datetime64[D]') -
np.timedelta64(30,'D'))
def cond_merge(g,windows):
g = g.merge(windows,on='company',how='left')
g = g[(g.date >= g.beg_date) & (g.date <= g.end_date)]
return g.groupby('end_date')['measure'].sum()
print df.groupby('company').apply(cond_merge,windows)
company end_date
0 2010-02-01 20
2010-03-15 30
1 2010-04-01 10
2010-05-15 15
Một tùy chọn khác Bây giờ nếu cửa sổ của bạn không bao giờ chồng lên nhau (như trong các dữ liệu chẳng hạn), bạn có thể làm một cái gì đó như sau như một sự thay thế điều đó không 't thổi lên một dataframe nhưng là khá nhanh:
windows['date'] = windows['end_date']
df = df.merge(windows,on=['company','date'],how='outer')
print df
company date measure end_date
0 0 2010-01-01 10 NaT
1 0 2010-01-15 10 NaT
2 0 2010-02-01 10 2010-02-01
3 0 2010-02-15 10 NaT
4 0 2010-03-01 10 NaT
5 0 2010-03-15 10 2010-03-15
6 0 2010-04-01 10 NaT
7 1 2010-03-01 5 NaT
8 1 2010-03-15 5 NaT
9 1 2010-04-01 5 2010-04-01
10 1 2010-04-15 5 NaT
11 1 2010-05-01 5 NaT
12 1 2010-05-15 5 2010-05-15
merge này về cơ bản chèn ngày kết thúc cửa sổ của bạn vào dataframe và sau đó san lấp ngày kết thúc (theo cá nhân) sẽ cung cấp cho bạn một cấu trúc dễ dàng tạo ra bạn tổng kết các cửa sổ :
df['end_date'] = df.groupby('company')['end_date'].apply(lambda x: x.bfill())
print df
company date measure end_date
0 0 2010-01-01 10 2010-02-01
1 0 2010-01-15 10 2010-02-01
2 0 2010-02-01 10 2010-02-01
3 0 2010-02-15 10 2010-03-15
4 0 2010-03-01 10 2010-03-15
5 0 2010-03-15 10 2010-03-15
6 0 2010-04-01 10 NaT
7 1 2010-03-01 5 2010-04-01
8 1 2010-03-15 5 2010-04-01
9 1 2010-04-01 5 2010-04-01
10 1 2010-04-15 5 2010-05-15
11 1 2010-05-01 5 2010-05-15
12 1 2010-05-15 5 2010-05-15
df = df[df.end_date.notnull()]
df['beg_date'] = (df['end_date'].values.astype('datetime64[D]') -
np.timedelta64(30,'D'))
print df
company date measure end_date beg_date
0 0 2010-01-01 10 2010-02-01 2010-01-02
1 0 2010-01-15 10 2010-02-01 2010-01-02
2 0 2010-02-01 10 2010-02-01 2010-01-02
3 0 2010-02-15 10 2010-03-15 2010-02-13
4 0 2010-03-01 10 2010-03-15 2010-02-13
5 0 2010-03-15 10 2010-03-15 2010-02-13
7 1 2010-03-01 5 2010-04-01 2010-03-02
8 1 2010-03-15 5 2010-04-01 2010-03-02
9 1 2010-04-01 5 2010-04-01 2010-03-02
10 1 2010-04-15 5 2010-05-15 2010-04-15
11 1 2010-05-01 5 2010-05-15 2010-04-15
12 1 2010-05-15 5 2010-05-15 2010-04-15
df = df[(df.date >= df.beg_date) & (df.date <= df.end_date)]
print df.groupby(['company','end_date']).sum()
measure
company end_date
0 2010-02-01 20
2010-03-15 30
1 2010-04-01 10
2010-05-15 15
Một cách khác là định lại mẫu dữ liệu đầu tiên của bạn thành dữ liệu hàng ngày và sau đó tính toán rolling_sums với cửa sổ 30 ngày; và chọn ngày cuối cùng mà bạn quan tâm. Điều này cũng có thể là bộ nhớ khá chuyên sâu.
Hiện tại 'end_date' trong bảng_b đều có cửa sổ chồng chéo; ví dụ: công ty 1 có thể có ngày của năm 2010-03-01 và 2010-03-15. –
Xin chào @KarlD có khả năng. – JAB