2025, Oct 16 14:32

pandas pivot_table में MultiIndex उप-योग जोड़ें: आधुनिक, pd.append के बिना

इस गाइड में pandas pivot_table के MultiIndex पर groupby, लेबल रीशेप, concat और sort_index से उप-योग जोड़ने का आधुनिक तरीका जानें—pd.append के बिना, तेज़ व साफ।

pandas की pivot_table में उप-योग जोड़ना रिपोर्टिंग की सामान्य जरूरत है, लेकिन कई पुराने स्निपेट अब निरस्त किए जा चुके pd.append पर निर्भर करते हैं। नीचे दिया गया तरीका संक्षिप्त और आधुनिक है: जब आपकी पिवट की पंक्तियों पर MultiIndex हो, जैसे index=["A", "B"], और आप उसी तालिका में प्रत्येक समूह के उप-योग चाहते हों, तब यह बेहतरीन काम करता है।

समस्या की रूपरेखा

हम एक सरल डेटासेट से शुरू करते हैं और पदानुक्रमित पंक्तियों वाली पिवट बनाते हैं। उद्देश्य है—संरचना को बिगाड़े बिना, इंडेक्स के किसी एक स्तर के लिए उप-योग वाली पंक्तियाँ जोड़ना।

import pandas as pd

raw_df = pd.DataFrame({
    "A": ["A1", "A1", "A1", "A2", "A2", "A2", "A3", "A3", "A3"],
    "B": ["B1", "B1", "B1", "B2", "B2", "B2", "B3", "B3", "B3"],
    "C": ["C1", "C1", "C2", "C2", "C2", "C3", "C3", "C3", "C3"],
    "D": [1, 2, 3, 4, 5, 6, 7, 8, 9],
})

cube = raw_df.pivot_table(
    index=["A", "B"],
    columns="C",
    values="D",
    aggfunc="sum",
    fill_value=0,
)

print(cube)

पिवट कुछ इस तरह दिखता है:

C       C1  C2  C3
A  B              
A1 B1   3   3   0
A2 B2   0   9   6
A3 B3   0   0  24

असल चुनौती क्या है

एक-स्तरीय इंडेक्स में आप margins पर भरोसा कर सकते हैं, लेकिन जैसे ही पंक्तियाँ MultiIndex हो जाती हैं, आपको उप-योग इस तरह निकालने और रखने का तरीका चाहिए जो इंडेक्स की संरचना से मेल खाए। मकसद है—सब कुछ एक ही तालिका में रखना, प्रत्येक समूह के टोटल सही स्थान पर डालना, और निरस्त APIs से बचना।

समाधान: इंडेक्स स्तर पर groupby, लेबल रीशेप, concat, फिर sort

ढांचा सरल है। पहले, चुने हुए इंडेक्स स्तर पर एग्रीगेट करें। फिर, उस परिणाम को ऐसा पुनः-लेबल करें कि वह प्रत्येक समूह के नीचे “Total” पंक्ति बनकर MultiIndex में फिट हो जाए। अंत में, इसे मूल पिवट के साथ जोड़ें (concatenate) और इंडेक्स के आधार पर sort करें।

# पहले इंडेक्स स्तर ("A") के उप-योग
level_sums = cube.groupby(level=0).sum().rename(index=lambda k: (k, "Total"))
with_totals = pd.concat([cube, level_sums]).sort_index()

print(with_totals)

परिणाम में A के हर समूह के नीचे एक उप-योग पंक्ति जुड़ जाती है:

C         C1  C2  C3
A1 B1      3   3   0
   Total   3   3   0
A2 B2      0   9   6
   Total   0   9   6
A3 B3      0   0  24
   Total   0   0  24

यदि उप-योग दूसरे स्तर ("B") पर चाहिए, तो groupby में स्तर बदलें, नए इंडेक्स लेबल उसी के अनुसार सेट करें, और फिर उसी स्तर के आधार पर sort करें:

# दूसरे इंडेक्स स्तर ("B") के उप-योग
level_sums_b = cube.groupby(level=1).sum().rename(index=lambda v: ("Total", v))
with_totals_b = pd.concat([cube, level_sums_b]).sort_index(level=1)

print(with_totals_b)

ऐसा करने पर आउटपुट होगा:

C         C1  C2  C3
A1    B1   3   3   0
Total B1   3   3   0
A2    B2   0   9   6
Total B2   0   9   6
A3    B3   0   0  24
Total B3   0   0  24

यह क्यों उपयोगी है

रिपोर्टों में पढ़ने की सुविधा और त्वरित जाँच के लिए उप-योग अक्सर जरूरी होते हैं। सीधे पिवट पर यह करने से सब कुछ एक ही जगह रहता है, अलग-अलग तालिकाएँ जोड़ने की जरूरत नहीं पड़ती, और MultiIndex लेआउट के साथ भी सब कुछ सहज रहता है। concat का उपयोग निरस्त पैटर्न से बचाता है और मौजूदा pandas संस्करणों के साथ अनुकूल रहता है।

मुख्य बातें

जब pandas की pivot_table में कई इंडेक्स स्तर हों, तो जिस स्तर पर उप-योग चाहिए उस पर grouped sum निकालें, प्राप्त लेबलों को ऐसा ढालें कि वे मौजूदा MultiIndex में घुल-मिल जाएँ, फिर concatenate करके sort कर दें। एक-स्तरीय इंडेक्स के लिए margins पर्याप्त हो सकते हैं, पर बहु-स्तरीय स्थिति में यह तरीका आउटपुट को साफ-सुथरा और प्रस्तुत करने लायक बनाए रखता है।

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