2025, Nov 01 10:01
pandas में groupby, assign और mask से 'Other' समूह बनाकर पाई चार्ट
pandas में लूप-आधारित कोड को वेक्टराइज़्ड चेन से बदलें: groupby, assign, mask से बिक्री प्रतिशत निकालें, 'Other' समूह बनाएं और पाई चार्ट तैयार करें.
अन्वेषणात्मक डेटा-कार्य को स्पष्ट, पुनरुत्पादन योग्य कोड में बदलना अक्सर अनावश्यक मध्यवर्ती चरणों और लूप्स को हटाने से शुरू होता है। pandas में एक आम स्थिति है: मैट्रिक्स को समेकित करना, प्रतिशत निकालना, छोटे योगदानकर्ताओं को “Other” के तहत समेटना, और एक चार्ट बनाना। नीचे एक संक्षिप्त मार्गदर्शिका है जो दिखाती है कि लूप-आधारित तरीके को उसी व्यवहार को बनाए रखते हुए चेन की गई, वेक्टराइज़्ड पाइपलाइन से कैसे बदला जा सकता है।
समस्या का अवलोकन
कार्य यह है कि Kaggle के videogamesales डेटासेट से प्रत्येक प्रकाशक के वैश्विक वीडियो गेम बिक्री में हिस्से की गणना की जाए, 2% से कम योगदान देने वाले प्रकाशकों को एकल “Other” समूह में समेट दिया जाए, और परिणाम का पाई चार्ट तैयार किया जाए। शुरुआती इम्प्लीमेंटेशन काम करता है, लेकिन वह कई मध्यवर्ती ऑब्जेक्ट बनाता है, चरणों के बीच स्टेट बदलता है, और थ्रेशहोल्ड से नीचे वालों को फिर से लेबल करने के लिए मैनुअल लूप का उपयोग करता है।
जिस मूल कोड को सरल बनाना है
नीचे दिया गया स्निपेट स्पष्ट मध्यवर्तियों और for लूप के साथ मूल तरीका दिखाता है। लॉजिक जस का तस है, लेकिन स्पष्टता के लिए नाम थोड़े बदले गए हैं।
pub_sales_tbl = games_df.groupby('Publisher')[['Global_Sales']].sum().sort_values('Global_Sales', ascending=False)
all_sales = pub_sales_tbl['Global_Sales'].sum()
pub_sales_tbl['Share'] = pub_sales_tbl['Global_Sales'] / all_sales
pos = 0
cutoff = 0.02
publisher_labels = list(pub_sales_tbl.index)
for ratio in pub_sales_tbl['Share']:
if ratio < cutoff:
publisher_labels[pos] = 'Other'
pos = pos + 1
pub_sales_tbl.index = publisher_labels
pub_sales_tbl = pub_sales_tbl.groupby(pub_sales_tbl.index).sum().sort_values('Global_Sales', ascending=False)
plt.title("most profitable publisehr")
plt.ylabel("")
pie_ax = pub_sales_tbl['Global_Sales'].plot(kind='pie', figsize=(10, 5), legend=False)
pie_ax.set_ylabel("")
plt.show()
क्या हो रहा है और यह कमतर क्यों है
यह वर्कफ़्लो कुल, अनुपात और एक boolean शर्त सही तरह से निकालता है, लेकिन फिर इंडेक्स पोज़िशनों पर काउंटर के साथ चलता है ताकि थ्रेशहोल्ड से नीचे वाली प्रविष्टियों को नया लेबल दे सके। यह पैटर्न त्रुटि-प्रवण भी है और pandas में अनावश्यक भी, क्योंकि pandas पहले से ही वेक्टराइज़्ड ऑपरेशंस देता है जिनसे कॉलम बदले और लेबल एक ही पास में रीअसाइन किए जा सकते हैं। enumerate जैसी छोटी सुधार भी इंडेक्स के लिए, मुख्य समस्या नहीं हटाती: यहां पंक्ति-दर-पंक्ति लूप की ज़रूरत ही नहीं है। अंतिम नतीजा समान होना चाहिए, लेकिन उसे घोषणात्मक ढंग से, चरण-दर-चरण, ग्लोबल नेमस्पेस में मध्यवर्ती वैरिएबल बनाए और बदलाए बिना व्यक्त किया जा सकता है।
एक चेन की गई, वेक्टराइज़्ड समाधान
नीचे की पाइपलाइन मेथड चेनिंग का उपयोग करके उसी डेटासेट से वही परिणाम निकालती है। यह पाई चार्ट बनाती है और स्पष्ट लूप्स तथा अतिरिक्त वैरिएबल्स से बचती है। लौटाया गया ऑब्जेक्ट एक matplotlib figure होता है; चाहें तो आप इसे प्लॉटिंग में उपयोग हुए एग्रीगेटेड डेटा को लौटाने के लिए भी अनुकूलित कर सकते हैं। डेटासेट अपेक्षाकृत छोटा है, इसलिए पाइपलाइन सूक्ष्म अनुकूलनों की तुलना में पठनीयता को प्राथमिकता देती है।
import pandas as pd
records = pd.read_csv('vgsales.csv')
(
records
.groupby('Publisher', as_index=False)['Global_Sales'].sum()
.rename(columns={'Global_Sales': 'alltime_sales'})
.assign(
alltime_sales_percent=lambda frame: frame['alltime_sales'].div(frame['alltime_sales'].sum()).mul(100)
)
.assign(
major_publisher_name=lambda frame: frame['Publisher'].mask(frame['alltime_sales_percent'] < 2, 'Other')
)
.pipe(lambda frame: display(frame) or frame)
.groupby('major_publisher_name')['alltime_sales_percent'].sum()
.sort_values(ascending=False)
.plot.pie(
title='All-time sales share of major publishers',
ylabel='', figsize=(5, 5), cmap='tab20b'
)
);
यह क्यों मायने रखता है
चेनिंग पूरी डेटा-कहानी को एक पढ़ने योग्य पाइपलाइन में रखती है: एग्रीगेट करें, प्रतिशत में व्यक्त करें, शर्त के आधार पर रिलेबल करें, रोल-अप करें, सॉर्ट करें, और प्लॉट करें। यह मानसिक बोझ घटाती है, नेमस्पेस को साफ रखती है, और हर कदम को ऑडिट करना आसान बनाती है। जब आपको थ्रेशहोल्ड बदलना हो या किसी मध्यवर्ती रूपांतरण को देखना हो, तो यह एक पंक्ति का परिवर्तन होता है, न कि कई वैरिएबल्स की रिफैक्टरिंग। यह तरीका idiomatic pandas पैटर्न के अनुकूल है और पंक्ति-स्तरीय मैनुअल लूप्स की तुलना में वैचारिक रूप से बेहतर स्केल करता है।
व्यावहारिक निष्कर्ष
जब आपको छोटी श्रेणियों को “Other” स्लाइस में समेटकर उनका हिस्सा दिखाना हो, तो assign और mask जैसे वेक्टराइज़्ड रूपांतरणों को groupby के साथ प्राथमिकता दें। अगर कभी आप लूप पर टिके रहें, तो मैनुअल इंडेक्स काउंटर की जगह enumerate का इस्तेमाल भी थोड़ा सुविधा देता है, लेकिन इस मामले में लूप को पूरी तरह हटाना ही सरल और अधिक भरोसेमंद है। चेन की गई कॉल से लौटे figure को वैसे ही उपयोग किया जा सकता है, या आप अंतिम चरण को बदलकर आगे दोबारा उपयोग के लिए एग्रीगेटेड सीरीज़ लौटवा सकते हैं।
संक्षिप्त पाइपलाइन बग्स के लिए सतह क्षेत्र घटाती है और मंशा साफ करती है: एक बार शेयर निकालें, थ्रेशहोल्ड के आधार पर लेबल करें, एग्रीगेट करें, और प्लॉट करें। अक्सर यही फर्क होता है ऐसे प्रोसेसिंग कोड में जो केवल चलता है बनाम उस कोड में जिसे बनाए रखना और फिर से देखना आसान हो।
यह लेख StackOverflow पर प्रश्न by just a tw highschooler और MuhammedYunus SaveGaza के उत्तर पर आधारित है।