ฉันคิดว่าสิ่งนี้ต้องการการเปรียบเทียบ ใช้ DataFrame ดั้งเดิมของ 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)]
})
ตามที่แสดงความคิดเห็นในคำตอบของเขา Andy ใช้ประโยชน์อย่างเต็มที่จากการทำดัชนีเวกเตอร์และแพนด้า
c = df.groupby(['state', 'office_id'])['sales'].sum().rename("count")
c / c.groupby(level=0).sum()
3.42 ms ± 16.7 µs ต่อลูป
(ค่าเฉลี่ย± std. dev ของ 7 รัน, 100 ลูปแต่ละครั้ง)
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 µs ต่อลูป
(ค่าเฉลี่ย± std. dev ของ 7 รัน, 100 ลูปแต่ละครั้ง)
นี่เป็นคำตอบที่ช้าที่สุดเนื่องจากคำนวณx.sum()
สำหรับแต่ละx
ระดับในระดับ 0
สำหรับฉันนี่ยังคงเป็นคำตอบที่มีประโยชน์แม้ว่าจะไม่ใช่ในรูปแบบปัจจุบันก็ตาม สำหรับ EDA อย่างรวดเร็วบนชุดข้อมูลขนาดเล็กapply
ให้คุณใช้วิธีการผูกมัดเพื่อเขียนสิ่งนี้ในบรรทัดเดียว ดังนั้นเราจึงลบความต้องการในการตัดสินใจเกี่ยวกับชื่อของตัวแปรซึ่งมีราคาแพงมากในการคำนวณสำหรับทรัพยากรที่มีค่าที่สุดของคุณ (สมองของคุณ !!)
นี่คือการปรับเปลี่ยน
(
df.groupby(['state', 'office_id'])
.agg({'sales': 'sum'})
.groupby(level=0)
.apply(lambda x: 100 * x / float(x.sum()))
)
10.6 ms ± 81.5 µs ต่อลูป
(ค่าเฉลี่ย± std. dev ของ 7 รัน, 100 ลูปแต่ละครั้ง)
ดังนั้นจึงไม่มีใครสนใจเกี่ยวกับ 6ms ในชุดข้อมูลขนาดเล็ก อย่างไรก็ตามนี่คือความเร็ว 3 เท่าและในชุดข้อมูลขนาดใหญ่ที่มีกลุ่มคาร์ดิเนลลิตี้สูงสิ่งนี้จะสร้างความแตกต่างอย่างมาก
เมื่อเพิ่มโค้ดด้านบนเราสร้าง DataFrame ที่มีรูปร่าง (12,000,000, 3) พร้อม 14412 หมวดหมู่รัฐและ 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
})
ใช้ Andy's
2 วินาที ± 10.4 ms ต่อลูป
(ค่าเฉลี่ย± std. dev ของ 7 รัน, 1 ลูปแต่ละครั้ง)
และ exp1orer
19 วินาที ± 77.1 ms ต่อลูป
(ค่าเฉลี่ย± std. dev. ของการรัน 7 ครั้ง, การวนซ้ำ 1 ครั้ง)
ตอนนี้เราเห็น x10 เร่งความเร็วบนชุดข้อมูลขนาดใหญ่ที่มีคาร์ดินาลิตี้สูง
อย่าลืม UV คำตอบทั้งสามข้อนี้ถ้าคุณ UV อันนี้ !!
df['sales'] / df.groupby('state')['sales'].transform('sum')
ดูเหมือนจะเป็นคำตอบที่ชัดเจนที่สุด