1、ax.bar()函数
条形图可以垂直或水平绘制。条形图显示离散类别之间的比较。图表的一根轴显示被比较的具体类别,另一根轴代表测量值。Matplotlib中,条形图用以下的函数来画:
ax.bar(x, height, width, bottom, align)
该函数制作了一个大小为(x -width=2;x+width=2;底;底+高)的约束矩形的条形图。
参数解释如下:
参数 | 解释 |
---|---|
x | x是 控制条形图的中心(默认)还是左边缘 |
height | 标量或标量序列代表条形图的高度 |
width | 标量或类数组,可选。条形图的宽度默认为0.8 |
bottom | 标量或类数组,可选。条形图的Y坐标,默认为None |
align | {‘center’, ‘edge’}, 可选,默认’center’ |
tick_label | 条形图的刻度标签。默认值。无 (使用默认的数字标签。) |
更多参数 | 点击官方文档 |
2、绘制单个条形图
以下是Matplotlib条形图的一个简单例子。它显示了一个机构提供的各种课程的注册学生人数:
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
langs = ['数学', '英语', '物理', '化学', '生物']
students = [30,19,45,30,25]
ax.bar(langs,students)
plt.show()
显示结果如下:
3、绘制水平交错的条形图
有时候,我们还要给条形图增加图例,加入一些对比,并且还要给对比的使用不同的颜色,代码示例如下:
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
data = [[30, 25, 50, 20],
[40, 23, 51, 17],
[35, 22, 45, 19]]
# x轴上坐标的个数,也是data列表里面的列表内的元素个数。4也可以用len(data[0])代替。
X = np.arange(4)
fig = plt.figure()
ax = fig.add_axes([0.1,0.1,0.8,0.8])
'''
F1、F2、F3画柱状图,共三个,第一个参数可以认为是labels,第二个参数是各自的y坐标,如果我们想要
在某个柱状图下面设置x轴刻度值,就可以在该柱状图下面用tick_label设置。
'''
F1 = ax.bar(X + 0.00, data[0], color = 'b', width = 0.25)
F2 = ax.bar(X + 0.25, data[1], color = 'g', width = 0.25,tick_label=[2017,2018,2019,2020])
F3 = ax.bar(X + 0.50, data[2], color = 'r', width = 0.25)
# 给柱状图设置图例,第一个参数是个元组,元组中每个元素代表一个柱状图,第二个参数是对应着的图例的名字。
ax.legend((F1,F2,F3),('数学','英语','物理'))
plt.show()
显示结果如下:
上述代码注释有点儿多,请认真阅读。
4、多个条形图堆叠的绘制
代码与3中的大部分都一样,唯一改动的就是ax.bar中的第一个参数,讲水平位移的量给删除,就默认得到了数值方向上的堆叠,代码如下:
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
data = [[30, 25, 50, 20],
[40, 23, 51, 17],
[35, 22, 45, 19]]
X = np.arange(len(data[0]))
fig = plt.figure()
ax = fig.add_axes([0.1,0.1,0.8,0.8])
# 唯一改动的就是ax.bar中的第一个参数。
F1 = ax.bar(X, data[0], color = 'b', width = 0.25)
F2 = ax.bar(X, data[1], color = 'g', width = 0.25,tick_label=[2017,2018,2019,2020])
F3 = ax.bar(X, data[2], color = 'r', width = 0.25)
ax.legend((F1,F2,F3),('数学','英语','物理'))
plt.show()
结果如下:
此外,还可以给柱状图添加一个误差条,如下代码:
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
data = [[30, 25, 50, 20],
[40, 23, 51, 17],
[35, 22, 45, 19]]
F1_std = [2,3,4,1]
F2_std = [3,1,2,1]
F3_std = [3,1,2,1]
X = np.arange(len(data[0]))
fig = plt.figure()
ax = fig.add_axes([0.1,0.1,0.8,0.8])
# 唯一改动的就是ax.bar中的第一个参数。
F1 = ax.bar(X, data[0], color = 'b', width = 0.25,yerr=F1_std)
F2 = ax.bar(X, data[1], color = 'g', width = 0.25,
yerr=F2_std,
tick_label=[2017,2018,2019,2020])
F3 = ax.bar(X, data[2], color = 'r', width = 0.25,yerr=F3_std)
ax.legend((F1,F2,F3),('数学','英语','物理'))
plt.show()
上面的代码还可以写成:
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
data = [[30, 25, 50, 20],
[40, 23, 51, 17],
[35, 22, 45, 19]]
X = ['2017','2018','2019','2020']
F1_std = [2,3,4,1]
F2_std = [3,1,2,1]
F3_std = [3,1,2,1]
fig = plt.figure()
ax = fig.add_axes([0.1,0.1,0.8,0.8])
# 参数X是x坐标轴上的标签值,label是为了显示图例的,是每个柱状图的标签。
ax.bar(X, data[0], color='b', width=0.25, label='数学', yerr=F1_std)
ax.bar(X, data[1], color='g', width=0.25, label='英语', yerr=F2_std)
ax.bar(X, data[2], color='r', width=0.25, label = '物理', yerr=F3_std)
ax.legend()
plt.show()
显示结果如下:
在举一个例子:
import numpy as np
import matplotlib.pyplot as plt
labels = ['G1', 'G2', 'G3', 'G4', 'G5']
men_means = [20, 35, 30, 35, 27]
women_means = [25, 32, 34, 20, 25]
men_std = [2, 3, 4, 1, 2]
women_std = [3, 5, 2, 3, 3]
width = 0.35 # the width of the bars: can also be len(x) sequence
fig, ax = plt.subplots()
# label = 'Men'显示在图例中,labels为x轴的。
ax.bar(labels, men_means, width, yerr=men_std, label='Men')
ax.bar(labels, women_means, width, yerr=women_std, bottom=men_means,
label='Women')
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.legend()
plt.show()
显示结果如下:
注意上述代码中的一些小变动,尤其注意上述代码中ax.bar()函数里面的参数所代表的含义。
5、条形图横向显示
此处放上一个官方的给的例子,涉及的知识点很多,耐心查看理解,直接上代码:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
from collections import namedtuple
np.random.seed(42)
Student = namedtuple('Student', ['name', 'grade', 'gender'])
Score = namedtuple('Score', ['score', 'percentile'])
# GLOBAL CONSTANTS
test_names = ['Pacer Test', 'Flexed Arm\n Hang', 'Mile Run', 'Agility',
'Push Ups']
test_meta = dict(zip(test_names, ['laps', 'sec', 'min:sec', 'sec', '']))
def attach_ordinal(num):
"""Convert an integer to an ordinal string, e.g. 2 -> '2nd'."""
suffixes = {
str(i): v
for i, v in enumerate(['th', 'st', 'nd', 'rd', 'th',
'th', 'th', 'th', 'th', 'th'])}
v = str(num)
# special case early teens
if v in {
'11', '12', '13'}:
return v + 'th'
return v + suffixes[v[-1]]
def format_score(scr, test):
"""
Build up the score labels for the right Y-axis by first
appending a carriage return to each string and then tacking on
the appropriate meta information (i.e., 'laps' vs. 'seconds'). We
want the labels centered on the ticks, so if there is no meta
info (like for pushups) then don't add the carriage return to
the string
"""
md = test_meta[test]
if md:
return '{0}\n{1}'.format(scr, md)
else:
return scr
def format_ycursor(y):
y = int(y)
if y < 0 or y >= len(test_names):
return ''
else:
return test_names[y]
def plot_student_results(student, scores, cohort_size):
# create the figure
fig, ax1 = plt.subplots(figsize=(9, 7))
fig.subplots_adjust(left=0.115, right=0.88)
fig.canvas.set_window_title('Eldorado K-8 Fitness Chart')
pos = np.arange(len(test_names))
rects = ax1.barh(pos, [scores[k].percentile for k in test_names],
align='center',
height=0.5,
tick_label=test_names)
ax1.set_title(student.name)
ax1.set_xlim([0, 100])
ax1.xaxis.set_major_locator(MaxNLocator(11))
ax1.xaxis.grid(True, linestyle='--', which='major',
color='grey', alpha=.25)
# Plot a solid vertical gridline to highlight the median position
ax1.axvline(50, color='grey', alpha=0.25)
# Set the right-hand Y-axis ticks and labels
ax2 = ax1.twinx()
scoreLabels = [format_score(scores[k].score, k) for k in test_names]
# set the tick locations
ax2.set_yticks(pos)
# make sure that the limits are set equally on both yaxis so the
# ticks line up
ax2.set_ylim(ax1.get_ylim())
# set the tick labels
ax2.set_yticklabels(scoreLabels)
ax2.set_ylabel('Test Scores')
xlabel = ('Percentile Ranking Across {grade} Grade {gender}s\n'
'Cohort Size: {cohort_size}')
ax1.set_xlabel(xlabel.format(grade=attach_ordinal(student.grade),
gender=student.gender.title(),
cohort_size=cohort_size))
rect_labels = []
# Lastly, write in the ranking inside each bar to aid in interpretation
for rect in rects:
# Rectangle widths are already integer-valued but are floating
# type, so it helps to remove the trailing decimal point and 0 by
# converting width to int type
width = int(rect.get_width())
rankStr = attach_ordinal(width)
# The bars aren't wide enough to print the ranking inside
if width < 40:
# Shift the text to the right side of the right edge
xloc = 5
# Black against white background
clr = 'black'
align = 'left'
else:
# Shift the text to the left side of the right edge
xloc = -5
# White on magenta
clr = 'white'
align = 'right'
# Center the text vertically in the bar
yloc = rect.get_y() + rect.get_height() / 2
label = ax1.annotate(rankStr, xy=(width, yloc), xytext=(xloc, 0),
textcoords="offset points",
ha=align, va='center',
color=clr, weight='bold', clip_on=True)
rect_labels.append(label)
# make the interactive mouse over give the bar title
ax2.fmt_ydata = format_ycursor
# return all of the artists created
return {
'fig': fig,
'ax': ax1,
'ax_right': ax2,
'bars': rects,
'perc_labels': rect_labels}
student = Student('Johnny Doe', 2, 'boy')
scores = dict(zip(
test_names,
(Score(v, p) for v, p in
zip(['7', '48', '12:52', '17', '14'],
np.round(np.random.uniform(0, 100, len(test_names)), 0)))))
cohort_size = 62 # The number of other 2nd grade boys
arts = plot_student_results(student, scores, cohort_size)
plt.show()
显示的结果如下:
代码详细解读以后在更。