source

matplotlib 범례를 축 밖으로 이동하면 그림 상자에 의해 범례가 잘립니다.

lovecheck 2022. 12. 28. 21:45
반응형

matplotlib 범례를 축 밖으로 이동하면 그림 상자에 의해 범례가 잘립니다.

저는 다음 질문에 익숙합니다.

그림 외부에 범례가 있는 Matplotlib savefig

범례를 플롯에서 제외하는 방법

이 질문들의 답변은 그 전설이 들어맞도록 축이 정확히 축소되는 것을 만지작거릴 수 있는 사치를 가지고 있는 것 같다.

그러나 축을 축소하는 것은 이상적인 해결책이 아닙니다. 왜냐하면 데이터가 더 작아지기 때문에 실제로 해석하기가 더 어렵기 때문입니다. 특히 복잡하고 많은 일들이 일어나고 있는 경우에는 더욱 그렇습니다.따라서 큰 전설이 필요하다

설명서의 복잡한 범례의 예는 그림의 범례가 실제로 여러 데이터 점을 완전히 가리기 때문에 이러한 범례의 필요성을 보여줍니다.

http://matplotlib.sourceforge.net/users/legend_guide.html#legend-of-complex-plots

확대되는 피규어 범례에 맞추어 피규어 박스의 크기를 동적으로 확장할 수 있으면 좋겠습니다.

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-2*np.pi, 2*np.pi, 0.1)
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(x, np.sin(x), label='Sine')
ax.plot(x, np.cos(x), label='Cosine')
ax.plot(x, np.arctan(x), label='Inverse tan')
lgd = ax.legend(loc=9, bbox_to_anchor=(0.5,0))
ax.grid('on')

최종 라벨 'Inverse tan'은 실제로 그림 상자 밖에 있습니다(게시판 품질이 아니라 컷오프 상태가 불량합니다). 여기에 이미지 설명 입력

마지막으로, R과 LaTeX에서는 이것이 정상적인 동작이라고 들었습니다만, Python에서는 이것이 왜 어려운지 조금 혼란스럽습니다.역사적인 이유가 있나요?Matlab도 이 문제에 대해 똑같이 서투른가요?

pastbin http://pastebin.com/grVjc007에 이 코드의 (약간만) 긴 버전이 있습니다.

EMS 죄송합니다. 사실 방금 matplotlib mailling list에서 다른 답변을 받았습니다(Benjamin Root에게 감사합니다).

찾고 있는 코드는 saveconfig 콜을 다음과 같이 조정하는 것입니다.

fig.savefig('samplefigure', bbox_extra_artists=(lgd,), bbox_inches='tight')
#Note that the bbox_extra_artists must be an iterable

이는 명백히 tight_layout을 호출하는 것과 비슷하지만 대신 saveconfig를 사용하여 계산에서 추가 아티스트를 고려할 수 있습니다.이것에 의해, 실제로, 피규어 박스의 사이즈가 조정되었습니다.

import matplotlib.pyplot as plt
import numpy as np

plt.gcf().clear()
x = np.arange(-2*np.pi, 2*np.pi, 0.1)
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(x, np.sin(x), label='Sine')
ax.plot(x, np.cos(x), label='Cosine')
ax.plot(x, np.arctan(x), label='Inverse tan')
handles, labels = ax.get_legend_handles_labels()
lgd = ax.legend(handles, labels, loc='upper center', bbox_to_anchor=(0.5,-0.1))
text = ax.text(-0.2,1.05, "Aribitrary text", transform=ax.transAxes)
ax.set_title("Trigonometry")
ax.grid('on')
fig.savefig('samplefigure', bbox_extra_artists=(lgd,text), bbox_inches='tight')

그 결과, 다음과 같이 됩니다.

[편집] 이 질문의 목적은 이러한 문제에 대한 전통적인 해결책과 마찬가지로 임의의 텍스트의 임의의 좌표 배치를 완전히 피하는 것이었다.그럼에도 불구하고, 최근 많은 편집자들이 이러한 내용을 넣기를 고집하고 있으며, 이는 종종 코드를 통해 오류가 발생하는 방식으로 이어지고 있습니다.문제를 수정하고 임의의 텍스트를 정리하여 bbox_extra_artists 알고리즘에서도 이러한 문제가 어떻게 고려되는지 보여 줍니다.

추가: 즉시 도움이 될 만한 것을 찾았지만, 아래의 나머지 코드도 다른 방법을 제공합니다.

하다를 사용하세요.subplots_adjust()"CHANGE: "CHANGE: "CHANGE: " 。

fig.subplots_adjust(bottom=0.2) # <-- Change the 0.02 to work for your plot.

