Bunun kıyaslamaya ihtiyacı olduğunu düşünüyorum. OP'nin orijinal DataFrame'ini kullanarak,
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)]
})
Cevabına yorum yaptığı gibi, Andy vektörleşme ve panda indekslemesinden tam olarak yararlanıyor.
c = df.groupby(['state', 'office_id'])['sales'].sum().rename("count")
c / c.groupby(level=0).sum()
Çevrim başına 3,42 ms ± 16,7 µs
(ortalama 7 çalışma, ortalama 100 döngü, ortalama 100 döngü)
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 döngü başına ± 24.4 µs
(ortalama 7 adım, ortalama 100 döngü, her biri 100 döngü)
Bu seviye 0'daki x.sum()
her biri için hesapladığı için en yavaş cevaptır x
.
Benim için bu, mevcut haliyle olmasa da, hala yararlı bir cevaptır. Daha küçük veri kümelerinde hızlı EDA için, apply
bunu tek bir satıra yazmak için yöntem zinciri kullanmanıza izin verir . Bu nedenle , en değerli kaynağınız (beyniniz !!) için aslında çok hesaplamalı olarak pahalı olan bir değişkenin adına karar verme ihtiyacını ortadan kaldırıyoruz .
İşte değişiklik,
(
df.groupby(['state', 'office_id'])
.agg({'sales': 'sum'})
.groupby(level=0)
.apply(lambda x: 100 * x / float(x.sum()))
)
Loop başına 10.6 ms ± 81.5 µs
(ortalama 7 std. Ortalama, her biri 100 ilmek)
Yani hiç kimse küçük bir veri kümesinde 6 ms umurumda değil. Bununla birlikte, bu 3 kat hızlanır ve yüksek kardinalite gruplarına sahip daha büyük bir veri kümesinde bu büyük bir fark yaratacaktır.
Yukarıdaki koda ek olarak, 14412 devlet kategorisi ve 600 office_id ile şekilli (12.000.000, 3) bir DataFrame,
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 kullanarak,
Devre başına 2 s ± 10,4 ms
(7 çalışmanın ortalama ± standart sapması, her biri 1 döngü)
ve exp1orer
Çevrim başına 19 s ± 77,1 ms
(7 çalışmanın ortalama ± standart sapması, her biri 1 döngü)
Şimdi büyük, yüksek kardinalite veri kümelerinde x10'un hızlandığını görüyoruz.
Eğer bu UV cevap bu üç cevap UV emin olun !!
df['sales'] / df.groupby('state')['sales'].transform('sum')
en açık cevap gibi görünüyor.