2025, Oct 15 21:34
दो 2D हिस्टोग्राम को साझा colorbar के साथ प्लॉट करने का सही तरीका (Matplotlib)
Matplotlib में दो 2D हिस्टोग्राम को साथ-साथ प्लॉट करें और साझा colorbar जोड़ें। Axes बनाम pyplot की उलझन दूर करें, shared normalization लगाएँ, तुलना पाएं.
जब आप दो 2D हिस्टोग्राम को साथ-साथ रखते हैं और एक साझा कलरबार चाहते हैं, तो यदि आप matplotlib के स्पष्ट Axes इंटरफ़ेस को pyplot की अप्रत्यक्ष स्टेट मशीन के साथ मिला देते हैं, तो उलझन भरा व्यवहार आसानी से सामने आता है। इसका सबसे सामान्य लक्षण यह होता है कि एक उप-आकृति खाली रह जाती है, जबकि दूसरी में प्लॉट दिखता है, और कलरबार से जुड़ी कोई भी लॉजिक साथ नहीं देती।
समस्या की रूपरेखा
कार्य यह है कि एक CSV पढ़ी जाए, सप्ताह का दिन और वर्ष का सप्ताह निकाला जाए, और फिर एक ही पंक्ति में दो वेटेड 2D हिस्टोग्राम दिखाए जाएँ, ताकि एक साझा कलरबार के साथ यह तुलना हो सके कि साल भर में दो मान कैसे बदलते हैं।
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from datetime import datetime
weekday_names = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
month_names = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
dataset = pd.read_csv("Mod4Data.csv", nrows=366)
# तारीख से हिस्से निकालें
dataset["Date"] = dataset["Day"].apply(pd.to_datetime)
dataset["Day of Week"] = dataset["Date"].dt.dayofweek
dataset['week_of_year'] = dataset['Date'].dt.strftime('%W')
dataset['Month'] = dataset['Date'].dt.month
# संख्यात्मक प्रकार सुनिश्चित करें
dataset['Value1'] = dataset['Value1'].astype(float)
dataset['Value2'] = dataset['Value2'].astype(float)
dataset['week_of_year'] = dataset['week_of_year'].astype(float)
canvas, axes_grid = plt.subplots(1, 2, figsize=(18, 10))
# बाएँ प्लॉट का प्रयास
axes_grid[0] = plt.hist2d(
    dataset["Day of Week"],
    dataset["week_of_year"],
    bins=[7, 52],
    weights=dataset["Value1"],
    vmin=1000,
    vmax=20000,
)
plt.title("Value 1 Amounts")
plt.yticks([2, 6.3348, 10.66, 14.99, 19.32, 23.65, 27.98, 32.31, 36.64, 40.97, 45.3, 49.63], month_names)
plt.xticks([0, 1, 2, 3, 4, 5, 6], weekday_names, rotation=45)
# दाएँ प्लॉट का प्रयास
second_hist = plt.hist2d(
    dataset["Day of Week"],
    dataset["week_of_year"],
    bins=[7, 52],
    weights=dataset["Value2"],
    vmin=1000,
    vmax=20000,
)
plt.title("Value 2 Amounts")
plt.yticks([2, 6.3348, 10.66, 14.99, 19.32, 23.65, 27.98, 32.31, 36.64, 40.97, 45.3, 49.63], month_names)
plt.xticks([0, 1, 2, 3, 4, 5, 6], weekday_names, rotation=45)
क्या गड़बड़ होती है और क्यों
यहाँ दो अलग-अलग समस्याएँ हैं। पहली, कोड plt.subplots से मिले स्पष्ट Axes वर्कफ़्लो और वर्तमान axes पर ड्रॉ करने वाली pyplot की अप्रत्यक्ष API के बीच आगे-पीछे होता है। plt.hist2d का परिणाम axes_grid[0] में असाइन करने से Axes ऑब्जेक्ट उस ट्यूपल से ओवरराइट हो जाता है जो hist2d लौटाता है, इसलिए मूल बाएँ subplot खो जाता है। बाद की pyplot कॉल्स, जैसे plt.title और दूसरी plt.hist2d, इच्छित उप-आकृतियों पर नहीं बल्कि उस समय जो भी current axes है, उसी पर रेंडर हो जाती हैं।
दूसरी बात, एक साझा कलरबार के लिए किसी एक हिस्टोग्राम से सही mappable चाहिए। hist2d के मामले में mappable चौथा रिटर्न मान होता है। साझा कलरबार यह भी मान कर चलता है कि दोनों प्लॉट संख्या को रंगों में एक जैसी तरह से बदलते हैं; इसे समान normalization इस्तेमाल करके सुनिश्चित किया जाता है।
लेआउट और कलरबार कैसे सुधारें
बेहतर तरीका है कि पूरे समय explicit Axes इंटरफ़ेस ही इस्तेमाल करें, hist2d से mappable को सँभाल लें, और दोनों प्लॉट्स में साझा normalization लगाएँ ताकि एक ही कलरबार सार्थक रहे।
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.colors import Normalize
weekday_names = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
month_names = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
# इनपुट और फीचर इंजीनियरिंग
frame = pd.read_csv("Mod4Data.csv", nrows=366)
frame["Date"] = frame["Day"].apply(pd.to_datetime)
frame["Day of Week"] = frame["Date"].dt.dayofweek
frame['week_of_year'] = frame['Date'].dt.strftime('%W')
frame['Month'] = frame['Date'].dt.month
frame['Value1'] = frame['Value1'].astype(float)
frame['Value2'] = frame['Value2'].astype(float)
frame['week_of_year'] = frame['week_of_year'].astype(float)
# साझा normalization उप-आकृतियों में एकसमान रंग मैपिंग सुनिश्चित करता है
shared_norm = Normalize(vmin=1000, vmax=20000)
fig, ax_array = plt.subplots(nrows=1, ncols=2, figsize=(18, 10), layout="constrained")
# बायाँ हीटमैप
_, _, _, img_left = ax_array[0].hist2d(
    frame["Day of Week"],
    frame["week_of_year"],
    bins=[7, 52],
    weights=frame["Value1"],
    norm=shared_norm,
)
ax_array[0].set_title("Value 1 Amounts")
ax_array[0].set_yticks([2, 6.3348, 10.66, 14.99, 19.32, 23.65, 27.98, 32.31, 36.64, 40.97, 45.3, 49.63])
ax_array[0].set_yticklabels(month_names)
ax_array[0].set_xticks([0, 1, 2, 3, 4, 5, 6])
ax_array[0].set_xticklabels(weekday_names, rotation=45)
# दायाँ हीटमैप
_, _, _, img_right = ax_array[1].hist2d(
    frame["Day of Week"],
    frame["week_of_year"],
    bins=[7, 52],
    weights=frame["Value2"],
    norm=shared_norm,
)
ax_array[1].set_title("Value 2 Amounts")
ax_array[1].set_yticks([2, 6.3348, 10.66, 14.99, 19.32, 23.65, 27.98, 32.31, 36.64, 40.97, 45.3, 49.63])
ax_array[1].set_yticklabels(month_names)
ax_array[1].set_xticks([0, 1, 2, 3, 4, 5, 6])
ax_array[1].set_xticklabels(weekday_names, rotation=45)
# एक साझा कलरबार: एक mappable से लिया गया और दोनों अक्षों पर लागू
plt.colorbar(img_right, ax=ax_array, location="top")
plt.show()
यह क्यों मायने रखता है
संगत API शैली बनाए रखने से ऐसे छुपे हुए स्टेट बग्स से बचा जा सकता है जिन्हें पहचानना और दोहराना दोनों मुश्किल होते हैं। जब आप कई हिस्टोग्राम के लिए एक ही कलरबार चाहते हैं, तो रंग मैपिंग एक जैसी होना जरूरी है, वरना वही रंग हर subplot पर अलग मान दर्शाएगा। एक ही normalization इस समानता की गारंटी देता है, और कलरबार को एक mappable देना उसके उद्देश्य को स्पष्ट करता है।
मुख्य बातें
plt.subplots से मिले Axes ऑब्जेक्ट्स का ही उपयोग करें और उन्हीं पर plotting मेथड्स कॉल करें; अप्रत्यक्ष pyplot इंटरफ़ेस पर वापस न जाएँ। plotting कॉल्स से लौटे ट्यूपल से Axes संदर्भों को ओवरराइट न करें। साझा कलरबार के लिए, hist2d द्वारा लौटाया गया mappable दें और साझा normalization लगाएँ, ताकि दोनों पैनल एक ही तरह से डेटा को रंगों में मैप करें। मदद मांगते समय, चित्र को स्पष्ट रूप से दिखाने वाला छोटा और पुनरुत्पाद्य उदाहरण समस्या और उसके समाधान को सीधा बनाता है।