Làm cách nào để tạo một cột mới với Groupby (). Sum ()?
Có hai cách - một cách đơn giản và một cách khác thú vị hơn một chút.
Mọi người yêu thích: GroupBy.transform()
với'sum'
Câu trả lời của @Ed Chum có thể được đơn giản hóa một chút. Gọi DataFrame.groupby
hơn là Series.groupby
. Điều này dẫn đến cú pháp đơn giản hơn.
df[['Date', 'Data3']]
Date Data3
0 2015-05-08 5
1 2015-05-07 8
2 2015-05-06 6
3 2015-05-05 1
4 2015-05-08 50
5 2015-05-07 100
6 2015-05-06 60
7 2015-05-05 120
df.groupby('Date')['Data3'].transform('sum')
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Data3, dtype: int64
Nó nhanh hơn một chút,
df2 = pd.concat([df] * 12345)
%timeit df2['Data3'].groupby(df['Date']).transform('sum')
%timeit df2.groupby('Date')['Data3'].transform('sum')
10.4 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
8.58 ms ± 559 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Không độc đáo, nhưng đáng để bạn cân nhắc: GroupBy.sum()
+Series.map()
Tôi tình cờ gặp một đặc điểm riêng thú vị trong API. Từ những gì tôi nói, bạn có thể tái tạo điều này trên bất kỳ phiên bản chính nào trên 0,20 (tôi đã thử nghiệm điều này trên 0,23 và 0,24). Có vẻ như bạn luôn có thể cắt bớt một vài mili giây thời gian transform
nếu thay vào đó bạn sử dụng một chức năng trực tiếp của GroupBy
và phát nó bằng cách sử dụng map
:
df.Date.map(df.groupby('Date')['Data3'].sum())
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Date, dtype: int64
So sánh với
df.groupby('Date')['Data3'].transform('sum')
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Data3, dtype: int64
Thử nghiệm của tôi cho thấy map
là một chút nhanh hơn nếu bạn có thể đủ khả năng để sử dụng trực tiếp GroupBy
chức năng (ví dụ như mean
, min
, max
, first
, vv). Nó nhanh hơn hoặc ít hơn đối với hầu hết các tình huống chung lên đến khoảng ~ 200 nghìn bản ghi. Sau đó, hiệu suất thực sự phụ thuộc vào dữ liệu.
(Trái: v0.23, Phải: v0.24)
Thay thế tuyệt vời để biết và tốt hơn nếu bạn có khung nhỏ hơn với số lượng nhóm nhỏ hơn. . . nhưng tôi muốn giới thiệu transform
như một sự lựa chọn đầu tiên. Nghĩ rằng điều này là giá trị chia sẻ dù sao.
Mã điểm chuẩn, để tham khảo:
import perfplot
perfplot.show(
setup=lambda n: pd.DataFrame({'A': np.random.choice(n//10, n), 'B': np.ones(n)}),
kernels=[
lambda df: df.groupby('A')['B'].transform('sum'),
lambda df: df.A.map(df.groupby('A')['B'].sum()),
],
labels=['GroupBy.transform', 'GroupBy.sum + map'],
n_range=[2**k for k in range(5, 20)],
xlabel='N',
logy=True,
logx=True
)