जुड़वाँ के साथ माध्यमिक अक्ष (): किंवदंती में कैसे जोड़ें?


288

मेरे पास दो y- कुल्हाड़ियों के साथ एक भूखंड है, का उपयोग कर twinx()। मैं भी लाइनों को लेबल देता हूं, और उन्हें दिखाना चाहता हूंlegend() हूं, लेकिन मैं केवल एक धुरी के लेबल प्राप्त करने में सफल रहा हूं:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(time, Swdown, '-', label = 'Swdown')
ax.plot(time, Rn, '-', label = 'Rn')
ax2 = ax.twinx()
ax2.plot(time, temp, '-r', label = 'temp')
ax.legend(loc=0)
ax.grid()
ax.set_xlabel("Time (h)")
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")
ax2.set_ylabel(r"Temperature ($^\circ$C)")
ax2.set_ylim(0, 35)
ax.set_ylim(-20,100)
plt.show()

इसलिए मुझे केवल किंवदंती में पहली धुरी के लेबल मिलते हैं, न कि दूसरे अक्ष के 'अस्थायी' लेबल। मैं इस तीसरे लेबल को किंवदंती में कैसे जोड़ सकता हूं?

यहां छवि विवरण दर्ज करें


4
[ इसे दूर से किसी भी उत्पादन कोड के करीब न करें ] जब मेरा एकमात्र उद्देश्य एपप्रॉप्ट किंवदंती ASAP के साथ एक सुंदर भूखंड उत्पन्न करना है, तो मैं axउस शैली के साथ एक खाली सरणी की साजिश रचने का एक बदसूरत हैक का उपयोग करता हूं जिस पर मैं उपयोग करता हूं ax2: अपने मामले, ax.plot([], [], '-r', label = 'temp')। यह ठीक से करने की तुलना में बहुत तेज और सरल है ...
नेस्टेनिन

जवाबों:


370

आप आसानी से लाइन जोड़कर एक दूसरी किंवदंती जोड़ सकते हैं:

ax2.legend(loc=0)

आप इसे प्राप्त करेंगे:

यहां छवि विवरण दर्ज करें

लेकिन अगर आप एक किंवदंती पर सभी लेबल चाहते हैं तो आपको कुछ इस तरह करना चाहिए:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')

time = np.arange(10)
temp = np.random.random(10)*30
Swdown = np.random.random(10)*100-10
Rn = np.random.random(10)*100-10

fig = plt.figure()
ax = fig.add_subplot(111)

lns1 = ax.plot(time, Swdown, '-', label = 'Swdown')
lns2 = ax.plot(time, Rn, '-', label = 'Rn')
ax2 = ax.twinx()
lns3 = ax2.plot(time, temp, '-r', label = 'temp')

# added these three lines
lns = lns1+lns2+lns3
labs = [l.get_label() for l in lns]
ax.legend(lns, labs, loc=0)

ax.grid()
ax.set_xlabel("Time (h)")
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")
ax2.set_ylabel(r"Temperature ($^\circ$C)")
ax2.set_ylim(0, 35)
ax.set_ylim(-20,100)
plt.show()

जो आपको यह देगा:

यहां छवि विवरण दर्ज करें


2
यह errorbarभूखंडों के साथ विफल रहता है । एक समाधान के लिए जो उन्हें सही ढंग से संभालता है, नीचे देखें: stackoverflow.com/a/10129461/1319447
Davide

1
मेरे मामले में दो अतिव्यापी किंवदंतियों को रोकने के लिए जहां मैंने दो .legend (लोक = 0) निर्दिष्ट किए हैं, आपको किंवदंती स्थान मान के लिए दो भिन्न मान निर्दिष्ट करना चाहिए (दोनों 0 के अलावा)। देखें: matplotlib.org/api/legend_api.html
Roalt

मुझे कई लाइनों के साथ कुछ सबप्लॉट में एक लाइन जोड़ने में कुछ परेशानी हुई ax1। इस स्थिति में उपयोग करें lns1=ax1.linesऔर फिर lns2इस सूची में जोड़ें ।
छोटे बॉबी टेबल्स

