Python扩展库Matplotlib依赖于扩展库numpy和标准库tkinter,可以绘制多种形式的图形,例如折线图、散点图、饼状图、柱状图、雷达图等,图形质量可以达到出版要求。
Python扩展库,matplotlib 主要包括pylab、pyplot等绘图模块和大量用于字体、颜色、图例等图形元素的管理与控制的模块,提供了类似于MATLAB的绘图接口,支持线条样式、字体属性、轴属性及其他属性的管理和控制,可以使用非常简洁的代码绘制出优美的各种图案。
使用pylab或pyplot绘图的一般过程为:
首先生成或读入数据
根据实际需要绘制二维折线图、散点图、柱状图、饼状图、雷达图或三维曲线、曲面、柱状图等
坐标轴标签(matplotlib.pyplot模块的xlabel()、ylabel()函数或者轴域的**set_xlable()、set_ylable()**的方法)
坐标轴刻度(matplotlib.pyplot模块的xticks()、yticks()函数或者轴域的**set_xticks()、set_yticks()**的方法)
图例(matplotlib.pyplot模块的legend()函数)
标题(matplotlib.pyplot模块的title函数)
4.显示或保存绘图结果
折线图的绘制用matplotlib.pyplot中的函数plot()绘制,通过参数指定折线图上端点的位置、标记符号的形状、大小和颜色以及线条的颜色、线型等样式。
plot( args, kwargs)
参数名称 | 含义 |
---|---|
args | ( 参数1, 参数2, 参数3 ) |
第一个参数用来指定折线图上一个或多个端点的 X坐标
第二个参数用来指定折线图上一个或多个端点的 Y坐标
第三个参数用来同时指定折线图的颜色、线型和标记符号形状(也可以通过关键参数Kwargs指定)
颜色 | ‘r’红色 ,‘g’绿色,‘b’蓝色,‘c’青色,‘m’品红色,‘y’黄色,‘k’黑色,‘w’白色 |
---|---|
线形 | ‘-’实心线,‘–’短划线,‘-.’点划线,‘:’点线 |
标记符号 | ‘.’圆点、‘o’圆圈、‘v’向下的三角形、‘^’向上的三角形、‘<’向左的三角形、‘>’向右的三角形、‘*’五角星、‘+’加号、‘-’减号、‘x’x符号、‘D’菱形 |
例如,plot(x,y,‘g-v’)使用x,y元素作为端点坐标绘制绿色实心线并使用向下的三角形作为标记端点
Kwargs
用来设置标签、线宽、反走样以及标记符号的大小、边线颜色、边线宽度与背景色等属性 |
---|
**alpha:**指定透明度,介于0到1之间,默认为1,表示完全不透明 |
antialiased或aa: True表示图形启用抗锯齿或反走样,False表示不启用,默认为True |
color或c:用来指定线条颜色,取值见上表 |
label:用来指定线条标签,设置之后会显示在图例中 |
linestytle或ls:指定线形 |
linewidth或lw:指定线条宽度 |
marker:指定标记符号的形状 |
markeredgecolor或mec:指定标记符号边线的颜色 |
markeredgewidth或mew:指定标记符号边线的宽度 |
markerfacecolor或mfc:用来指定标记符号的背景颜色 |
markersize或ms:用来指定标记符号的大小 |
visible:指定线条和标记符号是否可见,默认为True |
已知学校附近某烧烤店2019年每月的营业额如表所示,编写程序绘制折线图对该烧烤店全年营业额进行可视化,可使用红色点划线连接每个月的数据,并在每月的数据出使用三角形标记
某烧烤店2019年每个月的营业额 |
---|
月份 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
营业额 | 5.2 | 2.7 | 5.8 | 5.7 | 7.3 | 9.2 | 18.7 | 15.6 | 20.5 | 18.0 | 7.8 | 6.9 |
import matplotlib.pyplot as plt
#月份和每月营业额
month = list(range(1,13))
money = [5.2,2.7,5.8,5.7,7.3,9.2,18.7,15.6,20.5,18.0,7.8,6.9]
plt.plot(month,money,'r-.v')
plt.xlabel('月份',fontproperties='simhei',fontsize=14)
plt.ylabel('营业额(万元)',fontproperties='simhei',fontsize=14)
plt.title('烧烤店2019年营业额变化趋势',fontproperties='simhei',fontsize=18)
#紧缩四周空白,扩大绘图区域可用的面积
#plt.tight_layout()
plt.show()
结果如图所示:
散点图比较适合描述数据在平面或空间中的分布,可以用来帮助分析数据之间的关联。
scatter(x,y,s=None,c=None,marker=None,cmap=None,norm=None,vmin=None,vmax=None,alpha=None,
linewidths=None,verts=None,edgecolors=None,hold=None,data=None, kwargs)
参数名称 | 含义 |
---|---|
x,y | 分别用来指定散点的x,y坐标,可以为标量或数组形式的数据。 |
s | 指定散点符号的大小 |
marker | 指定散点符号的形状 |
alpha | 指定散点符号的透明度 |
linewidths | 指定线宽,可以是标量或类似于数组的对象 |
edgecolors | 指定散点符号的边线颜色,可以是颜色值或包含若干颜色的序列 |
结合折线图和散点图,重新绘制烧烤摊折线图的图形。使用plot()函数依次连接若干端点绘制折线图,使用scatter()函数在指定的端点处绘制散点图,结合这两个函数,可以重新得到折线图的结果图,但是为了区分,此次将端点符号设置为蓝色三角形。
某烧烤店2019年每个月的营业额 |
---|
月份 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
营业额 | 5.2 | 2.7 | 5.8 | 5.7 | 7.3 | 9.2 | 18.7 | 15.6 | 20.5 | 18.0 | 7.8 | 6.9 |
import matplotlib.pyplot as plt
#月份和每月的营业额
month = list(range(1,13))
money = [5.2,2.7,5.8,5.7,7.3,9.2,18.7,15.6,20.5,18.0,7.8,6.9]
#绘制折线图,设置颜色和线型
plt.plot(month,money,'r-.')
#绘制散点图,设置颜色、符号和大小
plt.scatter(month,money,c='b',marker='v',s=28)
plt.xlabel('月份',fontproperties='simhei',fontsize=14)
plt.ylabel('营业额(万元)',fontproperties='simhei',fontsize=14)
plt.title('烧烤店2019年营业额变化趋势',fontproperties='simhei',fontsize=14)
plt.show()
某商场安排工作人员在不同位置对手机信号强度进行测试以便进一步提高商场信号,测试数据保存于文件“D:\服务质量保证\商场一楼手机信号强度.txt”中,文件中每行使用逗号分隔的3个数字分别表示商场内一个位置的x,y坐标和信号强度,其中x,y坐标值以商场西南角为坐标原点且向东为x正轴(共150米)、向北为y正轴(共30米),信号强度以0表示无信号,100表示最强
打开文件读取数据:
with open(r'D:\服务质量保证\商场一楼手机信号强度.txt') as fp:
bar(left,height,width=0.8,bottom=None,hold=None,data=None, kwargs)
参数名称 | 含义 |
---|---|
left | 指定每个柱的左侧边框的x坐标 |
height | 指定每个柱的高度 |
bottom | 指定每个柱底部边框的y坐标 |
width | 指定每个柱的宽度,默认为0.8 |
color | 指定每个柱的颜色 |
edgecolor | 指定每个柱的边框的颜色 |
linewidth | 指定每个柱的边框的线宽 |
align | 每个柱的对齐方式 |
orientation | 指定柱的朝向,‘vertical’时为垂直柱状图,‘horizontal’时绘制水平柱状图 |
alpha | 指定透明度 |
hatch | 指定内部填充符号,可选的值有:‘/’、"\\"、“|”、“-”、“+”、“x”、“o”、“O”、“.”、“*” |
label | 指定图例中显示的文本标签 |
fill | 设置是否填充 |
某商场几个部门2019年每个月的业绩如下图,编写程序绘制柱状图可视化各部门的业绩,可以借助于pandas的DataFrame结构快速绘制图形,并要求坐标轴、标题和图例能够显示中文。
某商场各部门业绩 |
---|
月份 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
男装 | 51 | 32 | 58 | 57 | 30 | 46 | 38 | 38 | 40 | 53 | 58 | 50 |
女装 | 70 | 30 | 48 | 73 | 82 | 80 | 43 | 25 | 30 | 49 | 79 | 60 |
餐饮 | 60 | 40 | 46 | 50 | 57 | 76 | 70 | 33 | 70 | 61 | 49 | 45 |
化妆品 | 110 | 75 | 130 | 80 | 83 | 95 | 87 | 89 | 96 | 88 | 86 | 89 |
金银首饰 | 143 | 100 | 89 | 90 | 78 | 129 | 100 | 97 | 108 | 152 | 96 | 87 |
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
data = pd.DataFrame({'月份':[1,2,3,4,5,6,7,8,9,10,11,12],
'男装':[51,32,58,57,30,46,38,38,40,53,58,50],
'女装':[70,30,48,73,82,80,43,25,30,49,79,60],
'餐饮':[60,40,46,50,57,76,70,33,70,61,49,45],
'化妆品':[110,75,130,80,83,95,87,89,96,88,86,89],
'金银首饰':[143,100,89,90,78,129,100,97,108,152,96,87]})
#绘制柱状图,指定月份数据作为x轴
data.plot(x='月份',kind='bar')
#设置x、y轴标签和字体
plt.xlabel('月份',fontproperties='simhei')
plt.ylabel('营业额(万元)',fontproperties='simhei')
#设置图例字体
myfont = fm.FontProperties(fname=r'C:\Windows\Fonts\STKAITI.ttf')
plt.legend(prop=myfont)
plt.show()
结果如图:
要求可以设置每个柱的颜色、内部填充符号、描边效果和标注文本
import matplotlib.pyplot as plt
month = list(range(1,13))
money = [5.2,2.7,5.8,5.7,7.3,9.2,18.7,15.6,20.5,18.0,7.8,6.9]
#绘制每个月的营业额
for x,y in zip(month,money):
#营业额越高,颜色中的红色分量越大
#格式字符串中的0表示不够2位时前面补0
color = '#%02x'%int(y*10)+'6666'
plt.bar(x,y,
color=color,hatch='*',width=0.6,
edgecolor='b',linestyle='--',linewidth=1.5)
plt.text(x-0.3,y+0.2,'%.1f'%y)
plt.xlabel('月份',fontproperties='simhei')
plt.ylabel('营业额(万元)',fontproperties='simhei')
plt.title('烧烤店营业额',fontproperties='simhei',fontsize=14)
#设置x轴刻度
plt.xticks(month)
#设置y轴跨度
plt.ylim(0,22)
plt.show()
编柱状图进行展示和对比
闯红灯情况调查情况 |
---|
从不闯红灯 | 跟从别人闯红灯 | 带头闯红灯 | |
---|---|---|---|
男性 | 450 | 800 | 200 |
女性 | 150 | 100 | 300 |
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
#创建DataFrame结构
df = pd.DataFrame({'男性':(450,800,200),
'女性':(150,100,300)})
df.plot(kind='bar')
plt.xticks([0,1,2],
['从不闯红灯','跟从别人闯红灯','带头闯红灯'],
fontproperties='simhei',
rotation=20)
plt.yticks(list(df['男性'].values) + list(df['女性'].values))
plt.ylabel('人数',fontproperties='stkaiti',fontsize=14)
plt.title('过马路的方式',fontproperties='stkaiti',fontsize=14)
font = fm.FontProperties(fname=r'C:\Windows\Fonts\STKAITI.ttf')
plt.legend(prop=font)
plt.show()
结果如图所示:
pie(x,explode=None,labels=None,colors=None,autopct=None,pctdistance=0.6,shadow=False,labeldistance=1.1,startangle=None,radius=None,counterclock=True,wedgeprops=None,textprops=None,center=(0,0),frame=False,hold=None,data=None)
参数名称 | 含义 |
---|---|
x | 数组形式的数据,自动计算其中每个数据的占比并确定对应的扇形面积 |
explode | 取值可以为None或与x等长的数组,用来指定每个扇形沿半径方向相对于圆形的偏移量,None表示不进行偏移,正数表示远离圆心 |
colors | 可以为None或包含颜色值的序列,用来指定每个扇形的颜色,如果颜色数量少于扇形数量,就循环使用这些颜色 |
labels | 与x等长的字符串序列,指定每个扇形的文本标签 |
autopct | 设置在扇形内部使用数字值作为标签显示时的格式 |
pctdistance | 设置每个扇形的中心与autopct指定的文本之间的距离,默认为0.6 |
labeldistance | 每个饼标签绘制时的径向距离 |
shadow | True/False,用来设置饼状图中每个扇形的绘制方向 |
startangle | 设置每个饼状图第一个扇形的起始角度,相对于x轴并沿逆时针方向计算 |
radius | 设置饼的半径,默认为1 |
counterclock | True/False,设置饼状图中每个扇形的绘制方向 |
center | (x,y)形式的元组,设置饼的圆心位置 |
frame | True/False,设置是否显示边框 |
已知某班级的数据结构、线性数代、英语和Python课程考试成绩,要求绘制饼状图显示每门课的成绩中 优(85分以上),及格(60~84),不及格(60分以下)的占比
from itertools import groupby
import matplotlib.pyplot as plt
#设置图形中使用的字体
plt.rcParams['font.sans-serif'] = ['simhei']
#每门课的成绩
scores = {'数据结构':[89,70,49,87,92,84,73,71,78,81,90,37,
77,82,81,79,80,82,75,90,54,80,70,68,61],
'线性数代':[70,74,80,60,50,87,68,77,95,80,79,74,
69,64,82,81,78,90,78,79,72,69,45,70,70],
'英语':[83,87,69,55,80,89,96,81,83,90,54,70,79,
66,85,82,88,76,60,80,75,83,75,70,20],
'Python':[90,60,82,79,88,92,85,87,89,71,45,50,
80,81,87,93,80,70,68,65,85,89,80,72,75]}
#自定义分组函数,在下面groupby()函数中使用
def splitScore(score):
if score>=85:
return '优'
elif score>=60:
return '及格'
else:
return '不及格'
#统计每门课程中优、及格、不及格的人数
ratios = dict()
for subject,subjectScore in scores.items():
ratios[subject] = {}
for category, num in groupby(sorted(subjectScore),splitScore):
ratios[subject][category] = len(tuple(num))
#创建4个子图
fig, axs = plt.subplots(2,2)
axs.shape = 4,
#依次在4个子图中绘制每门课程的饼状图
for index, subjectData in enumerate(ratios.items()):
#选择子图
plt.sca(axs[index])
subjectName, subjectRatio = subjectData
plt.pie(list(subjectRatio.values()),
labels=list(subjectRatio.keys()),
autopct='%1.1f%%')
plt.xlabel(subjectName)
plt.legend()
plt.gca().set_aspect('equal')
plt.show()
结果如图所示:
import matplotlib.pyplot as plt
#设置图形中使用的字体
plt.rcParams['font.sans-serif']='simhei'
#将画布设定为正方形,则绘制的饼图是正圆
plt.figure(figsize=(6,6))
#定义饼图的标签,标签是列表
label=['第一','第二','第三']
#设定各项距离圆心n个半径
explode=[0.01,0.01,0.01]
values=[4,7,9]
plt.pie(values,explode=explode,labels=labels,autopct='%1.1f%%')
plt.title('2018年饼图')
plt.show()
polar(args,kwargs)
其中polar()函数的中args与kwargs参数的含义与plot()函数相似
根据某学生的部分专业核心和成绩清单绘制雷达图
import numpy as np
import matplotlib.pyplot as plt
course = ['C++','Python','高数','大学英语','软件工程',
'组成原理','数字图像处理','计算机图形学']
scores = [80,95,78,85,45,65,80,60]
dataLength = len(scores)
angles = np.linspace(0,
2*np.pi,
dataLength,
endpoint=False)
scores.append(scores[0])
angles = np.append(angles,angles[0])
#绘制雷达图
plt.polar(angles,
scores,
'rv--',
linewidth=2)
#设置角度网格标签
plt.thetagrids(angles*180/np.pi,
courses,
fontproperties='simhei')
#填充雷达图内部
plt.fill(angles,
scores,
facecolor='r',
alpha=0.6)
plt.show()
为了分析家庭开销的详细情况,也为了更好地进行家庭理财,张三对2018年每个月的蔬菜、水果、肉类、日用品、旅游、随礼等各项指出做了详细记录。
import random
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
data = {
'蔬菜':[1350,1500,1330,1550,900,1400,980,1100,1370,1250,1000,1100],
'水果':[400,600,580,620,700,650,860,900,880,900,600,600],
'肉类':[480,700,370,440,500,400,360,380,480,600,600,400],
'日用':[1100,1400,1040,1300,1200,1300,1000,1200,950,1000,900,950],
'衣服':[650,3500,0,300,300,3000,1400,500,800,2000,0,0],
'旅游':[4000,1800,0,0,0,0,0,4000,0,0,0,0],
'随礼':[0,4000,0,600,0,1000,600,1800,800,0,0,1000]
}
dataLength = len(data['蔬菜'])
angles = np.linspace(0,
2*np.pi,
dataLength,
endpoint=False)
markers = '*v^Do'
for col in data.keys():
color = '#'+''.join(map('{0:02x}'.format,
np.random.randint(0,255,3)))
plt.polar(angles,data[col],color=color,
marker=random.choice(markers),label=col)
plt.thetagrids(angles*180/np.pi,
list(map(lambda i:'%d月'%i,range(1,13))),
fontproperties='simhei')
font = fm.FontProperties(fname=r'C:\Windows\Fonts\STKAITI.ttf')
plt.legend(prop=font)
plt.show()
结果如图所示: