Làm thế nào để đưa huyền thoại ra khỏi cốt truyện


988

Tôi có một loạt 20 ô (không phải là ô phụ) được tạo thành một hình duy nhất. Tôi muốn huyền thoại ở bên ngoài chiếc hộp. Đồng thời, tôi không muốn thay đổi trục, vì kích thước của hình được giảm xuống. Xin vui lòng giúp tôi cho các truy vấn sau đây:

  1. Tôi muốn giữ hộp huyền thoại bên ngoài khu vực cốt truyện. (Tôi muốn huyền thoại ở bên ngoài khu vực cốt truyện).
  2. Có phải dù sao tôi cũng giảm kích thước phông chữ của văn bản bên trong hộp chú giải, để kích thước của hộp chú giải sẽ nhỏ.

14
Đối với các phiên bản matplotlib mới hơn, câu trả lời này cho thấy cách đặt matplotlib để tự động xác định vị trí đặt chú giải mà không can thiệp vào các ô .
dotancohen

2
Có cùng một câu hỏi và tìm thấy ví dụ tuyệt vời này có tác dụng với tôi "ngoài
luồng

1
Câu trả lời này có chiều sâu hơn https://stackoverflow.com/a/43439132/52074. và làm như vậy với hai dòng mã! câu trả lời nâng cao +1200 cũng tốt nhưng tôi thấy nó ít chung chung hơn.
Trevor Boyd Smith

2
@dotancohen "tự động xác định nơi đặt huyền thoại mà không can thiệp vào cốt truyện" Trong một số trường hợp nhất định, khi cốt truyện có nhiều đường cong, thật không may là không thể. Trong những trường hợp đó, người dùng có thể muốn đặt chú thích theo cách thủ công và thực sự đặt nó bên ngoài khu vực cốt truyện. Tôi đang gặp khó khăn với một âm mưu như vậy ngay bây giờ.
Ali

btw, danh sách các lựa chọn của loc: tốt nhất; phía trên bên phải; phía trên bên trái; phía dưới bên trái; phía dưới bên phải; đúng; trung tâm bên trái; trung tâm phải; trung tâm thấp hơn; trung tâm phía trên; trung tâm;
Z-Y00

Câu trả lời:


57

Bạn có thể làm cho văn bản chú giải nhỏ hơn bằng cách tạo các thuộc tính phông chữ:

from matplotlib.font_manager import FontProperties

fontP = FontProperties()
fontP.set_size('small')
legend([plot1], "title", prop=fontP) 
# or add prop=fontP to whatever legend() call you already have

50
những gì là plot1trong câu trả lời này?
Paul H

41
những gì là legendtrong câu trả lời này?
Richard

28
Điều này trả lời phần thứ hai của câu hỏi, nhưng không phải là phần chính (phần có tiêu đề).
Mateen Ulhaq

8
Ngoài ra, cách thích hợp để làm điều này làplt.legend(fontsize='small')
Mateen Ulhaq

41
Câu trả lời này là khủng khiếp và cung cấp rất ít bối cảnh!
Tekill

1797

Có một số cách để làm những gì bạn muốn. Để thêm vào những gì @inalis và @Navi đã nói, bạn có thể sử dụng bbox_to_anchorđối số từ khóa để đặt chú thích một phần bên ngoài các trục và / hoặc giảm kích thước phông chữ.

Trước khi bạn xem xét giảm kích thước phông chữ (có thể khiến mọi thứ cực kỳ khó đọc), hãy thử chơi xung quanh với việc đặt chú giải ở những nơi khác nhau:

Vì vậy, hãy bắt đầu với một ví dụ chung:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

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

for i in xrange(5):
    ax.plot(x, i * x, label='$y = %ix$' % i)

ax.legend()

plt.show()

văn bản thay thế

Nếu chúng ta làm điều tương tự, nhưng sử dụng bbox_to_anchorđối số từ khóa, chúng ta có thể dịch chuyển chú thích bên ngoài ranh giới trục:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

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

for i in xrange(5):
    ax.plot(x, i * x, label='$y = %ix$' % i)

ax.legend(bbox_to_anchor=(1.1, 1.05))

plt.show()

văn bản thay thế

Tương tự, bạn có thể làm cho chú giải trở nên ngang hơn và / hoặc đặt nó ở trên cùng của hình (Tôi cũng đang bật các góc tròn và một bóng thả đơn giản):

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

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

for i in xrange(5):
    line, = ax.plot(x, i * x, label='$y = %ix$'%i)

ax.legend(loc='upper center', bbox_to_anchor=(0.5, 1.05),
          ncol=3, fancybox=True, shadow=True)
plt.show()