요.bbox_to_anchor원하는 위치에 범례 상자를 가져오려면 범례 명령의 일부를 사용하십시오.「 」의의 몇개의 .figsize 을 합니다.subplots_adjust(bottom=...)품질도를 작성해야 합니다.

다른 방법:단순히 회선을 변경했을 뿐입니다.

fig = plt.figure(1)

대상:

fig = plt.figure(num=1, figsize=(13, 13), dpi=80, facecolor='w', edgecolor='k')

및 변경됨

lgd = ax.legend(loc=9, bbox_to_anchor=(0.5,0))

로.

lgd = ax.legend(loc=9, bbox_to_anchor=(0.5,-0.02))

화면에 잘 표시된다(24인치 CRT 모니터).

서 ★★★★figsize=(M,N)그림 창을 M인치 x N인치로 설정합니다.딱 맞을 때까지 이걸로 놀아요.으로 변환하여 에 따라 를 사용하여 하여 잘라냅니다viewport옵션을 선택합니다.

여기 또 다른 매우 수동적인 해결책이 있습니다.축의 크기를 정의할 수 있으며 그에 따라 패딩이 고려됩니다(범례 및 눈금 표시 포함).그것이 누군가에게 유용하기를 바란다.

예(축 크기는 동일!):

여기에 이미지 설명 입력

코드:

#==================================================
# Plot table

colmap = [(0,0,1) #blue
         ,(1,0,0) #red
         ,(0,1,0) #green
         ,(1,1,0) #yellow
         ,(1,0,1) #magenta
         ,(1,0.5,0.5) #pink
         ,(0.5,0.5,0.5) #gray
         ,(0.5,0,0) #brown
         ,(1,0.5,0) #orange
         ]


import matplotlib.pyplot as plt
import numpy as np

import collections
df = collections.OrderedDict()
df['labels']        = ['GWP100a\n[kgCO2eq]\n\nasedf\nasdf\nadfs','human\n[pts]','ressource\n[pts]'] 
df['all-petroleum long name'] = [3,5,2]
df['all-electric']  = [5.5, 1, 3]
df['HEV']           = [3.5, 2, 1]
df['PHEV']          = [3.5, 2, 1]

numLabels = len(df.values()[0])
numItems = len(df)-1
posX = np.arange(numLabels)+1
width = 1.0/(numItems+1)

fig = plt.figure(figsize=(2,2))
ax = fig.add_subplot(111)
for iiItem in range(1,numItems+1):
  ax.bar(posX+(iiItem-1)*width, df.values()[iiItem], width, color=colmap[iiItem-1], label=df.keys()[iiItem])
ax.set(xticks=posX+width*(0.5*numItems), xticklabels=df['labels'])

#--------------------------------------------------
# Change padding and margins, insert legend

fig.tight_layout() #tight margins
leg = ax.legend(loc='upper left', bbox_to_anchor=(1.02, 1), borderaxespad=0)
plt.draw() #to know size of legend

padLeft   = ax.get_position().x0 * fig.get_size_inches()[0]
padBottom = ax.get_position().y0 * fig.get_size_inches()[1]
padTop    = ( 1 - ax.get_position().y0 - ax.get_position().height ) * fig.get_size_inches()[1]
padRight  = ( 1 - ax.get_position().x0 - ax.get_position().width ) * fig.get_size_inches()[0]
dpi       = fig.get_dpi()
padLegend = ax.get_legend().get_frame().get_width() / dpi 

widthAx = 3 #inches
heightAx = 3 #inches
widthTot = widthAx+padLeft+padRight+padLegend
heightTot = heightAx+padTop+padBottom

# resize ipython window (optional)
posScreenX = 1366/2-10 #pixel
posScreenY = 0 #pixel
canvasPadding = 6 #pixel
canvasBottom = 40 #pixel
ipythonWindowSize = '{0}x{1}+{2}+{3}'.format(int(round(widthTot*dpi))+2*canvasPadding
                                            ,int(round(heightTot*dpi))+2*canvasPadding+canvasBottom
                                            ,posScreenX,posScreenY)
fig.canvas._tkcanvas.master.geometry(ipythonWindowSize) 
plt.draw() #to resize ipython window. Has to be done BEFORE figure resizing!

# set figure size and ax position
fig.set_size_inches(widthTot,heightTot)
ax.set_position([padLeft/widthTot, padBottom/heightTot, widthAx/widthTot, heightAx/heightTot])
plt.draw()
plt.show()
#--------------------------------------------------
#==================================================

언급URL : https://stackoverflow.com/questions/10101700/moving-matplotlib-legend-outside-of-the-axis-makes-it-cutoff-by-the-figure-box

반응형