Tôi nghĩ rằng điều này cần điểm chuẩn. Sử dụng DataFrame gốc của OP,
df = pd.DataFrame({
'state': ['CA', 'WA', 'CO', 'AZ'] * 3,
'office_id': range(1, 7) * 2,
'sales': [np.random.randint(100000, 999999) for _ in range(12)]
})
Như đã nhận xét về câu trả lời của mình, Andy tận dụng tối đa việc vector hóa và lập chỉ mục gấu trúc.
c = df.groupby(['state', 'office_id'])['sales'].sum().rename("count")
c / c.groupby(level=0).sum()
3,42 ms ± 16,7 Nhận xét trên mỗi vòng lặp
(trung bình ± std. Dev của 7 lần chạy, mỗi vòng 100 lần)
state_office = df.groupby(['state', 'office_id']).agg({'sales': 'sum'})
state = df.groupby(['state']).agg({'sales': 'sum'})
state_office.div(state, level='state') * 100
4,66 ms ± 24,4 Nút trên mỗi vòng lặp
(trung bình ± std. Dev của 7 lần chạy, mỗi vòng 100 vòng)
Đây là câu trả lời chậm nhất vì nó tính toán x.sum()
cho từng x
cấp độ 0.
Đối với tôi, đây vẫn là một câu trả lời hữu ích, mặc dù không ở dạng hiện tại. Để nhanh chóng EDA trên các bộ dữ liệu nhỏ hơn, apply
cho phép bạn sử dụng phương thức xâu chuỗi để viết điều này trong một dòng duy nhất. Do đó, chúng tôi loại bỏ nhu cầu quyết định tên của một biến, thực sự rất tốn kém về mặt tính toán cho tài nguyên quý giá nhất của bạn (bộ não của bạn !!).
Đây là sửa đổi,
(
df.groupby(['state', 'office_id'])
.agg({'sales': 'sum'})
.groupby(level=0)
.apply(lambda x: 100 * x / float(x.sum()))
)
10,6 ms ± 81,5 Lời nói trên mỗi vòng lặp
(trung bình ± std. Dev của 7 lần chạy, mỗi vòng 100 vòng)
Vì vậy, không ai sẽ quan tâm đến 6ms trên một tập dữ liệu nhỏ. Tuy nhiên, đây là tốc độ tăng gấp 3 lần và, trên một tập dữ liệu lớn hơn với các nhóm có số lượng thẻ cao, điều này sẽ tạo ra sự khác biệt lớn.
Thêm vào mã trên, chúng tôi tạo một DataFrame có hình dạng (12.000.000, 3) với 14412 danh mục trạng thái và 600 office_ids,
import string
import numpy as np
import pandas as pd
np.random.seed(0)
groups = [
''.join(i) for i in zip(
np.random.choice(np.array([i for i in string.ascii_lowercase]), 30000),
np.random.choice(np.array([i for i in string.ascii_lowercase]), 30000),
np.random.choice(np.array([i for i in string.ascii_lowercase]), 30000),
)
]
df = pd.DataFrame({'state': groups * 400,
'office_id': list(range(1, 601)) * 20000,
'sales': [np.random.randint(100000, 999999)
for _ in range(12)] * 1000000
})
Sử dụng Andy,
2 s ± 10,4 ms mỗi vòng lặp
(trung bình ± std. Dev của 7 lần chạy, mỗi vòng 1 vòng)
và exp1orer
19 s ± 77,1 ms mỗi vòng lặp
(trung bình ± std. Dev của 7 lần chạy, mỗi vòng 1 vòng)
Vì vậy, bây giờ chúng ta thấy x10 tăng tốc trên các bộ dữ liệu cardinality lớn, cao.
Hãy chắc chắn để UV ba câu trả lời nếu bạn UV câu này !!
df['sales'] / df.groupby('state')['sales'].transform('sum')
dường như là câu trả lời rõ ràng nhất