văn bản thay thế

Ngoài ra, bạn có thể thu nhỏ chiều rộng của âm mưu hiện tại và đặt chú thích hoàn toàn bên ngoài trục của hình (lưu ý: nếu bạn sử dụng chặt chẽ_layout () , sau đó bỏ qua ax.set_poseition ():

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

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

for i in xrange(5):
    ax.plot(x, i * x, label='$y = %ix$'%i)

# Shrink current axis by 20%
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])

# Put a legend to the right of the current axis
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

plt.show()

văn bản thay thế

Và theo cách tương tự, bạn có thể thu nhỏ cốt truyện theo chiều dọc và đặt chú thích ngang ở phía dưới:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

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

for i in xrange(5):
    line, = ax.plot(x, i * x, label='$y = %ix$'%i)

# Shrink current axis's height by 10% on the bottom
box = ax.get_position()
ax.set_position([box.x0, box.y0 + box.height * 0.1,
                 box.width, box.height * 0.9])

# Put a legend below current axis
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05),
          fancybox=True, shadow=True, ncol=5)

plt.show()

văn bản thay thế

Có một cái nhìn vào hướng dẫn huyền thoại matplotlib . Bạn cũng có thể xem qua plt.figlegend().


10
Nếu bất cứ ai gặp vấn đề với điều này, hãy lưu ý rằng chặt chẽ_layout () sẽ gây ra sự cố!
Matthew G.

4
câu trả lời chính xác! liên kết chính xác đến tài liệu là matplotlib.org/users/legend_guide.html#legend-location
meduz

4
như tính đầy đủ, bạn có thể nói rằng nói chung (tổng hợp từ tài liệu) " bbox_to_anchorlà một bộ gồm 4 phao (x, y, chiều rộng, chiều cao của hộp) hoặc một tuple 2 phao (x, y) trong các trục được chuẩn hóa tọa độ. "
meduz

5
Tôi phải thừa nhận đây có lẽ là câu trả lời SO được truy cập nhiều nhất của tôi từ trước đến nay. Tôi chỉ không thể giúp quay lại nó nhiều lần bởi vì không có cách nào một người hợp lý có thể nhớ logic này mà không cần tìm nó ở đây.
KT.

9
Lưu ý rằng nếu bạn muốn lưu hình vào một tệp, có lẽ bạn nên lưu trữ đối tượng được trả lại, tức là legend = ax.legend()và sau đófig.savefig(bbox_extra_artists=(legend,))
Coldfix

792

Đặt huyền thoại ( bbox_to_anchor)

Một chú giải được định vị bên trong hộp giới hạn của các trục bằng cách sử dụng locđối số plt.legend.
Ví dụ: loc="upper right"đặt chú giải ở góc trên bên phải của hộp giới hạn, theo mặc định, phạm vi từ (0,0)đến (1,1)tọa độ trục (hoặc trong ký hiệu hộp giới hạn (x0,y0, width, height)=(0,0,1,1)).

Để đặt chú giải bên ngoài hộp giới hạn trục, người ta có thể chỉ định một tuple (x0,y0)tọa độ trục của góc dưới bên trái của chú giải.

plt.legend(loc=(1.04,0))

Tuy nhiên, một cách tiếp cận linh hoạt hơn sẽ là chỉ định thủ công hộp giới hạn mà theo đó chú thích sẽ được đặt, sử dụng bbox_to_anchorđối số. Người ta có thể hạn chế chỉ cung cấp (x0,y0)một phần của hộp. Điều này tạo ra một hộp zero zero, trong đó chú giải sẽ mở rộng theo hướng được đưa ra bởi locđối số. Ví dụ

plt.legend (bbox_to_anchor = (1.04,1), loc = "phía trên bên trái")

đặt chú giải bên ngoài các trục, sao cho góc trên bên trái của chú giải nằm ở vị trí (1.04,1)tọa độ trục.

Các ví dụ khác được đưa ra dưới đây, trong đó bổ sung sự tương tác giữa các đối số khác nhau như modencolsđược hiển thị.

nhập mô tả hình ảnh ở đây

l1 = plt.legend(bbox_to_anchor=(1.04,1), borderaxespad=0)
l2 = plt.legend(bbox_to_anchor=(1.04,0), loc="lower left", borderaxespad=0)
l3 = plt.legend(bbox_to_anchor=(1.04,0.5), loc="center left", borderaxespad=0)
l4 = plt.legend(bbox_to_anchor=(0,1.02,1,0.2), loc="lower left",
                mode="expand", borderaxespad=0, ncol=3)
l5 = plt.legend(bbox_to_anchor=(1,0), loc="lower right", 
                bbox_transform=fig.transFigure, ncol=3)
