2025, Oct 17 16:35
guides के साथ plotnine में दो लेजेंड का क्रम कैसे बदलें
इस ट्यूटोरियल में सीखें: plotnine में bars और lines के अलग‑अलग legends का order नियंत्रित करें. guides और guide_legend से बिना डेटा बदले क्रम बदलें.
plotnine में कई एस्थेटिक्स मिलाने पर अक्सर एक से अधिक लेजेंड बन जाते हैं। अगर वे गलत क्रम में दिखें, तो ग्राफ़ अटपटा लगता है। नीचे डेटा को रेशेप किए बिना या geoms बदले बिना उनके क्रम को नियंत्रित करने का छोटा, सीधा तरीका है।
Goal
एक बार‑और‑स्टेप चार्ट बनाना जिसमें दो अलग‑अलग लेजेंड हों—बार्स (2040) के लिए अलग, लाइनों (2015) के लिए अलग—और लेजेंड पैनल में उनका क्रम आपस में बदलना।
Reproducible example with the unwanted legend order
# आयात
import polars as po
import polars.selectors as sel
from plotnine import *
# डेटा
payload = {
    "Category": ['0-1', '1-5', '5-10', '10-15', '15-20', '20-25', '25-30', '30-35', '35-40', '40-45', '45-50', '50-55', '55-60', '60-65', '65-70', '70-75', '75-80', '80-85', '85-90', '90-95', '95 en ouder'],
    "Mannen 2040": [-540, -910, -1530, -1990, -2120, -2300, -2270, -2340, -2540, -2690, -3140, -3370, -3750, -4200, -5310, -7250, -8310, -8170, -6970, -4610, -1480],
    "Vrouwen 2040": [460, 670, 1050, 1740, 2030, 2450, 3040, 3280, 3370, 3420, 3990, 4390, 4510, 4880, 6170, 8050, 9530, 11080, 11470, 8900, 3350],
    "Mannen 2015": [-420, -660, -980, -1310, -1380, -1550, -1490, -1410, -1460, -1810, -2360, -2690, -2910, -3030, -3430, -3050, -2920, -2540, -1800, -840, -210],
    "Vrouwen 2015": [360, 500, 710, 1180, 1350, 1720, 2070, 2060, 1930, 2060, 2570, 2850, 2870, 2840, 3300, 3070, 3540, 4240, 4400, 2950, 1020]
}
wide_tbl = po.DataFrame(payload)
long_tbl = wide_tbl.unpivot(sel.numeric(), index="Category")
# प्लॉट
(
    ggplot() +
    geom_bar(
        data=long_tbl.filter(po.col('variable').is_in(['Mannen 2040', 'Vrouwen 2040'])),
        mapping=aes(x='Category', y='value', fill='variable'),
        stat='identity'
    ) +
    scale_fill_manual(values=['#007BC7', '#CA005D']) +
    geom_step(
        data=long_tbl.filter(po.col('variable').is_in(['Mannen 2015', 'Vrouwen 2015'])),
        mapping=aes(x='Category', y='value', color='variable', group='variable'),
        stat='identity',
        size=1.5,
        direction='mid'
    ) +
    scale_color_manual(values=['#0C163F', '#FFB612']) +
    scale_x_discrete(limits=payload['Category']) +
    scale_y_continuous(
        name="Euro's (x miljoen)",
        limits=[-10_000, 12_500],
        breaks=range(-10_000, 12_500, 2_000),
        labels=list(map(abs, range(-10_000, 12_500, 2_000)))
    ) +
    coord_flip() +
    theme(
        figure_size=(8, 6),
        plot_title=element_text(color="#01689B", size=16, hjust=0.5),
        legend_position="bottom",
        legend_title=element_blank(),
        legend_key=element_blank(),
        panel_background=element_rect(fill="white"),
        panel_grid_major_x=element_line(colour="black", size=0.25),
        axis_ticks_length=5,
        axis_ticks_y=element_line(color="black", size=1.5),
        axis_line_y=element_line(color="black", size=1.5, linetype="solid"),
        axis_title_y=element_blank(),
        axis_title_x=element_text(colour="#007BC7", size=10, hjust=1)
    ) +
    ggtitle("De uitgaven aan zorg voor vrouwen zijn hoger dan\nvoor mannen, en dit verschil neemt toe in de toekomst")
)
What’s happening
बार्स fill एस्थेटिक का और लाइनें color एस्थेटिक का उपयोग करती हैं, इसलिए plotnine दो लेजेंड बनाता है। डिफ़ॉल्ट रूप से उनका क्रम इस बात से तय होता है कि स्केल से गाइड्स कैसे बनते हैं। अगर वह क्रम आपकी मंशा के मुताबिक नहीं है, तो आपको उसे स्पष्ट रूप से बताना होगा।
Fix: swap legend order with guides
guides और guide_legend की मदद से हर लेजेंड का क्रम निर्धारित करें। नीचे दिया गया परिवर्तन मूल डेटा को छुए बिना उन्हें साफ़‑सुथरे तरीके से आपस में बदल देता है।
import polars as po
import polars.selectors as sel
from plotnine import *
# डेटा
payload = {
    "Category": ['0-1', '1-5', '5-10', '10-15', '15-20', '20-25', '25-30', '30-35', '35-40', '40-45', '45-50', '50-55', '55-60', '60-65', '65-70', '70-75', '75-80', '80-85', '85-90', '90-95', '95 en ouder'],
    "Mannen 2040": [-540, -910, -1530, -1990, -2120, -2300, -2270, -2340, -2540, -2690, -3140, -3370, -3750, -4200, -5310, -7250, -8310, -8170, -6970, -4610, -1480],
    "Vrouwen 2040": [460, 670, 1050, 1740, 2030, 2450, 3040, 3280, 3370, 3420, 3990, 4390, 4510, 4880, 6170, 8050, 9530, 11080, 11470, 8900, 3350],
    "Mannen 2015": [-420, -660, -980, -1310, -1380, -1550, -1490, -1410, -1460, -1810, -2360, -2690, -2910, -3030, -3430, -3050, -2920, -2540, -1800, -840, -210],
    "Vrouwen 2015": [360, 500, 710, 1180, 1350, 1720, 2070, 2060, 1930, 2060, 2570, 2850, 2870, 2840, 3300, 3070, 3540, 4240, 4400, 2950, 1020]
}
long_tbl = po.DataFrame(payload).unpivot(sel.numeric(), index="Category")
(
    ggplot() +
    geom_bar(
        data=long_tbl.filter(po.col('variable').is_in(['Mannen 2040', 'Vrouwen 2040'])),
        mapping=aes(x='Category', y='value', fill='variable'),
        stat='identity'
    ) +
    scale_fill_manual(values=['#007BC7', '#CA005D'], guide=guide_legend(order=1)) +
    geom_step(
        data=long_tbl.filter(po.col('variable').is_in(['Mannen 2015', 'Vrouwen 2015'])),
        mapping=aes(x='Category', y='value', color='variable', group='variable'),
        stat='identity',
        size=1.5,
        direction='mid'
    ) +
    scale_color_manual(values=['#0C163F', '#FFB612']) +
    scale_x_discrete(limits=payload['Category']) +
    scale_y_continuous(
        name="Euro's (x miljoen)",
        limits=[-10_000, 12_500],
        breaks=range(-10_000, 12_500, 2_000),
        labels=list(map(abs, range(-10_000, 12_500, 2_000)))
    ) +
    coord_flip() +
    theme(
        figure_size=(8, 6),
        plot_title=element_text(color="#01689B", size=16, hjust=0.5),
        legend_position="bottom",
        legend_title=element_blank(),
        legend_key=element_blank(),
        panel_background=element_rect(fill="white"),
        panel_grid_major_x=element_line(colour="black", size=0.25),
        axis_ticks_length=5,
        axis_ticks_y=element_line(color="black", size=1.5),
        axis_line_y=element_line(color="black", size=1.5, linetype="solid"),
        axis_title_y=element_blank(),
        axis_title_x=element_text(colour="#007BC7", size=10, hjust=1)
    ) +
    guides(
        color=guide_legend(order=1),  # 2015 की रेखाएँ
        fill=guide_legend(order=2)    # 2040 के बार्स
    ) +
    ggtitle("De uitgaven aan zorg voor vrouwen zijn hoger dan\nvoor mannen, en dit verschil neemt toe in de toekomst")
)
Why this matters
स्पष्ट लेजेंड समझ को तेज़ बनाते हैं। जब किसी प्लॉट में बार्स और लाइनें साथ हों, तो पाठक विज़ुअल चैनलों और लेजेंड ब्लॉकों के बीच स्थिर मैपिंग की उम्मीद करते हैं। लेजेंड का क्रम नियंत्रित करने से गलतफहमी से बचाव होता है और बहु‑स्तरीय विज़ुअलाइज़ेशन संभालना आसान रहता है।
Wrap‑up
यदि plotnine में अलग‑अलग एस्थेटिक्स अलग‑अलग लेजेंड बनाते हैं, तो उनके आपसी क्रम को स्पष्ट रूप से तय करें। न्यूनतम बदलाव यही है कि guide_legend(order=...) के साथ guides जोड़ दें। इससे डेटा जस‑का‑तस रहता है, geoms वैसे ही बने रहते हैं, और साफ़‑साफ़ बतता है कि पहले क्या दिखना चाहिए। छोटा सा बदलाव, पर पढ़ने‑समझने पर बड़ा असर।