Python - 图例与饼图重叠 [英] Python - Legend overlaps with the pie chart

查看:130
本文介绍了Python - 图例与饼图重叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

简短的回答是:您可以使用

如果没有图例,情节确实无法生存,请继续第 2 步.

第 2 步:确保需要饼图.

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

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

放置图例

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

但是,我们可以使用 bbox_to_anchor 参数指定我们自己的边界框.如果 bbox_to_anchor 被赋予一个 2 元组,例如bbox_to_anchor=(1,1) 表示边界框位于轴的右上角,没有范围.然后它作为一个点,根据 loc 参数放置图例.然后它将扩展到零大小的边界框之外.例如.如果 loc"upper left",则图例的左上角在位置 (1,1),图例将向右和向下扩展.

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

将 matplotlib.pyplot 导入为 plt导入 matplotlib.patches总计 = [100]标签 = [地球"、水星"、金星"、火星"、木星"、土星"、天王星"、海王星"、冥王星*"]plt.title('1952 年以来环球小姐的起源')plt.gca().axis("equal")pie = plt.pie(total, startangle=90, colors=[plt.cm.Set3(0)],wedgeprops = { 'linewidth': 2, "edgecolor" :"k" })句柄 = []对于 i, l 在 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="左上角")plt.gcf().text(0.93,0.04,"* 自 2006 年起退出竞争", ha="right")plt.subplots_adjust(左=0.1,底部=0.1,右=0.75)

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

还可以选择将 4 元组用于 bbox_to_anchor.如何使用或解释这一点在这个问题中有详细说明:

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

title = plt.title('是什么让我的电脑变慢')title.set_ha("左")plt.gca().axis("equal")pie = plt.pie(total, startangle=0)label=["木马"、"病毒"、"打开的标签页太多"、"杀毒软件"]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)

使用 bbox_inches="tight"

保存文件

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

然后使用 bbox_inches="tight" 将其保存到 savefig,

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

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

一种复杂的方法,它允许将图例紧密地放置在图形内部,而不改变图形大小,如下所示:

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?

解决方案

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


The long version:

Step 1: Making sure a legend is needed.

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

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

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

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

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 loc argument.
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.

However, we may specify our own bounding box using the bbox_to_anchor argument. If bbox_to_anchor is 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 loc argument. It will then expand out of the zero-size bounding box. E.g. if loc is "upper left", the upper left corner of the legend is at position (1,1) and the legend will expand to the right and downwards.

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_adjust to obtain more space between the figure edge and the axis, which can then be taken up by the legend.

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.

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_transform argument and supply the figure transformation to it. The coordinates given to bbox_to_anchor are then interpreted as figure coordinates.

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.

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)

Saving the file with 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

but then save it using the 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:

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")

这篇关于Python - 图例与饼图重叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