防止饼图中的标签重叠 Python Matplotlib
Preventing overlapping labels in a pie chart Python Matplotlib
我有一个由以下代码生成的饼图,将标签挤向顶部。有没有更好的方法来添加标签和箭头以免重叠?我不能使用图例;我需要标签在每个切片旁边。
我知道 excel 中有一个“最适合”选项可以解决这样的问题 (Prevent overlapping of data labels in pie chart),但我想知道是否有任何 Python 等效项或方法在图表周围同样 space 标签,但保持切片的线条
import matplotlib.pyplot as plt
import numpy as np
bbox_props=dict(boxstyle='square,pad=0.3',fc ='w',ec='k',lw=0.72)
kw=dict(xycoords='data',textcoords='data',arrowprops=dict(arrowstyle='-'),zorder=0,va='center')
fig1,ax1=plt.subplots()
labels=["first\n1.8%","second\n1.3%","third\n10.5%","fourth\n13.8%","fifth\n7.8%","sixth\n6.7%","seventh\n9.9%","eighth\n12.2%","ninth\n12.7%","tenth\n10.9%","eleventh\n7.6%","twelfth\n4.8%"]
values=[1.8,1.3,10.5,13.8,7.8,6.7,9.9,12.2,12.7,10.9,7.6,4.8]
wedges,texts=ax1.pie(values,explode=[0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01],labeldistance=1.2,startangle=90)
for i,p in enumerate(wedges):
ang=(p.theta2-p.theta1)/2. +p.theta1
y=np.sin(np.deg2rad(ang))
x=np.cos(np.deg2rad(ang))
horizontalalignment={-1:"right",1:"left"}[int(np.sign(x))]
connectionstyle="angle,angleA=0,angleB={}".format(ang)
kw["arrowprops"].update({"connectionstyle":connectionstyle})
ax1.annotate(labels[i],xy=(x, y),xytext=(1.35*np.sign(x),1.4*y),
horizontalalignment=horizontalalignment,**kw)
fig1.show()
适不适合可视化不讨论。假设注释的顺序可以不同,我们可以将数字重新排序为大小的顺序,并相应地更改标签的顺序。这种方法取决于数据,可能仅限于此任务。可能有更聪明的方法来重新排序数据。
import matplotlib.pyplot as plt
import numpy as np
bbox_props=dict(boxstyle='square,pad=0.3',fc ='w',ec='k',lw=0.72)
kw=dict(xycoords='data',textcoords='data',arrowprops=dict(arrowstyle='-'),zorder=0,va='center')
fig1,ax1=plt.subplots()
labels=["first\n1.8%","second\n1.3%","third\n10.5%","fourth\n13.8%","fifth\n7.8%","sixth\n6.7%","seventh\n9.9%","eighth\n12.2%","ninth\n12.7%","tenth\n10.9%","eleventh\n7.6%","twelfth\n4.8%"]
values=[1.8,1.3,10.5,13.8,7.8,6.7,9.9,12.2,12.7,10.9,7.6,4.8]
# Add code
annotate_dict = {k:v for k,v in zip(labels, values)}
val = [[x,y] for x,y in zip(sorted(values, reverse=True),sorted(values))]
values1 = sum(val, [])
new_labels = []
for v in values1[:len(values)]:
for key, value in annotate_dict.items():
if v == value:
new_labels.append(key)
wedges,texts=ax1.pie(values1[:len(values)],explode=[0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01],labeldistance=1.2,startangle=90)
for i,p in enumerate(wedges):
ang=(p.theta2-p.theta1)/2. +p.theta1
y=np.sin(np.deg2rad(ang))
x=np.cos(np.deg2rad(ang))
horizontalalignment={-1:"right",1:"left"}[int(np.sign(x))]
connectionstyle="angle,angleA=0,angleB={}".format(ang)
kw["arrowprops"].update({"connectionstyle":connectionstyle})
ax1.annotate(new_labels[i],xy=(x, y),xytext=(1.35*np.sign(x),1.4*y),
horizontalalignment=horizontalalignment,**kw)
plt.show()
我有一个由以下代码生成的饼图,将标签挤向顶部。有没有更好的方法来添加标签和箭头以免重叠?我不能使用图例;我需要标签在每个切片旁边。
我知道 excel 中有一个“最适合”选项可以解决这样的问题 (Prevent overlapping of data labels in pie chart),但我想知道是否有任何 Python 等效项或方法在图表周围同样 space 标签,但保持切片的线条
import matplotlib.pyplot as plt
import numpy as np
bbox_props=dict(boxstyle='square,pad=0.3',fc ='w',ec='k',lw=0.72)
kw=dict(xycoords='data',textcoords='data',arrowprops=dict(arrowstyle='-'),zorder=0,va='center')
fig1,ax1=plt.subplots()
labels=["first\n1.8%","second\n1.3%","third\n10.5%","fourth\n13.8%","fifth\n7.8%","sixth\n6.7%","seventh\n9.9%","eighth\n12.2%","ninth\n12.7%","tenth\n10.9%","eleventh\n7.6%","twelfth\n4.8%"]
values=[1.8,1.3,10.5,13.8,7.8,6.7,9.9,12.2,12.7,10.9,7.6,4.8]
wedges,texts=ax1.pie(values,explode=[0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01],labeldistance=1.2,startangle=90)
for i,p in enumerate(wedges):
ang=(p.theta2-p.theta1)/2. +p.theta1
y=np.sin(np.deg2rad(ang))
x=np.cos(np.deg2rad(ang))
horizontalalignment={-1:"right",1:"left"}[int(np.sign(x))]
connectionstyle="angle,angleA=0,angleB={}".format(ang)
kw["arrowprops"].update({"connectionstyle":connectionstyle})
ax1.annotate(labels[i],xy=(x, y),xytext=(1.35*np.sign(x),1.4*y),
horizontalalignment=horizontalalignment,**kw)
fig1.show()
适不适合可视化不讨论。假设注释的顺序可以不同,我们可以将数字重新排序为大小的顺序,并相应地更改标签的顺序。这种方法取决于数据,可能仅限于此任务。可能有更聪明的方法来重新排序数据。
import matplotlib.pyplot as plt
import numpy as np
bbox_props=dict(boxstyle='square,pad=0.3',fc ='w',ec='k',lw=0.72)
kw=dict(xycoords='data',textcoords='data',arrowprops=dict(arrowstyle='-'),zorder=0,va='center')
fig1,ax1=plt.subplots()
labels=["first\n1.8%","second\n1.3%","third\n10.5%","fourth\n13.8%","fifth\n7.8%","sixth\n6.7%","seventh\n9.9%","eighth\n12.2%","ninth\n12.7%","tenth\n10.9%","eleventh\n7.6%","twelfth\n4.8%"]
values=[1.8,1.3,10.5,13.8,7.8,6.7,9.9,12.2,12.7,10.9,7.6,4.8]
# Add code
annotate_dict = {k:v for k,v in zip(labels, values)}
val = [[x,y] for x,y in zip(sorted(values, reverse=True),sorted(values))]
values1 = sum(val, [])
new_labels = []
for v in values1[:len(values)]:
for key, value in annotate_dict.items():
if v == value:
new_labels.append(key)
wedges,texts=ax1.pie(values1[:len(values)],explode=[0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01],labeldistance=1.2,startangle=90)
for i,p in enumerate(wedges):
ang=(p.theta2-p.theta1)/2. +p.theta1
y=np.sin(np.deg2rad(ang))
x=np.cos(np.deg2rad(ang))
horizontalalignment={-1:"right",1:"left"}[int(np.sign(x))]
connectionstyle="angle,angleA=0,angleB={}".format(ang)
kw["arrowprops"].update({"connectionstyle":connectionstyle})
ax1.annotate(new_labels[i],xy=(x, y),xytext=(1.35*np.sign(x),1.4*y),
horizontalalignment=horizontalalignment,**kw)
plt.show()