2025, Oct 31 04:31
साझा x-अक्ष वाले ऊर्ध्वाधर सबप्लॉट्स में y टिक-लेबल ओवरलैप को बिना hspace बदले कैसे ठीक करें
Matplotlib में साझा x-अक्ष वाले ऊर्ध्वाधर सबप्लॉट्स में y टिक-लेबल ओवरलैप का साफ समाधान: ScaledTranslation से केवल दो लेबल्स को हल्का शिफ्ट करें—लेआउट बदले बिना.
जब Matplotlib में एक ही x-अक्ष साझा करने वाले सबप्लॉट्स को ऊर्ध्वाधर रूप से रखा जाता है, तो ऊपर वाले अक्ष का सबसे निचला y टिक-लेबल और नीचे वाले अक्ष का सबसे ऊपरी y टिक-लेबल एक-दूसरे पर चढ़ सकते हैं। यह ओवरलैप पठनीयता बिगाड़ देता है, और अतिरिक्त hspace से पैडिंग करना या डेटा सीमाएँ बदलना हर बार उचित नहीं होता। उद्देश्य है कि दोनों टिक-लेबल बने रहें और बस हल्का-सा अंतर डाल दिया जाए।
ओवरलैप को पुनः बनाना
नीचे दिया गया न्यूनतम उदाहरण साझा x-अक्ष और शून्य ऊर्ध्वाधर अंतर के साथ दो सबप्लॉट बनाता है। ऊपर वाला अक्ष −1 से 1 तक फैला है, जबकि नीचे वाला −0.01 से 0.01 तक। सीमा जहाँ दोनों छूते हैं, वहाँ y टिक-लेबल टकरा जाते हैं।
import numpy as np
import matplotlib.pyplot as plt
fig_box, ax_grid = plt.subplots(nrows=2, sharex='col', gridspec_kw={'hspace': 0, 'wspace': 0})
ax_grid[1].set_xlim([0, 10])
ax_grid[0].set_ylim(-1.0, 1.0)
ax_grid[1].set_ylim(-0.01, 0.01)
x_vals = np.linspace(0, 10, 100)
ax_grid[0].plot(x_vals, np.sin(x_vals), color="red")
ax_grid[1].plot(x_vals, 0.01 * np.sin(x_vals), color="blue")
plt.show()
असल में क्या ओवरलैप होता है और क्यों
मुद्दा टिक की स्थिति का नहीं, बल्कि टिक-लेबल्स का है—यानी दोनों अक्षों की सीमा पर रेंडर हुआ पाठ। चूँकि सबप्लॉट्स x को साझा करते हैं और उनके बीच कोई ऊर्ध्वाधर पैडिंग नहीं है, ऊपर वाले अक्ष का सबसे निचला लेबल और नीचे वाले अक्ष का सबसे ऊपरी लेबल एक ही जगह घेर लेते हैं। hspace बदलने या y-सीमाएँ बढ़ाने से टकराव तो टल जाएगा, पर लेआउट या दृश्य रेंज भी बदल जाएगी, जो हर स्थिति में वांछनीय नहीं।
टिक नहीं, टिक-लेबल्स खिसकाएँ
सटीक समाधान यह है कि केवल वही दो समस्याग्रस्त लेबल्स को डिस्प्ले यूनिट्स में एक छोटे ऑफ़सेट से खिसका दिया जाए। ScaledTranslation पॉइंट्स में नापे गए ऊर्ध्वाधर शिफ्ट को लागू करने का साफ़-सुथरा तरीका देता है, जबकि डेटा और लेआउट जस के तस रहते हैं।
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.transforms import ScaledTranslation
fig_win, ax_set = plt.subplots(nrows=2, sharex='col', gridspec_kw={'hspace': 0, 'wspace': 0})
ax_set[1].set_xlim([0, 10])
ax_set[0].set_ylim(-1.0, 1.0)
ax_set[1].set_ylim(-0.01, 0.01)
x_seq = np.linspace(0, 10, 100)
ax_set[0].plot(x_seq, np.sin(x_seq), color="red")
ax_set[1].plot(x_seq, 0.01 * np.sin(x_seq), color="blue")
# 5 pt का ऊर्ध्वाधर ऑफ़सेट; 5 pt = 5/72 इंच
shift = ScaledTranslation(0, 5/72, fig_win.dpi_scale_trans)
# ऊपर वाले अक्ष के सबसे निचले लेबल को थोड़ा ऊपर खिसकाएँ
lbl = ax_set[0].yaxis.get_majorticklabels()[0]
lbl.set_transform(lbl.get_transform() + shift)
# नीचे वाले अक्ष के सबसे ऊपरी लेबल को थोड़ा नीचे खिसकाएँ
lbl = ax_set[1].yaxis.get_majorticklabels()[-1]
lbl.set_transform(lbl.get_transform() - shift)
plt.show()
यह तरीका उपयोगी क्यों है
यह तकनीक पठनीयता लौटाते हुए डेटा-सीमाएँ और कसा हुआ लेआउट सुरक्षित रखती है। आपको किसी टिक-सेट को दाहिने सरकाए बिना या subplot के अंतर को बढ़ाए बिना दोनों टिक-लेबल्स बनाए रखने देती है। यह तब खास मायने रखता है जब फ़िगर कॉम्पैक्ट रहना चाहिए, या किसी पैनल में दूसरी y-अक्ष जोड़नी हो—जहाँ टिक-लेबल्स के कॉलम को स्थानांतरित करना अड़चन बन सकता है।
मुख्य बातें
यदि x-अक्ष साझा करने वाले ऊर्ध्वाधर सबप्लॉट्स के बीच दो y टिक-लेबल्स आपस में टकराएँ, तो सिर्फ़ उन्हीं लेबल्स को हल्का-सा धक्का दें। ScaledTranslation के जरिए छोटा-सा पॉइंट-आधारित ऑफ़सेट उन्हें अलग करने के लिए काफ़ी है—अक्ष सीमाएँ या hspace बदले बिना—और दोनों लेबल दिखाई देते रहते हैं। ऊपर वाले अक्ष के सबसे निचले लेबल को थोड़ा ऊपर और नीचे वाले अक्ष के सबसे ऊपरी लेबल को थोड़ा नीचे खिसकाएँ—प्लॉट साफ़ और पढ़ने योग्य रहेगा।