Python - 图例与饼图重叠

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43272206/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 22:45:20  来源:igfitidea点击:

Python - Legend overlaps with the pie chart

pythonmatplotlibcharts

提问by cassandra

Using matplotlib in python. The legend overlaps with my pie chart. Tried various options for "loc" such as "best" ,1,2,3... but to no avail. Any Suggestions as to how to either exactly mention the legend position (such as giving padding from the pie chart boundaries) or at least make sure that it does not overlap?

在 python 中使用 matplotlib。图例与我的饼图重叠。尝试了“loc”的各种选项,例如“best”、1、2、3……但无济于事。关于如何准确提及图例位置(例如从饼图边界提供填充)或至少确保它不重叠的任何建议?

回答by ImportanceOfBeingErnest

The short answer is: You may use plt.legend's arguments loc, bbox_to_anchorand additionally bbox_transformand mode, to position the legend in an axes or figure.

简短的回答是:您可以使用plt.legend's arguments locbbox_to_anchor另外还有bbox_transformand mode,将图例定位在轴或图形中。



长版:

Step 1: Making sure a legend is needed.

第 1 步:确保需要图例。

In many cases no legend is needed at all and the information can be inferred by the context or the color directly:

在许多情况下,根本不需要图例,信息可以直接通过上下文或颜色推断:

enter image description here

在此处输入图片说明

enter image description here

在此处输入图片说明

If indeed the plot cannot live without a legend, proceed to step 2.

如果没有图例,情节确实无法生存,请继续执行步骤 2。

Step 2: Making sure, a pie chart is needed.

第 2 步:确保需要一个饼图。

In many cases pie charts are not the best way to convey information.

在许多情况下,饼图并不是传达信息的最佳方式。

enter image description here

在此处输入图片说明

If the need for a pie chart is unambiguously determined, let's proceed to place the legend.

如果明确确定需要饼图,让我们继续放置图例。

Placing the legend

放置图例

plt.legend()has two main arguments to determine the position of the legend. The most important and in itself sufficient is the locargument.
E.g. plt.legend(loc="upper left")placed the legend such that it sits in the upper left corner of its bounding box. If no further argument is specified, this bounding box will be the entire axes.

plt.legend()有两个主要参数来确定图例的位置。最重要且本身就足够的就是loc论证。
例如,plt.legend(loc="upper left")将图例放置在其边界框的左上角。如果未指定其他参数,则此边界框将是整个轴。

However, we may specify our own bounding box using the bbox_to_anchorargument. If bbox_to_anchoris given a 2-tuple e.g. bbox_to_anchor=(1,1)it means that the bounding box is located at the upper right corner of the axes and has no extent. It then acts as a point relative to which the legend will be placed according to the locargument. It will then expand out of the zero-size bounding box. E.g. if locis "upper left", the upper left corner of the legend is at position (1,1) and the legend will expand to the right and downwards.

但是,我们可以使用bbox_to_anchor参数指定我们自己的边界框。如果bbox_to_anchor给出一个 2 元组,例如bbox_to_anchor=(1,1)它意味着边界框位于轴的右上角并且没有范围。然后,它充当一个相对点,图例将根据loc参数放置在该点上。然后它将扩展到零大小的边界框之外。例如,如果loc"upper left",则图例的左上角位于位置 (1,1) 并且图例将向右和向下扩展。

This concept is used for the above plot, which tells us the shocking truth about the bias in Miss Universe elections.

这个概念用于上面的情节,它告诉我们关于环球小姐选举偏见的令人震惊的真相。

import matplotlib.pyplot as plt
import matplotlib.patches

total = [100]
labels = ["Earth", "Mercury", "Venus", "Mars", "Jupiter",  "Saturn", 
           "Uranus", "Neptune", "Pluto *"]
plt.title('Origin of Miss Universe since 1952')
plt.gca().axis("equal")
pie = plt.pie(total, startangle=90, colors=[plt.cm.Set3(0)],
                            wedgeprops = { 'linewidth': 2, "edgecolor" :"k" })
handles = []
for i, l in enumerate(labels):
    handles.append(matplotlib.patches.Patch(color=plt.cm.Set3((i)/8.), label=l))
plt.legend(handles,labels, bbox_to_anchor=(0.85,1.025), loc="upper left")
plt.gcf().text(0.93,0.04,"* out of competition since 2006", ha="right")
plt.subplots_adjust(left=0.1, bottom=0.1, right=0.75)

In order for the legend not to exceed the figure, we use plt.subplots_adjustto obtain more space between the figure edge and the axis, which can then be taken up by the legend.

为了使图例不超过图形,我们使用plt.subplots_adjust在图形边缘和轴之间获得更多空间,然后可以由图例占据。

There is also the option to use a 4-tuple to bbox_to_anchor. How to use or interprete this is detailed in this question: What does a 4-element tuple argument for 'bbox_to_anchor' mean in matplotlib?
and one may then use the mode="expand"argument to make the legend fit into the specified bounding box.

还可以选择使用 4 元组到bbox_to_anchor. 如何使用或解释这一点在这个问题中有详细说明:“bbox_to_anchor”的 4 元素元组参数在 matplotlib 中意味着什么?
然后可以使用该mode="expand"参数使图例适合指定的边界框。

There are some useful alternatives to this approach:

这种方法有一些有用的替代方法:

Using figure coordinates

使用图形坐标

Instead of specifying the legend position in axes coordinates, one may use figure coordinates. The advantage is that this will allow to simply place the legend in one corner of the figure without adjusting much of the rest. To this end, one would use the bbox_transformargument and supply the figure transformation to it. The coordinates given to bbox_to_anchorare then interpreted as figure coordinates.

可以使用图形坐标,而不是在轴坐标中指定图例位置。优点是这将允许简单地将图例放置在图形的一个角落,而无需调整其余部分。为此,可以使用该bbox_transform参数并为其提供图形转换。然后将给定的坐标bbox_to_anchor解释为图形坐标。

plt.legend(pie[0],labels, bbox_to_anchor=(1,0), loc="lower right", 
                          bbox_transform=plt.gcf().transFigure)

Here (1,0)is the lower right corner of the figure. Because of the default spacings between axes and figure edge, this suffices to place the legend such that it does not overlap with the pie.

(1,0)是图的右下角。由于轴和图形边缘之间的默认间距,这足以放置图例,使其不与饼图重叠。

enter image description here

在此处输入图片说明

In other cases, one might still need to adapt those spacings such that no overlap is seen, e.g.

在其他情况下,人们可能仍需要调整这些间距,以便看不到重叠,例如

title = plt.title('What slows down my computer')
title.set_ha("left")
plt.gca().axis("equal")
pie = plt.pie(total, startangle=0)
labels=["Trojans", "Viruses", "Too many open tabs", "The anti-virus software"]
plt.legend(pie[0],labels, bbox_to_anchor=(1,0.5), loc="center right", fontsize=10, 
           bbox_transform=plt.gcf().transFigure)
plt.subplots_adjust(left=0.0, bottom=0.1, right=0.45)

enter image description here

在此处输入图片说明

Saving the file with bbox_inches="tight"

保存文件 bbox_inches="tight"

Now there may be cases where we are more interested in the saved figure than at what is shown on the screen. We may then simply position the legend at the edge of the figure, like so

现在可能有些情况下我们对保存的图形比屏幕上显示的更感兴趣。然后我们可以简单地将图例放置在图形的边缘,就像这样

enter image description here

在此处输入图片说明

but then save it using the bbox_inches="tight"to savefig,

但是然后使用bbox_inches="tight"to保存它savefig

plt.savefig("output.png", bbox_inches="tight")

This will create a larger figure, which sits tight around the contents of the canvas:

这将创建一个更大的图形,它紧紧围绕画布的内容:

enter image description here

在此处输入图片说明

A sophisticated approach, which allows to place the legend tightly inside the figure, without changing the figure size is presented here: Creating figure with exact size and no padding (and legend outside the axes)

一种复杂的方法,它允许将图例紧密地放置在图形内部,而不改变图形大小,这里介绍了: 创建具有精确大小且没有填充的图形(以及轴外的图例)

Using Subplots

使用子图

An alternative is to use subplots to reserve space for the legend. In this case one subplot could take the pie chart, another subplot would contain the legend. This is shown below.

另一种方法是使用子图为图例保留空间。在这种情况下,一个子图可以采用饼图,另一个子图将包含图例。这如下所示。

fig = plt.figure(4, figsize=(3,3))
ax = fig.add_subplot(211) 
total = [4,3,2,81]
labels = ["tough working conditions", "high risk of accident", 
              "harsh weather", "it's not allowed to watch DVDs"]
ax.set_title('What people know about oil rigs')
ax.axis("equal")
pie = ax.pie(total, startangle=0)
ax2 = fig.add_subplot(212)
ax2.axis("off") 
ax2.legend(pie[0],labels, loc="center")

enter image description here

在此处输入图片说明