इसके द्वारा इस्तेमाल किए गए विभिन्न मूल्यों को यहाँloc समझाया गया है
Dror

1
अधिक स्वचालित तरीके के लिए नीचे का उत्तर देखें (matplotlib के साथ = = 2.1): stackoverflow.com/a/47370214/653364
joris

183

मुझे यकीन नहीं है कि यह कार्यक्षमता नई है, लेकिन आप लाइनों और स्वयं को ट्रैक करने के बजाय get_legend_handles_labels () विधि का उपयोग कर सकते हैं:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')

pi = np.pi

# fake data
time = np.linspace (0, 25, 50)
temp = 50 / np.sqrt (2 * pi * 3**2) \
        * np.exp (-((time - 13)**2 / (3**2))**2) + 15
Swdown = 400 / np.sqrt (2 * pi * 3**2) * np.exp (-((time - 13)**2 / (3**2))**2)
Rn = Swdown - 10

fig = plt.figure()
ax = fig.add_subplot(111)

ax.plot(time, Swdown, '-', label = 'Swdown')
ax.plot(time, Rn, '-', label = 'Rn')
ax2 = ax.twinx()
ax2.plot(time, temp, '-r', label = 'temp')

# ask matplotlib for the plotted objects and their labels
lines, labels = ax.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, loc=0)

ax.grid()
ax.set_xlabel("Time (h)")
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")
ax2.set_ylabel(r"Temperature ($^\circ$C)")
ax2.set_ylim(0, 35)
ax.set_ylim(-20,100)
plt.show()

1
यह एकमात्र उपाय है जो कुल्हाड़ियों को संभाल सकता है जहां भूखंड किंवदंतियों के साथ ओवरलैप होता है (अंतिम कुल्हाड़ी वह है जो किंवदंतियों की साजिश करना चाहिए)
एमिलियो वाज़केज़-रीना

5
यह समाधान errorbarभूखंडों के साथ भी काम करता है , जबकि स्वीकृत एक विफल रहता है (एक पंक्ति और इसके त्रुटिबारों को अलग-अलग दिखा रहा है, और उनमें से कोई भी सही लेबल नहीं है)। साथ ही, यह सरल है।
डेविड

मामूली पकड़: यह काम नहीं करता है अगर आप के लिए लेबल को अधिलेखित करना चाहते हैं ax2और यह शुरू से एक सेट नहीं है
सिप्रियन टोमायागो

टिप्पणी: क्लासिक प्लॉट के लिए, आपको लेबल तर्क को निर्दिष्ट करने की आवश्यकता नहीं है। लेकिन दूसरों के लिए, उदाहरण के लिए। आपको बार चाहिए
बेला

यह भी सब कुछ बहुत आसान बना देता है यदि आप पहले से नहीं जानते हैं कि कितनी लाइनें प्लॉट की जाने वाली हैं।
वेगार्ड जेरवेल

77

Matplotlib संस्करण 2.1 के बाद से, आप एक आंकड़ा किंवदंती का उपयोग कर सकते हैं । इसके बजाय ax.legend(), जो कुल्हाड़ियों से हैंडल के साथ एक किंवदंती पैदा करता हैax , कोई एक आंकड़ा किंवदंती बना सकता है

fig.legend (loc = "ऊपरी दाहिना")

जो आंकड़े में सभी सबप्लॉट से सभी हैंडल को इकट्ठा करेगा। चूंकि यह एक आंकड़ा किंवदंती है, इसलिए इसे आंकड़े के कोने पर रखा जाएगा, और locतर्क आंकड़ा के सापेक्ष है।

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,10)
y = np.linspace(0,10)
z = np.sin(x/3)**2*98

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x,y, '-', label = 'Quantity 1')

ax2 = ax.twinx()
ax2.plot(x,z, '-r', label = 'Quantity 2')
fig.legend(loc="upper right")

