Python 从dict创建饼图并更改箭头
我在dict中有一些计数数据,如下所示:Python 从dict创建饼图并更改箭头,python,matplotlib,pie-chart,Python,Matplotlib,Pie Chart,我在dict中有一些计数数据,如下所示: data = {'a_column': 20, 'b_column': 130, 'c_column': 140, 'd_column': 300, 'e_column': 150, 'f_column': 170, 'g_column': 10, 'h_column': 20, 'i_column': 250,'j_column': 54} 我想画一个饼图,像这样: data = {'a_column': 20, '
data = {'a_column': 20, 'b_column': 130,
'c_column': 140, 'd_column': 300, 'e_column': 150,
'f_column': 170, 'g_column': 10, 'h_column': 20, 'i_column': 250,'j_column': 54}
我想画一个饼图,像这样:
data = {'a_column': 20, 'b_column': 130,
'c_column': 140, 'd_column': 300, 'e_column': 150,
'f_column': 170, 'g_column': 10, 'h_column': 20, 'i_column': 250,'j_column': 54}
我所尝试的:
base_d = sum(list(data.values()))
final_data = {k:m/base_d*100 for k,m in data.items()}
final_data
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(12, 5), subplot_kw=dict(aspect="equal"))
recipe = list(final_data.keys())
data = list(final_data.values())
wedges, texts = ax.pie(data, wedgeprops=dict(width=0.5), startangle=-40)
bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
kw = dict(arrowprops=dict(arrowstyle="-"),
bbox=bbox_props, zorder=0, va="center")
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})
ax.annotate(recipe[i], xy=(x, y), xytext=(1*np.sign(x), 1.4*y),
horizontalalignment=horizontalalignment, **kw)
plt.show()
但这给了我这样的感觉:
data = {'a_column': 20, 'b_column': 130,
'c_column': 140, 'd_column': 300, 'e_column': 150,
'f_column': 170, 'g_column': 10, 'h_column': 20, 'i_column': 250,'j_column': 54}
如何使箭头像预期的图像一样,并删除标签周围的边框?我做了两件事
1.计算添加到标签的百分比2.删除框样式
将numpy导入为np
将matplotlib.pyplot作为plt导入
def组合列名称(列名称、当前值、总和):
百分比=四舍五入(当前值/总和*100,2)
name=“{}{}%.”格式(列名称,百分比)
返回名称
数据={'a_列]:20,'b_列]:130,
“c_列”:140,“d_列”:300,“e_列”:150,
“f_列”:170,“g_列”:10,“h_列”:20,“i_列”:250,“j_列”:54}
base_d=总和(列表(data.values())
final_data={combine_column_names(k,m,base_d):m/base_d*100表示data.items()中的k,m
图,ax=plt.子批次(figsize=(12,5),子批次(aspect=“equal”))
配方=列表(最终数据.keys())
数据=列表(最终数据值())
楔形,text=ax.pie(数据,楔形操作=dict(宽度=0.5),startangle=-40)
kw=dict(arrowprops=dict(arrowstyle=“-”),zorder=0,va=“center”)
对于枚举中的i,p(楔形):
ang=(p.theta2-p.theta1)/2+p、 θ1
y=np.sin(np.deg2rad(ang))
x=np.cos(np.deg2rad(ang))
水平对齐={-1:“右”,1:“左”}[int(np.sign(x))]
connectionstyle=“angle,angleA=0,angleB={}”。格式(ang)
kw[“arrowprops”].update({“connectionstyle”:connectionstyle})
ax.注释(配方[i],xy=(x,y),xytext=(1*np.符号(x),1.4*y),
水平对齐=水平对齐,**千瓦)
plt.show()
第1部分(共3部分)
根据@JohanC的建议,注释掉#bbox=bbox_props
以移除框,将1*np.sign(x)
更改为1.4*np.sign(x)
以沿x更宽地分布标签,计算百分比perc[i]
,并将其添加到ax.annotate(…)
内的标签中。最终图片看起来像(图片下面的代码):
最终代码:
第2部分(共3部分) 若你们有很多数据条目,那个么饼图的默认颜色看起来不太好,它只有10-15种独特的颜色。我决定根据彩虹的颜色制作自己的定制颜色。在我的着色中,即使有100个数据条目,所有颜色都是唯一的。在下面的代码中,着色是在
ax.pie(…colors=..)
内部完成的。我制作了彩虹着色的示例图像和代码:
第3部分(共3部分) 还决定改进非常多条目(大约100条条目)的情况。做了下一步的改进:1)沿着X个奇数和偶数条目分开。2) 沿Y方向均匀放置所有标签(在沿角度均匀放置之前)。3) 使字体变小
省略
bbox=bbox_props
如何省略边界框?和ax.annotate(…,xytext=(1.2*np.符号(x),…),…)
来增加水平距离?
import numpy as np, math, random
import matplotlib.pyplot as plt
np.random.seed(0)
random.seed(0)
data = {f'dat_{str(i).zfill(2)}' : random.random() for i in range(98)}
base_d = sum(list(data.values()))
final_data = {k:m/base_d*100 for k,m in data.items()}
fig, ax = plt.subplots(figsize=(12, 5), subplot_kw=dict(aspect="equal"))
recipe = list(final_data.keys())
data = list(final_data.values())
perc = [str(round(e / s * 100., 2)) + '%' for s in (sum(data),) for e in data]
wedges, texts = ax.pie(data, wedgeprops=dict(width=0.5), startangle=-40, radius = 0.8,
colors = (lambda C = 7: [plt.cm.gist_rainbow((i % C) / C + i // C * 1 / C / math.ceil(len(data) / C)) for i in range(len(data))])())
bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
kw = dict(arrowprops=dict(arrowstyle="-"),
#bbox=bbox_props,
zorder=0, va="center")
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))
yc = np.arcsin(y) / (np.pi / 2)
horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
connectionstyle = f'angle,angleA=0,angleB={ang}'
kw["arrowprops"].update({"connectionstyle": connectionstyle})
ax.annotate(recipe[i] + ' ' + perc[i], xy = (0.8 * x, 0.8 * y), xytext = ((1.0 + (i % 2) * 0.4) * np.sign(x), 1.4 * yc),
horizontalalignment = horizontalalignment, fontsize = 'x-small', **kw)
plt.show()