2025, Oct 02 11:32

pandas pivot_table में categorical फ़िल्टर के बाद अनचाहे कॉलम? observed=True से समाधान

pandas में categorical फ़िल्टर के बाद pivot_table में अतिरिक्त कॉलम क्यों दिखते हैं? observed=True से साफ़ परिणाम पाएं; व्यावहारिक उदाहरण व FutureWarning सहित.

जब आप pandas DataFrame को श्रेणीबद्ध मानों (categorical values) के किसी उपसमूह तक फ़िल्टर करते हैं और फिर पिवट टेबल बनाते हैं, तो अक्सर उन श्रेणियों के कॉलम देखकर हैरानी होती है जिन्हें आप समझते थे कि हट चुके हैं। यह बात गेम प्लेटफ़ॉर्म डेटा में खूब दिखती है: आप कुछ चुनिंदा प्लेटफ़ॉर्म ही रखते हैं, लेकिन pivot_table फिर भी मूल डेटा में कभी भी दिखे हर प्लेटफ़ॉर्म के लिए कॉलम बना देता है।

समस्या दोहराकर देखना

मान लीजिए, आप कई प्लेटफ़ॉर्म वाले गेम्स डेटासेट से शुरू करते हैं और उसे घटाकर केवल छह प्लेटफ़ॉर्म तक सीमित कर देते हैं। फ़िल्टर किए गए DataFrame में सब सही लगता है, फिर भी पिवट पूरी पुरानी श्रेणी-सूची वापस खींच लाता है।

# मूल डेटाफ़्रेम
df_games_src['platform'].unique()
# केवल छह लक्षित प्लेटफ़ॉर्म वाला नया डेटाफ़्रेम
df_games_filtered = df_games_src[df_games_src['platform'].isin(
    ['3DS', 'PSV', 'WiiU', 'PS4', 'XOne', 'PC'])].sort_values(by=['year', 'platform']).reset_index(drop=True)
df_games_filtered['platform'].unique()
# पिवट टेबल बनाना (अनपेक्षित अतिरिक्त कॉलम दिखाई देते हैं)
subset_sales = df_games_filtered[['name', 'platform', 'total_sales']]
sales_wide = subset_sales.pivot_table(
    values='total_sales', index='name', columns='platform', aggfunc='sum')
sales_wide

नतीजे में ऐसी तालिका दिखती है जिसमें चुनी हुई छह श्रेणियों से कहीं अधिक प्लेटफ़ॉर्म के कॉलम मौजूद हैं, जबकि फ़िल्टर किए गए DataFrame की unique सूची में सिर्फ वही छह हैं।

ऐसा क्यों होता है

यह व्यवहार pandas के categorical dtype से जुड़ा है। डिफ़ॉल्ट रूप से, pivot_table सहित कई विधियाँ आउटपुट में अप्रयुक्त श्रेणियों को भी शामिल कर लेती हैं। मतलब, dtype में जो श्रेणियाँ मौजूद हैं लेकिन आपके फ़िल्टर किए गए डेटा की वास्तविक पंक्तियों में नहीं दिखतीं, वे भी परिणाम में जगह बना लेती हैं। pandas यूज़र गाइड में यह विषय categorical operations अनुभाग में समझाया गया है: https://pandas.pydata.org/pandas-docs/stable/user_guide/categorical.html#operations.

समाधान

pivot_table को अप्रयुक्त श्रेणियों को नज़रअंदाज़ करने के लिए सबसे सीधा तरीका है observed=True सेट करना। इस फ्लैग के साथ, आउटपुट बनाते समय केवल वही श्रेणियाँ ली जाती हैं जो फ़िल्टर किए गए डेटा में वास्तव में मौजूद हैं।

subset_sales = df_games_filtered[['name', 'platform', 'total_sales']]
sales_wide = subset_sales.pivot_table(
    values='total_sales', index='name', columns='platform', aggfunc='sum', observed=True)
sales_wide

अब पिवट में केवल आपके फ़िल्टर की गई छह प्लेटफ़ॉर्म श्रेणियाँ ही आएंगी।

संक्षिप्त उदाहरण

यह छोटा उदाहरण डिफ़ॉल्ट व्यवहार और observed=True के बीच का अंतर दिखाता है।

import pandas as pd
# चार श्रेणियों वाली आधार तालिका
base_tbl = pd.DataFrame({
    'name': ['a', 'b', 'c', 'd'],
    'platform': ['w', 'x', 'y', 'z'],
    'total_sales': [1, 2, 3, 4]
})
# 'platform' को श्रेणीबद्ध (categorical) बनाएं
base_tbl = base_tbl.astype({'platform': 'category'})
# केवल वे पंक्तियाँ रखें जिनमें platform x या z है
narrow_tbl = base_tbl[base_tbl['platform'].isin(['x', 'z'])]
# डिफ़ॉल्ट: अप्रयुक्त श्रेणियाँ भी पिवट में आ जाती हैं
narrow_tbl.pivot_table(index='name', columns='platform', values='total_sales', aggfunc='sum')
# प्लेटफ़ॉर्म  w  x  y  z
# नाम
# b         0  2  0  0
# d         0  0  0  4
# observed=True के साथ: केवल इस्तेमाल हुई श्रेणियाँ शामिल होंगी
narrow_tbl.pivot_table(index='name', columns='platform', values='total_sales', aggfunc='sum', observed=True)
# प्लेटफ़ॉर्म    x    z
# नाम
# b         2.0  NaN
# d         NaN  4.0

यह क्यों अहम है

आउटपुट को साफ़-सुथरा और पढ़ने में आसान बनाने से आगे, एक व्यवहारगत बदलाव भी आने वाला है। कम से कम v2.3.2 पर आपका कोड सचेत करेगा, क्योंकि डिफ़ॉल्ट बदलने वाला है। चेतावनी संदेश स्पष्ट है:

FutureWarning: The default value of observed=False is deprecated and will change to observed=True in a future version of pandas. Specify observed=False to silence this warning and retain the current behavior

observed=True को स्पष्ट रूप से सेट करना आपके कोड को भविष्य के डिफ़ॉल्ट के अनुरूप रखता है और pandas के विकसित होने के साथ अप्रत्याशित सरप्राइज़ से बचाता है।

समापन

यदि आप किसी categorical कॉलम को फ़िल्टर करने के बाद भी पिवट आउटपुट में भूत-सी श्रेणियाँ देखते हैं, तो गलती फ़िल्टर की नहीं, डिफ़ॉल्ट categorical हैंडलिंग की है। pivot_table को केवल वास्तविक रूप से मौजूद श्रेणियाँ लेने के लिए observed=True पास करें। इससे आपकी तालिकाएँ उसी डेटा पर केंद्रित रहती हैं जिसे आपने जानबूझकर रखा है, और आपका कोड आने वाले डिफ़ॉल्ट परिवर्तन के लिए तैयार रहता है।

यह लेख StackOverflow पर एक प्रश्न (लेखक: RicardoDLM) और jqurious के उत्तर पर आधारित है।