ax.set_xlabel("x [units]")
ax.set_ylabel(r"Quantity 1")
ax2.set_ylabel(r"Quantity 2")

plt.show()

यहां छवि विवरण दर्ज करें

किंवदंती को कुल्हाड़ियों में वापस रखने के लिए, एक bbox_to_anchorऔर एक की आपूर्ति करेगा bbox_transform। बाद वाला कुल्हाड़ियों का कुल्हाड़ी का रूपांतर होगा जिसमें किंवदंती को निवास करना चाहिए। पूर्व locमें कुल्हाड़ियों के निर्देशांक में दिए गए किनारे के निर्देशांक हो सकते हैं ।

fig.legend(loc="upper right", bbox_to_anchor=(1,1), bbox_transform=ax.transAxes)

यहां छवि विवरण दर्ज करें


तो, संस्करण 2.1 पहले से ही जारी है? लेकिन एनाकोंडा 3 में, मैंने conda upgrade matplotlibपाया कोई नया संस्करण नहीं मिला है, मैं अभी भी v.2.0.2 का उपयोग कर रहा हूं
स्टेफिशिश

1
यह अंतिम परिणाम प्राप्त करने का एक क्लीनर तरीका है।
गौतम

1
सुंदर और आकर्षक
DanGoodrick

1
जब आप कई सबप्लॉट होते हैं तो यह काम नहीं करता है। यह सभी सबप्लॉट्स के लिए एक एकल किंवदंती जोड़ता है। आम तौर पर प्रत्येक उपप्लॉट के लिए एक किंवदंती की आवश्यकता होती है, जिसमें प्रत्येक किंवदंती में प्राथमिक और द्वितीयक अक्ष दोनों में श्रृंखला होती है।
sancho.s ReinstateMonicaCellio

@sancho Correct, यही इस उत्तर के तीसरे वाक्य में लिखा गया है, "... जो आंकड़े में सभी सबप्लॉट से सभी हैंडल को इकट्ठा करेगा।"
ImportanceOfBeingErnest

38

आप आसानी से कुल्हाड़ी में लाइन जोड़कर जो चाहें प्राप्त कर सकते हैं:

ax.plot([], [], '-r', label = 'temp')

या

ax.plot(np.nan, '-r', label = 'temp')

यह कुल्हाड़ी की पौराणिक कथा के लिए एक लेबल जोड़ने के अलावा कुछ भी साजिश नहीं करेगा।

मुझे लगता है कि यह बहुत आसान तरीका है। जब आपके पास दूसरी कुल्हाड़ियों में कुछ ही लाइनें हों, तो स्वचालित रूप से ट्रैक करना आवश्यक नहीं है, क्योंकि ऊपर की तरह हाथ से फिक्स करना काफी आसान होगा। वैसे भी, यह इस बात पर निर्भर करता है कि आपको क्या चाहिए।

पूरा कोड नीचे दिया गया है:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')

time = np.arange(22.)
temp = 20*np.random.rand(22)
Swdown = 10*np.random.randn(22)+40
Rn = 40*np.random.rand(22)

fig = plt.figure()
ax = fig.add_subplot(111)
ax2 = ax.twinx()

#---------- look at below -----------

ax.plot(time, Swdown, '-', label = 'Swdown')
ax.plot(time, Rn, '-', label = 'Rn')

ax2.plot(time, temp, '-r')  # The true line in ax2
ax.plot(np.nan, '-r', label = 'temp')  # Make an agent in ax

ax.legend(loc=0)

#---------------done-----------------

ax.grid()
ax.set_xlabel("Time (h)")
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")
ax2.set_ylabel(r"Temperature ($^\circ$C)")
ax2.set_ylim(0, 35)
ax.set_ylim(-20,100)
plt.show()

कथानक नीचे है:

यहां छवि विवरण दर्ज करें


अद्यतन: एक बेहतर संस्करण जोड़ें:

ax.plot(np.nan, '-r', label = 'temp')

यह plot(0, 0)धुरी रेंज को बदलने के दौरान कुछ नहीं करेगा ।