l6 = plt.legend(bbox_to_anchor=(0.4,0.8), loc="upper right")

Chi tiết về cách diễn giải đối số 4-tuple bbox_to_anchor, như trong l4, có thể được tìm thấy trong câu hỏi này . Việc mode="expand"mở rộng huyền thoại theo chiều ngang bên trong hộp giới hạn được đưa ra bởi 4-tuple. Đối với một huyền thoại mở rộng theo chiều dọc, xem câu hỏi này .

Đôi khi nó có thể hữu ích để chỉ định hộp giới hạn trong tọa độ hình thay vì tọa độ trục. Điều này được thể hiện trong ví dụ l5từ phía trên, trong đó bbox_transformđối số được sử dụng để đặt chú giải ở góc dưới bên trái của hình.

Hậu xử lý

Việc đặt huyền thoại bên ngoài các trục thường dẫn đến tình huống không mong muốn rằng nó hoàn toàn hoặc một phần bên ngoài khung vẽ.

Giải pháp cho vấn đề này là:

  • Điều chỉnh các tham số subplot
    Người ta có thể điều chỉnh các tham số subplot sao cho các trục chiếm ít không gian bên trong hình (và do đó để lại nhiều không gian hơn cho chú giải) bằng cách sử dụng plt.subplots_adjust. Ví dụ

    plt.subplots_adjust(right=0.7)

    để lại 30% không gian ở phía bên phải của hình, nơi người ta có thể đặt huyền thoại.

  • Bố cục chặt chẽ
    Sử dụng plt.tight_layoutCho phép tự động điều chỉnh các tham số của ô phụ sao cho các phần tử trong hình nằm sát với các cạnh của hình. Thật không may, huyền thoại không được tính đến trong thuyết tự động này, nhưng chúng tôi có thể cung cấp một hộp hình chữ nhật mà toàn bộ khu vực con (bao gồm cả nhãn) sẽ phù hợp.

    plt.tight_layout(rect=[0,0,0.75,1])
  • Lưu hình vớibbox_inches = "tight"
    Lý lẽ bbox_inches = "tight"để plt.savefigcó thể được sử dụng để lưu hình như vậy mà tất cả các nghệ sĩ trên vải (bao gồm cả huyền thoại) là phù hợp vào khu vực lưu. Nếu cần, kích thước hình được tự động điều chỉnh.

    plt.savefig("output.png", bbox_inches="tight")
  • tự động điều chỉnh các tham số của subplot
    Một cách để tự động điều chỉnh vị trí của subplot sao cho chú giải phù hợp bên trong khung vẽ mà không thay đổi kích thước hình có thể được tìm thấy trong câu trả lời này: Tạo hình với kích thước chính xác và không có phần đệm (và chú thích bên ngoài trục)

So sánh giữa các trường hợp được thảo luận ở trên:

nhập mô tả hình ảnh ở đây

Lựa chọn thay thế

Một huyền thoại hình
Một người có thể sử dụng một huyền thoại cho hình thay vì các trục , matplotlib.figure.Figure.legend. Điều này đã trở nên đặc biệt hữu ích cho phiên bản matplotlib> = 2.1, trong đó không cần đối số đặc biệt

fig.legend(loc=7) 

để tạo ra một huyền thoại cho tất cả các nghệ sĩ trong các trục khác nhau của hình. Truyền thuyết được đặt bằng cách sử dụng locđối số, tương tự như cách nó được đặt bên trong một trục, nhưng tham chiếu đến toàn bộ hình - do đó nó sẽ nằm ngoài trục một cách tự động. Những gì còn lại là điều chỉnh các ô con sao cho không có sự chồng chéo giữa truyền thuyết và các trục. Ở đây điểm "Điều chỉnh các tham số subplot" từ trên sẽ hữu ích. Một ví dụ:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,2*np.pi)
colors=["#7aa0c4","#ca82e1" ,"#8bcd50","#e18882"]
fig, axes = plt.subplots(ncols=2)
for i in range(4):
    axes[i//2].plot(x,np.sin(x+i), color=colors[i],label="y=sin(x+{})".format(i))

fig.legend(loc=7)
fig.tight_layout()
fig.subplots_adjust(right=0.75)   
plt.show()

nhập mô tả hình ảnh ở đây

Chú thích bên trong các trục con phụ chuyên dụng
Một cách khác để sử dụng bbox_to_anchorsẽ là đặt chú giải vào các trục con phụ chuyên dụng ( lax). Vì subplot huyền thoại nên nhỏ hơn cốt truyện, chúng ta có thể sử dụng gridspec_kw={"width_ratios":[4,1]}khi tạo trục. Chúng ta có thể ẩn các trục lax.axis("off")nhưng vẫn đặt một chú giải. Các tay cầm và nhãn chú thích cần lấy từ cốt truyện thực thông qua h,l = ax.get_legend_handles_labels(), và sau đó có thể được cung cấp cho chú giải trong phần laxphụ , lax.legend(h,l). Một ví dụ đầy đủ là dưới đây.

import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = 6,2

fig, (ax,lax) = plt.subplots(ncols=2, gridspec_kw={"width_ratios":[4,1]})
ax.plot(x,y, label="y=sin(x)")
....

h,l = ax.get_legend_handles_labels()
lax.legend(h,l, borderaxespad=0)
lax.axis("off")

plt.tight_layout()
plt.show()

Điều này tạo ra một cốt truyện khá giống với cốt truyện ở trên:

nhập mô tả hình ảnh ở đây

Chúng ta cũng có thể sử dụng các trục đầu tiên để đặt huyền thoại, nhưng sử dụng các bbox_transformtrục huyền thoại,

ax.legend(bbox_to_anchor=(0,0,1,1), bbox_transform=lax.transAxes)
lax.axis("off")

Trong phương pháp này, chúng ta không cần phải có các xử lý chú giải bên ngoài, nhưng chúng ta cần chỉ định bbox_to_anchorđối số.

Đọc thêm và ghi chú:

  • Xem xét hướng dẫn truyền thuyết matplotlib với một số ví dụ về những thứ khác bạn muốn làm với truyền thuyết.
  • Một số mã ví dụ để đặt huyền thoại cho biểu đồ hình tròn có thể được tìm thấy trực tiếp trong câu trả lời cho câu hỏi này: Python - Truyền thuyết trùng lặp với biểu đồ hình tròn
  • Đối locsố có thể lấy số thay vì chuỗi, làm cho các cuộc gọi ngắn hơn, tuy nhiên, chúng không được ánh xạ trực quan với nhau. Đây là ánh xạ để tham khảo:

nhập mô tả hình ảnh ở đây


Đưa huyền thoại vào một hiệp đồng trục phụ chuyên dụng rất độc đáo với fig.tight_layout. Nếu bạn đang sử dụng plt.subplotsđể tạo các trục, chỉ cần cung cấp cho nó một cái gì đó như gridspec_kw={'height_ratios': [100, 1]}(hoặc width_ratios) để các trục của huyền thoại là nhỏ ... Sau đó fig.tight_layout()sẽ mở rộng nó cho phù hợp. Ít nhất là cho matplotlib 3.0.3.
chuyến đi

161

Chỉ cần gọi cuộc legend()gọi sau plot()cuộc gọi như thế này:

# matplotlib
plt.plot(...)
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))

# Pandas
df.myCol.plot().legend(loc='center left', bbox_to_anchor=(1, 0.5))

Kết quả sẽ trông giống như thế này:

nhập mô tả hình ảnh ở đây


4
hoạt động khi chuyển các tham số tương tự cho matplotlib.pyplot.legend cũng như vậy
kidmose

8
Điều này có cắt đứt những từ trong truyền thuyết cho bất cứ ai khác không?
dùng1717828

85

Để đặt chú giải bên ngoài khu vực cốt truyện, hãy sử dụng locbbox_to_anchortừ khóa của legend(). Ví dụ: đoạn mã sau sẽ đặt chú giải ở bên phải của khu vực cốt truyện:

legend(loc="upper left", bbox_to_anchor=(1,1))

Để biết thêm thông tin, xem hướng dẫn truyền thuyết


10
Được rồi - Tôi thích cách thực hiện, nhưng khi tôi đi lưu hình (mà không thay đổi kích thước thủ công trong cửa sổ, điều mà tôi không muốn làm mỗi lần), huyền thoại sẽ bị cắt nhỏ. Bất cứ ý tưởng về cách tôi có thể khắc phục điều đó?
Astromax

@astromax Tôi không chắc nhưng có lẽ thử gọi plt.tight_layout()?
Christian Alis

81

Câu trả lời ngắn: bạn có thể sử dụng bbox_to_anchor+ bbox_extra_artists+ bbox_inches='tight'.


Câu trả lời dài hơn: Bạn có thể sử dụng bbox_to_anchorđể chỉ định thủ công vị trí của hộp chú giải, như một số người khác đã chỉ ra trong câu trả lời.

Tuy nhiên, vấn đề thông thường là hộp chú giải bị cắt, ví dụ:

import matplotlib.pyplot as plt

# data 
all_x = [10,20,30]
all_y = [[1,3], [1.5,2.9],[3,2]]

# Plot
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(all_x, all_y)

# Add legend, title and axis labels
lgd = ax.legend( [ 'Lag ' + str(lag) for lag in all_x], loc='center right', bbox_to_anchor=(1.3, 0.5))
ax.set_title('Title')
ax.set_xlabel('x label')
ax.set_ylabel('y label')

fig.savefig('image_output.png', dpi=300, format='png')

nhập mô tả hình ảnh ở đây

Để ngăn hộp chú giải khỏi bị cắt, khi bạn lưu hình, bạn có thể sử dụng các tham số bbox_extra_artistsbbox_inchesyêu cầu savefigbao gồm các phần tử được cắt trong hình ảnh đã lưu:

fig.savefig('image_output.png', bbox_extra_artists=(lgd,), bbox_inches='tight')

Ví dụ (Tôi chỉ thay đổi dòng cuối cùng để thêm 2 tham số vào fig.savefig()):

import matplotlib.pyplot as plt

# data 
all_x = [10,20,30]
all_y = [[1,3], [1.5,2.9],[3,2]]

# Plot
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(all_x, all_y)

# Add legend, title and axis labels
lgd = ax.legend( [ 'Lag ' + str(lag) for lag in all_x], loc='center right', bbox_to_anchor=(1.3, 0.5))
ax.set_title('Title')
ax.set_xlabel('x label')
ax.set_ylabel('y label')    

fig.savefig('image_output.png', dpi=300, format='png', bbox_extra_artists=(lgd,), bbox_inches='tight')

nhập mô tả hình ảnh ở đây

Tôi ước rằng matplotlib thực sự sẽ cho phép vị trí bên ngoài cho hộp huyền thoại như Matlab làm :

figure
x = 0:.2:12;
plot(x,besselj(1,x),x,besselj(2,x),x,besselj(3,x));
hleg = legend('First','Second','Third',...
              'Location','NorthEastOutside')
% Make the text of the legend italic and color it brown
set(hleg,'FontAngle','italic','TextColor',[.3,.2,.1])

nhập mô tả hình ảnh ở đây


6
Cảm ơn bạn rất nhiều! Các tham số "bbox_to_anchor", "bbox_extra_artist" và "" bbox_inches = 'chặt chẽ "chính xác là những gì tôi cần để làm cho nó hoạt động chính xác. Tuyệt vời!
Demitrian

6
Cảm ơn bạn, nhưng thực sự bbox_inches='tight'hoạt động hoàn hảo với tôi ngay cả khi không có bbox_extra_artist
avtomaton 8/11/2016

1
@avtomaton Cảm ơn, bạn nên biết, bạn sử dụng phiên bản matplotlib nào?
Franck Dernoncourt

1
@FranckDernoncourt python3, matplotlib phiên bản 1.5.3
avtomaton

68

Ngoài tất cả các câu trả lời xuất sắc ở đây, các phiên bản mới hơn matplotlibpylabcó thể tự động xác định nơi đặt chú giải mà không can thiệp vào các âm mưu , nếu có thể.

pylab.legend(loc='best')

Điều này sẽ tự động đặt huyền thoại ra khỏi dữ liệu nếu có thể! So sánh việc sử dụng loc = 'tốt nhất'

Tuy nhiên, nếu không có nơi nào để đặt chú giải mà không chồng chéo dữ liệu, thì bạn sẽ muốn thử một trong những câu trả lời khác; sử dụng loc="best"sẽ không bao giờ đặt huyền thoại bên ngoài cốt truyện.


2
Cảm ơn bạn đã chỉ ra điều này! Tôi đã tìm kiếm điều này một vài năm trước và không tìm thấy nó, và nó là thứ gì đó thực sự giúp cuộc sống của tôi dễ dàng hơn.
Edgar H

4
Tùy chọn này hữu ích nhưng không trả lời được câu hỏi nên tôi đã bỏ qua. theo như tôi có thể nói, tốt nhất đừng bao giờ đặt huyền thoại bên ngoài cốt truyện
Tommy

3
@ Mẹ: Trong các bình luận của OP (dường như đã biến mất ngay bây giờ), rõ ràng OP đã muốn huyền thoại không che dữ liệu đồ thị, và anh ấy nghĩ rằng bên ngoài cốt truyện là cách duy nhất để làm điều đó. Bạn có thể thấy điều này trong các câu trả lời từ mefathy, Mateo Sanchez, Bastiaan và radtek. OP hỏi cho X, nhưng ông muốn Y .
dotancohen

1
Thật ra là không. Anh ấy / cô ấy đặc biệt yêu cầu huyền thoại ở ngoài cốt truyện. Đó là tên của câu hỏi;) "Làm thế nào để đưa huyền thoại ra khỏi cốt truyện".
durbachit

4
Điều này không đảm bảo rằng truyền thuyết không làm lu mờ dữ liệu. Chỉ cần thực hiện một cốt truyện rất dày đặc - không có nơi nào để đặt huyền thoại. Ví dụ: hãy thử điều này ... từ numpy import arange, sin, pi import matplotlib.pyplot as plt t = arange (0.0, 100.0, 0.01) fig = plt.figure (1) ax1 = fig.add_subplot (211) ax1. phân tán (t, sin (2 * pi * t), nhãn = 'test') ax1.grid (Đúng) # ax1.set_ylim ((- 2, 2)) ax1.set_ylabel ('1 Hz') ax1.set_title ( 'Một sóng hình sin hoặc hai') cho nhãn trong ax1.get_xticklabels (): nhãn.set_color ('r') plt.legend (loc = 'best') plt.show ()
adam.r

56

Câu trả lời ngắn : Gọi kéo theo truyền thuyết và tương tác di chuyển nó bất cứ nơi nào bạn muốn:

ax.legend().draggable()

Trả lời dài : Nếu bạn thích đặt chú giải một cách tương tác / thủ công hơn là lập trình, bạn có thể chuyển chế độ có thể kéo của chú giải để bạn có thể kéo nó đến bất cứ nơi nào bạn muốn. Kiểm tra ví dụ dưới đây:

import matplotlib.pylab as plt
import numpy as np
#define the figure and get an axes instance
fig = plt.figure()
ax = fig.add_subplot(111)
#plot the data
x = np.arange(-5, 6)
ax.plot(x, x*x, label='y = x^2')
ax.plot(x, x*x*x, label='y = x^3')
ax.legend().draggable()
plt.show()

Không chắc chắn tôi hiểu điều này đầy đủ. Làm thế nào để tôi "kéo" huyền thoại đến bất cứ nơi nào tôi muốn với điều này? Tôi đang sử dụng Python 3.6 và Jupyter Notebook
sb2020

14

Không chính xác những gì bạn yêu cầu, nhưng tôi thấy đó là một giải pháp thay thế cho cùng một vấn đề. Làm cho huyền thoại bán trong suốt, như vậy: cốt truyện matplotlib với huyền thoại bán trong suốt và hộp văn bản bán trong suốt

Làm điều này với:

fig = pylab.figure()
ax = fig.add_subplot(111)
ax.plot(x,y,label=label,color=color)
# Make the legend transparent:
ax.legend(loc=2,fontsize=10,fancybox=True).get_frame().set_alpha(0.5)
# Make a transparent text box
ax.text(0.02,0.02,yourstring, verticalalignment='bottom',
                     horizontalalignment='left',
                     fontsize=10,
                     bbox={'facecolor':'white', 'alpha':0.6, 'pad':10},
                     transform=self.ax.transAxes)

8

Như đã lưu ý, bạn cũng có thể đặt huyền thoại trong cốt truyện, hoặc hơi tắt nó ra rìa. Dưới đây là một ví dụ sử dụng API Plotly Python , được tạo bằng IPython Notebook . Tôi ở trong đội.

Để bắt đầu, bạn sẽ muốn cài đặt các gói cần thiết:

import plotly
import math
import random
import numpy as np

Sau đó, cài đặt Plotly:

un='IPython.Demo'
k='1fw3zw2o13'
py = plotly.plotly(username=un, key=k)


def sin(x,n):
sine = 0
for i in range(n):
    sign = (-1)**i
    sine = sine + ((x**(2.0*i+1))/math.factorial(2*i+1))*sign
return sine

x = np.arange(-12,12,0.1)

anno = {
'text': '$\\sum_{k=0}^{\\infty} \\frac {(-1)^k x^{1+2k}}{(1 + 2k)!}$',
'x': 0.3, 'y': 0.6,'xref': "paper", 'yref': "paper",'showarrow': False,
'font':{'size':24}
}

l = {
'annotations': [anno], 
'title': 'Taylor series of sine',
'xaxis':{'ticks':'','linecolor':'white','showgrid':False,'zeroline':False},
'yaxis':{'ticks':'','linecolor':'white','showgrid':False,'zeroline':False},
'legend':{'font':{'size':16},'bordercolor':'white','bgcolor':'#fcfcfc'}
}

py.iplot([{'x':x, 'y':sin(x,1), 'line':{'color':'#e377c2'}, 'name':'$x\\\\$'},\
      {'x':x, 'y':sin(x,2), 'line':{'color':'#7f7f7f'},'name':'$ x-\\frac{x^3}{6}$'},\
      {'x':x, 'y':sin(x,3), 'line':{'color':'#bcbd22'},'name':'$ x-\\frac{x^3}{6}+\\frac{x^5}{120}$'},\
      {'x':x, 'y':sin(x,4), 'line':{'color':'#17becf'},'name':'$ x-\\frac{x^5}{120}$'}], layout=l)

Điều này tạo ra biểu đồ của bạn và cho phép bạn có cơ hội giữ huyền thoại trong chính cốt truyện. Mặc định cho chú giải nếu nó không được đặt là đặt nó vào cốt truyện, như được hiển thị ở đây.

nhập mô tả hình ảnh ở đây

Đối với vị trí thay thế, bạn có thể căn chỉnh chặt chẽ cạnh của biểu đồ và đường viền của chú giải và xóa các đường viền cho phù hợp hơn.

nhập mô tả hình ảnh ở đây

Bạn có thể di chuyển và định kiểu lại chú giải và biểu đồ bằng mã hoặc với GUI. Để thay đổi chú giải, bạn có các tùy chọn sau để định vị chú giải bên trong biểu đồ bằng cách gán giá trị x và y của <= 1. Ví dụ:

  • {"x" : 0,"y" : 0} - Dưới cùng bên trái
  • {"x" : 1, "y" : 0} -- Góc phải ở phía dưới
  • {"x" : 1, "y" : 1} -- Trên cùng bên phải
  • {"x" : 0, "y" : 1} - Trên cùng bên trái
  • {"x" :.5, "y" : 0} -- Trung tâm trên
  • {"x": .5, "y" : 1} -- Trung tâm hàng đầu

Trong trường hợp này, chúng tôi chọn phía trên bên phải legendstyle = {"x" : 1, "y" : 1}, cũng được mô tả trong tài liệu :

nhập mô tả hình ảnh ở đây


3

Một cái gì đó dọc theo những dòng này làm việc cho tôi. Bắt đầu với một chút mã được lấy từ Joe, phương pháp này sửa đổi độ rộng cửa sổ để tự động điều chỉnh một chú giải ở bên phải của hình.

import matplotlib.pyplot as plt
import numpy as np

plt.ion()

x = np.arange(10)

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

for i in xrange(5):
    ax.plot(x, i * x, label='$y = %ix$'%i)

# Put a legend to the right of the current axis
leg = ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

plt.draw()

# Get the ax dimensions.
box = ax.get_position()
xlocs = (box.x0,box.x1)
ylocs = (box.y0,box.y1)

# Get the figure size in inches and the dpi.
w, h = fig.get_size_inches()
dpi = fig.get_dpi()

# Get the legend size, calculate new window width and change the figure size.
legWidth = leg.get_window_extent().width
winWidthNew = w*dpi+legWidth
fig.set_size_inches(winWidthNew/dpi,h)

# Adjust the window size to fit the figure.
mgr = plt.get_current_fig_manager()
mgr.window.wm_geometry("%ix%i"%(winWidthNew,mgr.window.winfo_height()))

# Rescale the ax to keep its original size.
factor = w*dpi/winWidthNew
x0 = xlocs[0]*factor
x1 = xlocs[1]*factor
width = box.width*factor
ax.set_position([x0,ylocs[0],x1-x0,ylocs[1]-ylocs[0]])

plt.draw()

Tôi thấy điều này khá hữu ích và nó làm việc cho tôi. Lưu ý rằng nếu bạn đang ở trong phụ trợ wx (ví dụ: sử dụng windows), hãy thay thế mgr.window.wm_geometry ("% ix% i"% (winWidthNew, mgr.window.winfo_height ())) bằng mgr.window.SetClientSizeWH (winWid , winHeightNew) hoặc tương tự
Ezekiel Kruglick

Nếu bạn đang sử dụng phụ trợ Qt4Agg (mặc định trên bản cài đặt matplotlib Linux của tôi), thì hãy thay thế dòng này mgr.window.wm_geometry(...)bằng mgr.window.setFixedWidth(winWidthNew).
Filip S.

Và, như tôi vừa phát hiện ra, nếu bạn đang sử dụng một phụ trợ không hiển thị bất kỳ cửa sổ nào, có nghĩa là để lưu thẳng vào một tệp (như phụ trợ SVG và AGG), chỉ cần bỏ qua việc thay đổi kích thước cửa sổ hoàn toàn. fig.set_size_inches(...)chăm sóc thay đổi kích thước bạn cần.
Filip S.

3

Thật đáng để làm mới câu hỏi này, vì các phiên bản mới hơn của Matplotlib đã giúp việc định vị huyền thoại bên ngoài cốt truyện dễ dàng hơn nhiều. Tôi đã tạo ra ví dụ này với phiên bản Matplotlib 3.1.1.

Người dùng có thể truyền 2 tuple tọa độ cho loctham số để định vị chú giải ở bất cứ đâu trong khung giới hạn. Gotcha duy nhất là bạn cần chạy plt.tight_layout()để lấy matplotlib để tính toán lại kích thước cốt truyện để có thể nhìn thấy huyền thoại:

import matplotlib.pyplot as plt

plt.plot([0, 1], [0, 1], label="Label 1")
plt.plot([0, 1], [0, 2], label='Label 2')

plt.legend(loc=(1.05, 0.5))
plt.tight_layout()

Điều này dẫn đến cốt truyện sau:

cốt truyện với huyền thoại bên ngoài

Người giới thiệu:


2

Bạn cũng có thể thử figlegend. Có thể tạo một huyền thoại độc lập với bất kỳ đối tượng Axes nào. Tuy nhiên, bạn có thể cần tạo một số Đường dẫn "giả" để đảm bảo định dạng cho các đối tượng được truyền chính xác.


1

Dưới đây là một ví dụ từ hướng dẫn matplotlib được tìm thấy ở đây . Đây là một trong những ví dụ đơn giản hơn nhưng tôi đã thêm tính minh bạch vào chú giải và thêm plt.show () để bạn có thể dán phần này vào trình vỏ tương tác và nhận được kết quả:

import matplotlib.pyplot as plt
p1, = plt.plot([1, 2, 3])
p2, = plt.plot([3, 2, 1])
p3, = plt.plot([2, 3, 1])
plt.legend([p2, p1, p3], ["line 1", "line 2", "line 3"]).get_frame().set_alpha(0.5)
plt.show()

1

Giải pháp hiệu quả với tôi khi tôi có huyền thoại lớn là sử dụng thêm bố cục hình ảnh trống. Trong ví dụ sau tôi đã tạo 4 hàng và ở phía dưới, tôi vẽ hình ảnh với phần bù cho chú thích (bbox_to_anchor) ở trên cùng, nó không bị cắt.

f = plt.figure()
ax = f.add_subplot(414)
lgd = ax.legend(loc='upper left', bbox_to_anchor=(0, 4), mode="expand", borderaxespad=0.3)
ax.autoscale_view()
plt.savefig(fig_name, format='svg', dpi=1200, bbox_extra_artists=(lgd,), bbox_inches='tight')

1

Đây là một giải pháp khác, tương tự như thêm bbox_extra_artistsbbox_inches, trong đó bạn không cần phải có thêm nghệ sĩ trong phạm vi savefigcuộc gọi của mình . Tôi đã nghĩ ra điều này vì tôi tạo ra hầu hết cốt truyện của mình bên trong các hàm.

Thay vì thêm tất cả các bổ sung của bạn vào hộp giới hạn khi bạn muốn viết nó ra, bạn có thể thêm chúng trước các Figurenghệ sĩ. Sử dụng một cái gì đó tương tự như câu trả lời của Franck Dernoncourt ở trên :

import matplotlib.pyplot as plt

# data 
all_x = [10,20,30]
all_y = [[1,3], [1.5,2.9],[3,2]]

# plotting function
def gen_plot(x, y):
    fig = plt.figure(1)
    ax = fig.add_subplot(111)
    ax.plot(all_x, all_y)
    lgd = ax.legend( [ "Lag " + str(lag) for lag in all_x], loc="center right", bbox_to_anchor=(1.3, 0.5))
    fig.artists.append(lgd) # Here's the change
    ax.set_title("Title")
    ax.set_xlabel("x label")
    ax.set_ylabel("y label")
    return fig

# plotting
fig = gen_plot(all_x, all_y)

# No need for `bbox_extra_artists`
fig.savefig("image_output.png", dpi=300, format="png", bbox_inches="tight")

Đây là cốt truyện được tạo ra.


-1

không biết bạn đã sắp xếp vấn đề của mình chưa ... có lẽ là có, nhưng ... tôi chỉ đơn giản sử dụng chuỗi 'bên ngoài' cho vị trí, như trong matlab. Tôi đã nhập pylab từ matplotlib. xem mã như sau:

from matplotlib as plt
from matplotlib.font_manager import FontProperties
...
...
t = A[:,0]
sensors = A[:,index_lst]

for i in range(sensors.shape[1]):
    plt.plot(t,sensors[:,i])

plt.xlabel('s')
plt.ylabel('°C')
lgd = plt.legend(b,loc='center left', bbox_to_anchor=(1, 0.5),fancybox = True, shadow = True)

Nhấn vào đây để xem cốt truyện

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.