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, applybunu 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.