बिखराव के लिए एक अतिरिक्त उदाहरण

ax.scatter([], [], s=100, label = 'temp')  # Make an agent in ax
ax2.scatter(time, temp, s=10)  # The true scatter in ax2

ax.legend(loc=1, framealpha=1)

3
यह मुझे पंसद है। इस तरह के बदसूरत तरीके से यह प्रणाली को "चकमा" देता है, लेकिन लागू करने के लिए इतना सरल है।
डेनियल पावर

यह लागू करने के लिए वास्तव में सरल है। लेकिन जब इसे तितर बितर करने के लिए उपयोग किया जाता है, तो किंवदंती में परिणामी तितर बितर का आकार केवल एक छोटा बिंदु होता है।
geeeeeeen

@greeeeeeen तब आपको बस स्कैटर प्लॉट बनाते समय मार्कर साइज निर्दिष्ट करना चाहिए
Syrtis Major

@SyrtisMajor I, बेशक, यह कोशिश की। लेकिन इससे किंवदंती में मार्कर का आकार नहीं बदला।
15

@greeeeeeen क्या आपने एजेंट का मार्कर आकार बदल दिया है? मेरी पोस्ट देखें, मैंने उदाहरण कोड का एक स्निपेट जोड़ा।
सिरिटिस मेजर

7

एक त्वरित हैक जो आपकी आवश्यकताओं के अनुरूप हो सकता है ..

बॉक्स के फ्रेम को उतारें और मैन्युअल रूप से दो किंवदंतियों को एक दूसरे के बगल में रखें। कुछ इस तरह..

ax1.legend(loc = (.75,.1), frameon = False)
ax2.legend( loc = (.75, .05), frameon = False)

जहां चार्ट में स्थान का प्रतिनिधित्व करने के लिए लोक टुप बाएं से दाएं और नीचे-से-ऊपर प्रतिशत है।


5

मुझे निम्न आधिकारिक matplotlib उदाहरण मिला है जो एक लीजेंड में कई y-axes और सभी विभिन्न लेबलों को प्रदर्शित करने के लिए host_subplot का उपयोग करता है। कोई जरूरी हल नहीं। सबसे अच्छा समाधान मुझे अब तक मिला। http://matplotlib.org/examples/axes_grid/demo_parasite_axes2.html

from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
import matplotlib.pyplot as plt

host = host_subplot(111, axes_class=AA.Axes)
plt.subplots_adjust(right=0.75)

par1 = host.twinx()
par2 = host.twinx()

offset = 60
new_fixed_axis = par2.get_grid_helper().new_fixed_axis
par2.axis["right"] = new_fixed_axis(loc="right",
                                    axes=par2,
                                    offset=(offset, 0))

par2.axis["right"].toggle(all=True)

host.set_xlim(0, 2)
host.set_ylim(0, 2)

host.set_xlabel("Distance")
host.set_ylabel("Density")
par1.set_ylabel("Temperature")
par2.set_ylabel("Velocity")

p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density")
p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature")
p3, = par2.plot([0, 1, 2], [50, 30, 15], label="Velocity")

par1.set_ylim(0, 4)
par2.set_ylim(1, 65)

host.legend()

plt.draw()
plt.show()

ढेर अतिप्रवाह में आपका स्वागत है! यदि लिंक साइट उपलब्ध नहीं है या स्थायी रूप से ऑफ़लाइन हो जाती है, तो कृपया लिंक का सबसे प्रासंगिक हिस्सा उद्धृत करें। देखिए मैं कैसे एक अच्छा जवाब लिखता हूं । भविष्य में अधिक वर्तमान प्रश्नों पर ध्यान दें, यह लगभग 4 साल पुराना है।
बट्टूमी

वास्तव में एक अच्छी खोज लेकिन मेरी इच्छा है कि आपने उदाहरण से जो कुछ सीखा है, उसे ओपी के MWE में लागू किया और एक छवि शामिल की।
एयरोोटऑटो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.