如何在MatPlotLib ver.2.0.2中避免饼图标签重叠?

5
关于饼图绘制中标签重叠的问题,有很多人提出了疑问。然而,除了将它们转换为图例之外,我找不到自动化解决方案。对我来说,这个解决方案行不通,因为我有很多值(大约60个),转换为图例会使图表看起来非常混乱和不清晰。所以我的问题是,如果我想在饼图周围标记饼块,是否有任何MatPlotLib 2.0.2版本的自动化解决方案,可以让标签具有良好的间距(不重叠)?我唯一找到的解决方案是使用annotation()手动完成。请参见下面带有虚拟值的脚本。此外,是否可能用箭头连接饼图的楔形图与相关标签?
我使用Python 2.7和MatPlotLib 2.0.2
谢谢!
示例1(标签重叠)

enter image description here

示例2(手动更正)

enter image description here

import pylab 
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
l = ax.pie([1,0.2, 0.3,0.1,0.4,7,50,35,5,2],#[0, 0.1, 0, 0.1,0,0.1,0,0.1,0,0.1],
            #labels=("one","two","three made up sentences","four is also ther","five becomes a sentence","six it is","seven long", "eight long sent", "nine, as bla bel mo","ten is also short"),
            labels=("","","","","","six it is","seven long", "eight long sent", "nine, as bla bel mo","ten is also short"),
            colors=("b","g","r","y", "b","g","r","y","g","black"),
            startangle =20,
            radius=1,
            frame=True,   # Plot axes frame with the chart if true.
            labeldistance = 1.1 ) #returns a list of matplotlib.patches.Wedge objects

l2 = ax.pie([1,0.2, 0.3,0.1,0.4,7,50,35,5,2],#[0, 0.1, 0, 0.1,0,0.1,0,0.1,0,0.1],
            colors=("r","g","b","w", "g","b","y","r","w","black"),
            startangle =20,
            radius=1-0.7,
            frame=True)   # Plot axes frame with the chart if true.

coor = [t.get_position() for t in l[1]]

ax.axis('equal')
plt.annotate( 'one was very short now ext', xy= (coor[0][0], coor[0][1]) )      # https://kite.com/docs/python/matplotlib.pyplot.annotate
plt.annotate( 'two long sentense',          xy= (coor[1][0], coor[1][1]) ) 
plt.annotate('three things to say' ,        xy= (coor[2][0], coor[2][1]+0.02) ) 
plt.annotate( 'four main tasks to do',      xy= (coor[3][0], coor[3][1]+0.04) ) 
plt.annotate( 'five reasons to avoid',      xy= (coor[4][0], coor[4][1]+0.06 ))   

plt.savefig('test_draft.pdf')
plt.show()

你看过Plotly吗?它可以完成所有这些功能。链接在此 - Naren Murali
首先,在matplotlib中没有自动防止文本或标签重叠的方法。关于箭头,annotate允许使用箭头。也许这个问题对你有帮助:https://dev59.com/X6Dia4cB1Zd3GeqPJtCB。 - ImportanceOfBeingErnest
1个回答

3

您可以尝试旋转文本。以下为每个楔形图确定一个角度,然后相应地旋转注释文本。根据角度需要进行一些额外的微调,以确定文本对齐方式,并确保文本不会倒置。您可能需要进一步完善此功能。

import pylab 
import matplotlib.pyplot as plt
import math

fig, ax = plt.subplots()

labels= [
    "one",
    "two", 
    "three made up sentences", 
    "four is also there", 
    "five becomes a sentence",
    "six it is",
    "seven long", 
    "eight long sent", 
    "nine, as bla bel mo",
    "ten is also short"]

l = ax.pie([1,0.2, 0.3,0.1,0.4,7,50,35,5,2],
            labels=[''] * len(labels),
            colors=("b","g","r","y", "b","g","r","y","g","black"),
            startangle=20,
            radius=1,
            frame=True,   # Plot axes frame with the chart if true.
            labeldistance=1.1) #returns a list of matplotlib.patches.Wedge objects

l2 = ax.pie([1,0.2, 0.3,0.1,0.4,7,50,35,5,2],#[0, 0.1, 0, 0.1,0,0.1,0,0.1,0,0.1],
            colors=("r","g","b","w", "g","b","y","r","w","black"),
            startangle=20,
            radius=1-0.7,
            frame=True)   # Plot axes frame with the chart if true.

for label, t in zip(labels, l[1]):
    x, y = t.get_position()
    angle = int(math.degrees(math.atan2(y, x)))
    ha = "left"
    va = "bottom"

    if angle > 90:
        angle -= 180

    if angle < 0:
        va = "top"

    if -45 <= angle <= 0:
        ha = "right"
        va = "bottom"

    plt.annotate(label, xy=(x,y), rotation=angle, ha=ha, va=va, size=8)

ax.axis('equal')
plt.show() 

将显示为:

带有旋转标注的饼图


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接