मैं ग्रुपबी () के साथ एक नया कॉलम कैसे बनाऊँ?
इसके दो तरीके हैं - एक सीधा और दूसरा थोड़ा और दिलचस्प।
सबका पसंदीदा: GroupBy.transform()
साथ'sum'
@ ईडी चुम का जवाब थोड़ा सरल किया जा सकता है। के DataFrame.groupby
बजाय बुलाओ Series.groupby
। यह सरल वाक्य रचना में परिणाम करता है।
df[['Date', 'Data3']]
Date Data3
0 2015-05-08 5
1 2015-05-07 8
2 2015-05-06 6
3 2015-05-05 1
4 2015-05-08 50
5 2015-05-07 100
6 2015-05-06 60
7 2015-05-05 120
df.groupby('Date')['Data3'].transform('sum')
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Data3, dtype: int64
यह तेज है,
df2 = pd.concat([df] * 12345)
%timeit df2['Data3'].groupby(df['Date']).transform('sum')
%timeit df2.groupby('Date')['Data3'].transform('sum')
10.4 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
8.58 ms ± 559 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
अपरंपरागत, लेकिन अपने विचार पर ध्यान दें: GroupBy.sum()
+Series.map()
मैं एपीआई में एक दिलचस्प idiosyncrasy पर ठोकर खाई। जो मैं बताता हूं, आप इसे 0.20 से अधिक किसी भी बड़े संस्करण पर पुन: पेश कर सकते हैं (मैंने इसे 0.23 और 0.24 पर परीक्षण किया है)। ऐसा लगता है जैसे आप लगातार समय के कुछ मिलीसेकेंड को दाढ़ी बना सकते हैं transform
यदि आप इसके बजाय एक सीधा फ़ंक्शन का GroupBy
उपयोग करते हैं और इसे प्रसारित करते हैं map
:
df.Date.map(df.groupby('Date')['Data3'].sum())
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Date, dtype: int64
तुलना करना
df.groupby('Date')['Data3'].transform('sum')
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Data3, dtype: int64
मेरे परीक्षणों से पता चलता है कि map
एक सा तेजी से होता है यदि आप सीधे उपयोग करने के लिए खर्च कर सकते हैं, तो GroupBy
समारोह (जैसे mean
, min
, max
, first
, आदि)। यह लगभग ~ 200 हजार रिकॉर्ड तक की अधिकांश सामान्य स्थितियों के लिए कम या ज्यादा तेज है। उसके बाद, प्रदर्शन वास्तव में डेटा पर निर्भर करता है।
(बाएं: v0.23, दाएं: v0.24)
पता करने के लिए अच्छा विकल्प है, और बेहतर है अगर आपके पास छोटी संख्या में समूह हैं। । । लेकिन मैं transform
पहली पसंद के रूप में सलाह दूंगा। सोचा कि यह वैसे भी साझा करने लायक था।
संदर्भ के लिए बेंचमार्किंग कोड:
import perfplot
perfplot.show(
setup=lambda n: pd.DataFrame({'A': np.random.choice(n//10, n), 'B': np.ones(n)}),
kernels=[
lambda df: df.groupby('A')['B'].transform('sum'),
lambda df: df.A.map(df.groupby('A')['B'].sum()),
],
labels=['GroupBy.transform', 'GroupBy.sum + map'],
n_range=[2**k for k in range(5, 20)],
xlabel='N',
logy=True,
logx=True
)