मुझे लगता है कि इसके लिए बेंचमार्किंग की जरूरत है। ओपी के मूल डेटाफ़्रेम का उपयोग करते हुए,
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)]
})
जैसा कि उनके जवाब पर टिप्पणी की गई थी, एंडी वैक्टराइजेशन और पांडा इंडेक्सिंग का पूरा फायदा उठाते हैं।
c = df.groupby(['state', 'office_id'])['sales'].sum().rename("count")
c / c.groupby(level=0).sum()
3.42 एमएस 42 16.7 ms प्रति लूप
(मतलब। एसटीडी। 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 एमएस 66 24.4 ms प्रति लूप
(मतलब। एसटीडी। 7 रन का देव, प्रत्येक 100 लूप)
यह सबसे धीमा उत्तर है क्योंकि यह स्तर 0 में x.sum()प्रत्येक के लिए गणना करता है x।
मेरे लिए, यह अभी भी एक उपयोगी उत्तर है, हालांकि इसके वर्तमान स्वरूप में नहीं है। छोटे डेटासेट पर त्वरित EDA के लिए, applyआप इसे एक ही पंक्ति में लिखने के लिए विधि का उपयोग कर सकते हैं । इसलिए हम एक चर के नाम पर निर्णय की आवश्यकता को हटाते हैं, जो वास्तव में बहुत कम्प्यूटेशनल रूप से महंगा है आपके सबसे मूल्यवान संसाधन (आपका मस्तिष्क !!) के लिए ।
यहाँ संशोधन है,
(
df.groupby(['state', 'office_id'])
.agg({'sales': 'sum'})
.groupby(level=0)
.apply(lambda x: 100 * x / float(x.sum()))
)
10.6 एमएस 6 81.5 ms प्रति लूप
(मतलब। एसटीडी। 7 रन का देव, प्रत्येक 100 लूप)
तो कोई भी छोटे डेटासेट पर 6ms के बारे में परवाह नहीं कर रहा है। हालाँकि, यह 3x गति है और उच्च कार्डिनैलिटी ग्रुपबीज के साथ एक बड़े डेटासेट पर यह एक बड़ा अंतर बनाने जा रहा है।
उपरोक्त कोड को जोड़ते हुए, हम 14412 राज्य श्रेणियों और 600 %__ के साथ आकृति (12,000,000, 3) के साथ एक 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
})
एंडी का उपयोग करना,
2 एस ± 10.4 एमएस प्रति लूप
(माध्य। Std। 7 रन का देवता, 1 लूप प्रत्येक)
और exp1orer
19 s ± 77.1 एमएस प्रति लूप
(मतलब dev एसटीडी। 7 रन का। 1 लूप प्रत्येक)
तो अब हम बड़े, उच्च कार्डिनैलिटी डेटासेट पर x10 की गति देखते हैं।
अगर आप यह एक यूवी है तो इन तीन उत्तरों के लिए यूवी सुनिश्चित करें !!
df['sales'] / df.groupby('state')['sales'].transform('sum')सबसे साफ जवाब लगता है।