如何为条形图注释创建可变字体大小
How to create a variable fontsize for bar plot annotations
如何选择条形图条内文本注释的字体大小,条件为:
- 文本将完全覆盖矩形条区域。
请仔细阅读图表和代码,以便更清楚地了解问题。
所以,要求只是:字体大小应该相对于条形图中的条形
代码
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
# Plot styles
mpl.style.use("ggplot")
# data
fruits = pd.Series(index = ["Apples", "Oranges", "Watermelon"], data = [324,518, 258])
# Bar graph for Fruits
# figure
plt.figure(figsize = (7,5))
# bar graph
fruits.plot(kind = "bar", color = ["red", "orange", "green"], alpha = 0.6, width = 0.5, )
# percentage of each fruit type
categories = list(fruits.index)
categories_percent = [100*(value/fruits.sum()) for value in fruits ]
# categories annotations coordinates
ax = plt.gca() # get current axes
rects = ax.patches # rectangles axes of bars in the graph
# annotations
for i in range(len(categories)):
plt.annotate(f"{categories[i]} - {categories_percent[i] : 0.2f}%",
xy = (rects[i].get_x() + rects[i].get_width()/2,
rects[i].get_y() + (ax.get_yticks()[1] - ax.get_yticks()[0])*.2),
fontsize = [20,28,12][i], # Chosen by hit and trial for adjustment
color = "white",
ha = "center",
rotation = 90,
)
plt.ylabel("# Counts", fontsize = 15,)
plt.title("Distribution of Fruits", fontsize = 25, fontname = "Monospace", alpha = .6)
plt.xticks([])
plt.tight_layout(rect=[0, 0, 1, 1])
plt.show()
如何处理这行代码fontsize = [20,28,12][i], # Chosen by hit and trial for adjustment
动态调整栏区的字体大小?
- 使用可调整的
fontsize
更新现有注释
- 从逻辑的角度来看,数字大小的
y
作为高度的比例因子。
- 认为
.get_height
为图形的相对高度。
- 实际高度是 y 比例因子乘以
.get_height
。
- 关于包括宽度,我们可以包括相对宽度,它只是
.get_width
(不是 get_width*x
),但是它只是一个常数,因为它是相对宽度。
- 我们不能包括实际宽度,因为字体会针对 y 轴进行不成比例的调整。
x,y=15,15
plt.figure(figsize = (x,y))
for i in range(len(categories)):
txt="{} - {: 0.2f} %".format(categories[i],categories_percent[i])
plt.annotate(txt,
xy = (rects[i].get_x() + rects[i].get_width()/2,
rects[i].get_y() + (ax.get_yticks()[1] - ax.get_yticks()[0])*.2),
fontsize = (rects[i].get_height())*y*.2/len(txt), # Chosen by hit and trial for adjustment
color = "white",
ha = "center",
rotation = 90,
)
- 整个代码可以写的更干净如下
# data
fruits = pd.Series(index = ["Apples", "Oranges", "Watermelon"], data=[324,518, 258])
# calculate percent
per = fruits.div(fruits.sum()).mul(100).round(2)
# bar graph
y = 5
ax = fruits.plot(kind="bar", color=["red", "orange", "green"], alpha=0.6, width=0.5, figsize=(7, y), rot=0)
labels = [f'{fruit} - {per[fruit]}%' for fruit in fruits.index]
# annotations:
for label, p in zip(labels, ax.patches):
left, bottom, width, height = p.get_bbox().bounds
fs = height * y * 0.18 / len(label)
ax.annotate(label, xy=(left+width/2, bottom+height/2), ha='center', va='center', rotation=90, fontsize=fs)
plt.ylabel("# Counts", fontsize=15,)
plt.title("Distribution of Fruits", fontsize=25, fontname="Monospace", alpha=.6)
plt.xticks([])
plt.tight_layout(rect=[0, 0, 1, 1])
plt.show()
对于 figsize=(15,15):
对于 figsize=(8,8):
对于 figsize=(7,5):
如何选择条形图条内文本注释的字体大小,条件为:
- 文本将完全覆盖矩形条区域。
请仔细阅读图表和代码,以便更清楚地了解问题。
所以,要求只是:字体大小应该相对于条形图中的条形
代码
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
# Plot styles
mpl.style.use("ggplot")
# data
fruits = pd.Series(index = ["Apples", "Oranges", "Watermelon"], data = [324,518, 258])
# Bar graph for Fruits
# figure
plt.figure(figsize = (7,5))
# bar graph
fruits.plot(kind = "bar", color = ["red", "orange", "green"], alpha = 0.6, width = 0.5, )
# percentage of each fruit type
categories = list(fruits.index)
categories_percent = [100*(value/fruits.sum()) for value in fruits ]
# categories annotations coordinates
ax = plt.gca() # get current axes
rects = ax.patches # rectangles axes of bars in the graph
# annotations
for i in range(len(categories)):
plt.annotate(f"{categories[i]} - {categories_percent[i] : 0.2f}%",
xy = (rects[i].get_x() + rects[i].get_width()/2,
rects[i].get_y() + (ax.get_yticks()[1] - ax.get_yticks()[0])*.2),
fontsize = [20,28,12][i], # Chosen by hit and trial for adjustment
color = "white",
ha = "center",
rotation = 90,
)
plt.ylabel("# Counts", fontsize = 15,)
plt.title("Distribution of Fruits", fontsize = 25, fontname = "Monospace", alpha = .6)
plt.xticks([])
plt.tight_layout(rect=[0, 0, 1, 1])
plt.show()
如何处理这行代码fontsize = [20,28,12][i], # Chosen by hit and trial for adjustment
动态调整栏区的字体大小?
- 使用可调整的
fontsize
更新现有注释- 从逻辑的角度来看,数字大小的
y
作为高度的比例因子。 - 认为
.get_height
为图形的相对高度。 - 实际高度是 y 比例因子乘以
.get_height
。 - 关于包括宽度,我们可以包括相对宽度,它只是
.get_width
(不是get_width*x
),但是它只是一个常数,因为它是相对宽度。 - 我们不能包括实际宽度,因为字体会针对 y 轴进行不成比例的调整。
- 从逻辑的角度来看,数字大小的
x,y=15,15
plt.figure(figsize = (x,y))
for i in range(len(categories)):
txt="{} - {: 0.2f} %".format(categories[i],categories_percent[i])
plt.annotate(txt,
xy = (rects[i].get_x() + rects[i].get_width()/2,
rects[i].get_y() + (ax.get_yticks()[1] - ax.get_yticks()[0])*.2),
fontsize = (rects[i].get_height())*y*.2/len(txt), # Chosen by hit and trial for adjustment
color = "white",
ha = "center",
rotation = 90,
)
- 整个代码可以写的更干净如下
# data
fruits = pd.Series(index = ["Apples", "Oranges", "Watermelon"], data=[324,518, 258])
# calculate percent
per = fruits.div(fruits.sum()).mul(100).round(2)
# bar graph
y = 5
ax = fruits.plot(kind="bar", color=["red", "orange", "green"], alpha=0.6, width=0.5, figsize=(7, y), rot=0)
labels = [f'{fruit} - {per[fruit]}%' for fruit in fruits.index]
# annotations:
for label, p in zip(labels, ax.patches):
left, bottom, width, height = p.get_bbox().bounds
fs = height * y * 0.18 / len(label)
ax.annotate(label, xy=(left+width/2, bottom+height/2), ha='center', va='center', rotation=90, fontsize=fs)
plt.ylabel("# Counts", fontsize=15,)
plt.title("Distribution of Fruits", fontsize=25, fontname="Monospace", alpha=.6)
plt.xticks([])
plt.tight_layout(rect=[0, 0, 1, 1])
plt.show()
对于 figsize=(15,15):
对于 figsize=(8,8):
对于 figsize=(7,5):