2025, Oct 22 14:16

pandas DataFrame को कॉलम-संरेखण के साथ row-wise जोड़ें: pd.concat बनाम update

जानें क्यों DataFrame.update नई पंक्तियाँ नहीं जोड़ता, और pandas में pd.concat कॉलम नामों से संरेखित कर दो DataFrame को सुरक्षित रूप से row-wise जोड़ता है; sort=False व fillna टिप्स।

जब दो pandas DataFrame कुछ कॉलम साझा करते हैं लेकिन सभी नहीं, तो इन-प्लेस अपडेट का सहारा लेना सहज लगता है। लेकिन अगर लक्ष्य पहले DataFrame की सभी पंक्तियाँ बनाए रखना और फिर दूसरे से नई पंक्तियाँ जोड़ना है—कॉलम नामों के अनुसार संरेखित करके—तो अपडेट मददगार नहीं होगा। यहाँ सही उपाय है कॉलम-संरेखण के साथ पंक्ति-वार संयोजन।

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

एक तालिका चौड़ी है (अधिक कॉलम), दूसरी संकरी (उन्हीं कॉलम का उपसमुच्चय, संभव है अलग क्रम में)। मनचाहा परिणाम यह है कि मूल सभी पंक्तियाँ बनी रहें और संकरी तालिका की पंक्तियाँ अंत में जुड़ें—मिलते-जुलते कॉलम नामों के नीचे मान आएँ और बाकी जगहें खाली रहें।

भटकाने वाला तरीका

यह स्निपेट एक कुंजी के आधार पर एक फ़्रेम को दूसरे से “अपडेट” करने की कोशिश करता है। यह इंडेक्स सेट करता है और DataFrame.update का उपयोग करता है, जो केवल मौजूदा पंक्तियों के मानों को बदलता है। जब दूसरा DataFrame नई पंक्तियाँ जोड़ रहा हो, तब यह हमारे मकसद के अनुकूल नहीं है।

def sync_frames(big_tbl, small_tbl, id_col):
    """
    साझा कुंजी कॉलम के आधार पर small_tbl के मानों से big_tbl को अपडेट करता है।
    केवल वे कॉलम जो small_tbl में हैं, वही big_tbl में बदले जाएँगे।

    पैरामीटर्स:
    - big_tbl (pd.DataFrame): बड़ा DataFrame।
    - small_tbl (pd.DataFrame): छोटा DataFrame जिसमें अद्यतन मान हैं।
    - id_col (str): वह कॉलम नाम जिसे पंक्तियाँ मिलाने की कुंजी के रूप में उपयोग किया जाता है।

    रिटर्न्स:
    - pd.DataFrame: अद्यतन big_tbl।
    """

    slim = small_tbl.drop_duplicates(subset=id_col)

    big_tbl.set_index(id_col, inplace=True)
    slim.set_index(id_col, inplace=True)

    big_tbl.update(slim)

    big_tbl.reset_index(inplace=True)
    return big_tbl

यह आवश्यकता के लिए क्यों विफल होता है

अपेक्षित आउटपुट बताता है कि दूसरे DataFrame की पंक्तियाँ परिणाम में अतिरिक्त पंक्तियों के रूप में दिखनी चाहिए, समान कॉलम नामों के नीचे मान बैठें और बाकी खाली रहें। DataFrame.update पंक्तियाँ जोड़ता नहीं; यह केवल वहाँ के सेल्स को ओवरराइट करता है जहाँ इंडेक्स ओवरलैप हों। यानी, आप इन-प्लेस अपडेट नहीं कर रहे—आप पंक्तियों के द्वारा डेटासेट जोड़ रहे हैं।

सही तरीका: कॉलम-संरेखण के साथ पंक्ति-वार संयोजन

दूसरे DataFrame की पंक्तियाँ जोड़ते हुए कॉलम संरेखण बनाए रखने के लिए pd.concat का उपयोग करें। यह पंक्तियाँ स्टैक करता है और कॉलम नामों से संरेखित करता है। किसी इनपुट में जो कॉलम अनुपस्थित हों, उन्हें NaN मिलेगा (जिसे चाहें तो प्रदर्शन के लिए खाली स्ट्रिंग से बदल सकते हैं)।

import pandas as pd

# कॉलम संरेखण के साथ पंक्तियाँ संयोजित करें
blended = pd.concat([wide_df, narrow_df], ignore_index=True, sort=False)

# वैकल्पिक: रिक्त मानों को खाली स्ट्रिंग के रूप में दिखाएँ
blended = blended.fillna("")

# वैकल्पिक: मार्कडाउन तालिका के रूप में सुंदर प्रिंट
print(blended.to_markdown(tablefmt="grid"))

इससे ऐसा परिणाम मिलता है जिसमें पहले DataFrame की सभी पंक्तियाँ सुरक्षित रहती हैं, और दूसरे DataFrame की हर पंक्ति जोड़ दी जाती है। साझा कॉलम ठीक से लाइन अप होते हैं; जो कॉलम साझा नहीं हैं, वे जहाँ लागू हों खाली रहते हैं।

यह बारीकी क्यों मायने रखती है

update और concat के बीच चयन तय करता है कि आप मौजूदा पंक्तियों को बदल रहे हैं या डेटासेट बढ़ा रहे हैं। विषम स्रोतों या आंशिक एक्सट्रैक्ट्स को जोड़ने वाली पाइपलाइनों में, पंक्ति-वार संयोजन डेटा की अखंडता बनाए रखता है और अनचाही ओवरराइटिंग से बचाता है। साथ ही, जब कॉलम क्रम अलग हो, तब भी यह स्वाभाविक रूप से काम करता है—संरेखण स्थिति से नहीं, कॉलम लेबल से होता है।

मुख्य बातें

यदि आपको ऐसे DataFrame से नए रिकॉर्ड जोड़ने हैं जिसमें केवल कुछ कॉलम हों, तो pd.concat से संयोजन करें और sort=False देकर कॉलम संरेखण को बनाए रखें। DataFrame.update केवल तब उपयोग करें जब सचमुच मेल खाते इंडेक्स पर मौजूदा पंक्तियों के मानों को ओवरराइट करना हो। यदि परिणाम मानव-पठनीय होना है, तो रिक्त मानों को खाली स्ट्रिंग से भरें ताकि लेआउट स्पष्ट रहे।

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