2017-08-18 4 views
3

De nombreuses questions ont été posées concernant le chevauchement des étiquettes pour le traçage de diagrammes à secteurs. Cependant, je ne pouvais pas trouver de solution automatisée, sauf pour les convertir à la légende. Cette solution ne fonctionne pas pour moi car j'ai beaucoup de valeurs (environ 60), et la conversion en légende rendra l'intrigue très désordonnée et peu claire. Donc, ma question, si je veux étiqueter les coins autour du gâteau, est la solution automatisée pour MatPlotLib version 2.0.2 qui permet aux étiquettes d'avoir un bon espacement (pas de chevauchement)? La seule solution que j'ai trouvée est de le faire manuellement avec annotation(). Veuillez voir ci-dessous le script avec des valeurs factices. Est-il également possible de relier le coin de la tarte à l'étiquette associée avec une flèche?Comment éviter le chevauchement des étiquettes de camembert dans MatPlotLib ver.2.0.2?

J'utilise Python 2.7 et 2.0.2 matplotlib

Merci,

Exemple 1 (étiquettes) se chevauchent

enter image description here

Exemple 2 (corrigé manuellement)

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() 
+0

avez-vous eu un coup d'œil à plotly, il peut faire tout cela? [link here] (https://plot.ly/python/pie-charts/) –

+0

Tout d'abord, il n'existe aucun moyen automatique qui empêche le chevauchement de texte ou d'étiquettes dans matplotlib. Concernant les flèches, 'annoter 'permet d'utiliser les flèches. Peut-être que [cette question] (https://stackoverflow.com/questions/43349004/python-piechart-is-it-possible-to-do-callout-labels) est également intéressante ici. – ImportanceOfBeingErnest

Répondre

2

Vous pouvez essayer de faire pivoter le texte. Les éléments suivants déterminent un angle pour chaque coin et font ensuite pivoter le texte d'annotation en conséquence. Quelques ajustements supplémentaires sont nécessaires en fonction de l'angle pour déterminer l'alignement du texte et également pour s'assurer que le texte ne s'affiche pas à l'envers. Vous devrez peut-être affiner davantage cela.

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

qui afficherait comme:

pie with rotated annotations