2017-08-18 3 views
3

Es wurden viele Fragen bezüglich der Überlappung von Etiketten für die Kreisdiagrammdarstellung gestellt. Ich konnte jedoch keine automatisierte Lösung finden, außer sie in die Legende zu konvertieren. Diese Lösung funktioniert nicht für mich, da ich viele Werte habe (etwa 60), und die Umwandlung in eine Legende wird die Handlung sehr chaotisch und unklar erscheinen lassen. Also meine Frage, wenn ich Kuchenkeile um den Kuchen kennzeichnen möchte, ist die automatisierte Lösung für MatPlotLib Version 2.0.2, die Etiketten einen guten Abstand (keine Überlappung) ermöglicht? Die einzige Lösung, die ich gefunden habe, ist, es manuell mit annotation() zu tun. Siehe unten das Skript mit Dummy-Werten. Ist es auch möglich, den Keil des Kuchens mit dem zugehörigen Etikett mit einem Pfeil zu verbinden?Wie vermeidet man die Überlappung von Kuchendiagrammen in MatPlotLib Version 2.0.2?

I verwenden Python 2.7 und 2.0.2 matplotlib

Danke,

Beispiel 1 (überlappenden Etiketten)

enter image description here

Beispiel 2 (manuell korrigiert)

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

haben Sie bei plotly einen Blick hatte, kann er all dies tun? [link here] (https://plot.ly/python/pie-charts/) –

+0

Erstens gibt es keinen automatischen Weg, der verhindert, dass sich Text oder Etiketten in matplotlib überlappen. In Bezug auf Pfeile erlaubt 'annotieren' die Verwendung von Pfeilen. Vielleicht ist auch [diese Frage] (https://stackoverflow.com/questions/43349004/python-piechart-is-it-possible-to-do-callout-labels) von Interesse. – ImportanceOfBeingErnest

Antwort

2

Sie könnten experimentieren mit dem Drehen des Textes. Das Folgende bestimmt einen Winkel für jeden Keil und dreht dann den Anmerkungstext entsprechend. Je nach Winkel werden einige zusätzliche Optimierungen benötigt, um die Textausrichtung zu bestimmen und sicherzustellen, dass der Text nicht auf dem Kopf steht. Möglicherweise müssen Sie dies weiter verfeinern.

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

, die als angezeigt würde:

pie with rotated annotations

Verwandte Themen