2025, Nov 01 08:01

Polars में coalesce के साथ नाम कॉलम को सुसंगत बनाना

Polars में name_full व name_first/name_last को normalize करें: coalesce, split, list.get और null_on_oob से कम branching, साफ़ व स्केलेबल ट्रांसफॉर्मेशन.

Polars स्ट्रिंग फ़ील्ड्स को सामान्यीकृत करना सरल बनाता है, लेकिन परस्पर-विरोधी इनपुट मिलाने पर अक्सर लंबा-चौड़ा ब्रांचिंग हो जाती है। एक आम स्थिति नामों की है: कुछ पंक्तियाँ एक ही कॉमा-सेपरेटेड स्ट्रिंग देती हैं, जबकि अन्य में पहला और अंतिम नाम पहले से अलग-अलग कॉलम में होते हैं। लक्ष्य है बिना बार-बार की शर्तों के जाल में उलझे, सुसंगत कॉलम्स पर पहुँचना।

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

हमारे पास ऐसा डेटासेट है जहाँ कुछ पंक्तियाँ पूरा नाम “Last, First” प्रारूप में एक स्ट्रिंग के रूप में देती हैं, जबकि अन्य में अंतिम और पहला नाम अलग-अलग हैं। हमें अंत में दो साफ-सुथरे कॉलम चाहिए—जहाँ विभाजित कॉलम मौजूद हों, वहीं का मान लें; अन्यथा पूर्ण नाम को पार्स करके मान प्राप्त करें।

import polars as pl
rows = [
    {"name_full": "McCartney, Paul"},
    {"name_last": "Lennon", "name_first": "John"},
    {"name_full": "Starr, Ringo"},
    {"name_last": "Harrison", "name_first": "George"}
]
people_df = pl.DataFrame(rows)

साधारण तरीका क्यों दिक्कत देता है

एक तरीका है कि पूर्ण नाम को बाँट लें, अतिरिक्त स्पेस हटा दें, और फिर हर लक्षित कॉलम के लिए अलग शाखा बनाएँ। यह काम करता है, पर हर गंतव्य कॉलम के लिए अपनी शर्त लगानी पड़ती है, जो स्कीमा बढ़ने के साथ बोझिल हो जाती है।

(
    people_df.with_columns(
        pl.col("name_full")
          .str.split(",")
          .list.eval(pl.element().str.strip_chars())
          .alias("pieces")
    ).with_columns(
        pl.when(pl.col("name_last").is_null())
          .then(pl.col("pieces").list.get(0, null_on_oob=True))
          .otherwise(pl.col("name_last")).alias("name_last"),
        pl.when(pl.col("name_first").is_null())
          .then(pl.col("pieces").list.get(1, null_on_oob=True))
          .otherwise(pl.col("name_first")).alias("name_first")
    ).select(pl.all().exclude("name_full", "pieces"))
)

कार्यात्मक रूप से यह ठीक है, लेकिन हर अतिरिक्त फ़ील्ड के साथ एक और ब्रांच जुड़ती है—बॉयलरप्लेट और दृश्य शोर बढ़ता है।

coalesce के साथ संक्षिप्त पैटर्न

जब पूर्ण नाम कॉमा-पैटर्न का अनुसरण करता है, तो टोकन्स की पार्स की गई सूची रखना पर्याप्त है और जहाँ विभाजित कॉलम पहले से भरे हों, उन्हें प्राथमिकता दें। कुंजी है coalesce पर भरोसा करना, जो पहला non-null मान लौटाता है। इससे दोहराए जाने वाले कंडीशंस गायब हो जाते हैं और उद्देश्य साफ़ बना रहता है।

people_df.with_columns(
    pl.col("name_full")
      .str.split(",")
      .list.eval(pl.element().str.strip_chars())
      .alias("pieces")
).select(
    pl.coalesce(
        pl.col("name_last"),
        pl.col("pieces").list.get(0, null_on_oob=True)
    ).alias("name_last"),
    pl.coalesce(
        pl.col("name_first"),
        pl.col("pieces").list.get(1, null_on_oob=True)
    ).alias("name_first")
)

इस तरह पार्सिंग चरण स्पष्ट और छोटा रहता है, और मर्ज की तर्क-प्रक्रिया दो पढ़ने योग्य अभिव्यक्तियों में समा जाती है। list.get कॉल्स null_on_oob=True का उपयोग करती हैं ताकि जिस पंक्ति में पूर्ण नाम न हो, वहाँ त्रुटियाँ न आएँ।

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

डेटा इंजीनियरिंग पाइपलाइनों में अक्सर विषम इनपुट्स को एक मानकीकृत स्कीमा में समेटना पड़ता है। संक्षिप्त अभिव्यक्तियाँ रखरखाव का बोझ घटाती हैं, गलतियों की आशंका कम करती हैं और उद्देश्य स्पष्ट रखती हैं। Polars में coalesce पर भरोसा करना आपको यह व्यक्त करने देता है—“पहले इस कॉलम को चुनें, वरना पार्स किया हुआ विकल्प लें”—और हर लक्षित फ़ील्ड के लिए ब्रांचिंग लॉजिक दोहराने से बचाता है।

मुख्य बातें

जब name_full जैसे कॉलम में एक समान delimiter हो, तो उसे एक बार पार्स करें, बीच की बनी हुई array रखें, और फिर coalesce की मदद से मूल विभाजित कॉलम्स और पार्स किए गए टोकन्स के बीच पहला उपलब्ध मान चुनें। जैसे-जैसे आप फ़ील्ड्स जोड़ते हैं, यह तरीका साफ़-सुथरे ढंग से स्केल करता है और आपके ट्रांसफॉर्मेशन चरण सीधे और ऑडिट के अनुकूल रहते हैं।