「Python」matplotlib
引言
常用函数
plot函数
savefig保存
legend()图例
设置坐标轴/标题/画布大小
绘制多条曲线
叠加使用plot
subplot()绘制子图
数组
向量化
向量化处理
1.循环
2.向量化函数`vectorize`
3.用where
4.用例:
图表
1.柱状图(bar)
2.饼图(pie)
3.箱型图
4.散点图
综合示例
引言
matplotlib中pyplot子模块提供了和matlab类似的绘图api,方便用户快速绘制一些可视化图标
引入
# way1: 调用函数是加plt前缀 import matplotlib.pyplot as plt # way2: 引入pyplot的所有函数 from matplotlib.pyplot import * # 引入pylab 设置字体显示中文 from pylab import rcParams rcParams['font.sans-serif'] = ['SimHei'] # 设置字体 plt.rcParams["font.sans-serif"] = "SimHei" plt.rcParams["axes.unicode_minus"] = False
常用函数
matplotlib官方文档
# 用 plot函数绘制折线图 # 用 subplot函数绘制多幅图表 # 用 imshow函数展示图片 # 用 hist函数绘制直方图 # 用 pie绘制饼图 # 用 legend绘制图例
plot函数
dataframe.plot(kind='xxx',title='xx') # kind='bar','line','hist','scatter'[散点图] #单条线: plot([x], y, [fmt], data=None, **kwargs) #多条线一起画 plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs) ''' 参数解释: x,y表示具体坐标点,可以是序列数据或者是标量 [fmt]--可选参数,是一个字符串用于定义图的基本属性。 such as: color(颜色),marker(点型),linestyle(线型) 具体形式为:'[color][marker][line]' fmt接收的是每个属性的单个字母缩写 plot(x, y) # 默认配置 plot(x, y, '.') # 绘制点状标记 plot(x, y, 'bo-') # 绘制蓝色圆点实线 plot(x, y, 'g--') # 绘制绿色虚线
绘制sin函数
# 请绘制sin函数曲线 import matplotlib import matplotlib.pyplot as plt x = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360] y= [0, 0.5, 0.866, 1, 0.866, 0.5, 0, -0.5, -0.866, -1, -0.866, -0.5, 0] plt.plot(x,y,'.') plt.show()
savefig保存
# 请绘制抛物线曲线 import matplotlib.pyplot as plt def f(x): return 3 * x * x + 2 * x + 1 x = range(0, 51, 1) y = [f(e) for e in x] plt.plot(x, y, 'r--') plt.show()
legend()图例
legend() #以默认形式设置图例 legend(labels) #标记已有的绘图 legend(handles, labels) #明确定义图例中的元素 plt.legend(['A simple line']) # 明确定义图例中的元素,即两条线分别绘制图例 line1, = plt.plot([1,2,3], linestyle='--') line2, = plt.plot([3,2,1], linewidth=4) plt.legend([line1,line2],["Line 1","Line 2"])
设置坐标轴/标题/画布大小
- plt.xlim、plt.ylim用于设置横纵坐标轴范围;
- plt.xlabel、plt.ylabel用于设置坐标轴名称;
- plt.xticks、plt.yticks用于设置坐标轴刻度;
- plt.title用于设置图像标题。
- plt.figure()用于设置画布大小
xticks 每隔几个点显示链接
plt.plot(x,y,color='g')
plt.xticks(range(0,365,20))
(一共365个点,每隔20个显示)
matplotlib.pyplot.figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True, FigureClass=<class 'matplotlib.figure.Figure'>, clear=False, **kwargs)[source] ''' 在画图之前首先设置figure对象,使得后面的图形输出在这块规定了大小的画布上。 num:用于返回指定 id 的figure对象,如果此参数没有提供,则一个新的figure对象将被创建。 figsize:用于设置画布的宽高,单位为英尺。 dpi:用于设置分辨率。 facecolor用于设置背景色 edgecolor用于设置边框颜色。 ''' plt.figure(figsize=[8,5]) #在绘图之前设置画布大小,宽为 8 英尺,高为 5 英尺 plt.plot(x, y) #绘制曲线
绘制多条曲线
同一个图中:
叠加使用plot
import matplotlib.pyplot as plt from math import sin, cos, radians x = range(0, 360) y1 = [sin(radians(e)) for e in x] y2 = [cos(radians(e)) for e in x] plt.plot(x, y1, 'b-') plt.plot(x, y2, 'r--') plt.legend(['sin(x)', 'cos(x)'], loc='upper center') plt.xlabel('x') #设置 x 轴文字标记 plt.ylabel('sin/cos') #设置 y 轴文字标记 plt.axis([0, 360, -1.0, 1.0]) #设置坐标范围 plt.show()
在两个坐标系中:
subplot()绘制子图
# 第一种:整个绘图区域被分成 nrows 行和 ncols 列,index 表示第几个图 subplot(nrows, ncols, index, **kwargs) # 第二种:pos 是三位数的整数,其中第一位是行数,第二位是列数,第三位是子图的索引 subplot(pos, **kwargs) # 第三种:添加子图 ax subplot(ax) # 返回(<Figure size 640x480 with 4 Axes>, array([[<AxesSubplot:>, <AxesSubplot:>],[<AxesSubplot:>, <AxesSubplot:>]], dtype=object)) plt.subplots(m,n)
import numpy as np import matplotlib.pyplot as plt x1 = np.linspace(0.0, 5.0) x2 = np.linspace(0.0, 2.0) y1 = np.cos(2 * np.pi * x1) * np.exp(-x1) y2 = np.cos(2 * np.pi * x2) plt.subplot(2, 1, 1) # 开始绘制子图 1 或 subplot(211) 被分为2行一列,接下来是第一幅子图 plt.plot(x1, y1, 'o-') plt.title('A tale of 2 subplots') plt.ylabel('Damped oscillation') plt.subplot(2, 1, 2) # 开始绘制子图 2 或 subplot(212) 第二幅子图 plt.plot(x2, y2, '.-') plt.xlabel('time (s)') plt.ylabel('Undamped') plt.show()
import numpy as np import matplotlib.pyplot as plt nums = np.arange(1, 101) fig, axes = plt.subplots(2, 2) ax1 = axes[0, 0] ax2 = axes[0, 1] ax3 = axes[1, 0] ax4 = axes[1, 1] ax1.plot(nums, nums) ax2.plot(nums, -nums) ax3.plot(nums, nums ** 2) ax4.plot(nums, np.log(nums)) plt.show()
数组
在数学概念里,一个向量是一个 n 元组:
v=(_v_0,…,_vn_−1)
数组可以看做是向量的一般形式,可以有多个维度,
A 是一个二维数组,而向量是一维数组。
数组和列表的主要差别如下:
列表可以包含任意类型的对象,一个数组只能包含同一类型的对象;
当成员是整数、浮点数或复数时,使用数组会更加高效。
Numpy创建数组在[numpy初体验中提到](https://www.yuque.com/docs/share/149c2509-72bb-4b8a-98ff-f077f3bc25c2?# 《Numpy初体验》)
常见的用array创建数组
np.array([1,2,3,4])
其他函数:
ndarray2 = np.zeros((3, 3)) #产生3*3的数值为 0 的二维数组 ndarray3 = np.ones_like(ndarray2) # 按照 ndarray2 的形状创建数值为 1 的 3*3 数组 ndarray4 = np.arange(10) #产生 0-9 共 10 个元素 ndarray5 = np.arange(10, 20, 2) #产生数组 array([10, 12, 14, 16, 18]), 间隔为2 ndarray6 = np.linspace(2.0, 3.0, num=5) # 产生数组 array([ 2. , 2.25, 2.5 , 2.75, 3. ])
numpy中的数组处理函数
向量化
向量化指的是将需要循环才能操作数组的 Python 函数转化为直接操作整个数组的函数。向量化能够使得程序更短、可读性更好,且程序的运行速度更快。
# 抛物线向量化绘制 import numpy as np import matplotlib.pyplot as plt def f(x): result = 3 * x ** 2 + 2 * x + 1 return result x = np.linspace(0, 51, 51) # 区间[0,51] 样本数51 y = f(x) plt.plot(x, y, 'r--') plt.show()
向量化处理
以向量化阶跃函数为例
def H(x):
return (0 if x > 0 else 1)
上述代码只能处理数值型数据,在处理数组时会报错。
所以需要进行向量化处理:
有以下几种方案:
1.循环
def H1(x): r = np.zeros(len(x)) # or r = x.copy() for i in range(len(x)): r[i] = H(x[i]) return r
2.向量化函数vectorize
H2 = np.vectorize(H)
3.用where
def H3(x): return np.where(x < 0, 0.0, 1.0)
4.用例:
tips:
where可以嵌套
import numpy as np import matplotlib.pyplot as plt def f(x): return np.where((x < 0) | (x >= 2), 0, (np.where(x < 1, x, 2 - x))) t = np.linspace(-3, 5, 1000) # 区间[-3,5],样本数为1000 y = f(t) plt.title('Plotting hat func in this plot') plt.plot(t, y, 'b-') # 蓝色实线 plt.show()
图表
1.柱状图(bar)
bar函数绘制柱状图,参数如下:
matplotlib.pyplot.bar(x, height, width=0.8, bottom=None, *, align='center', data=None, **kwargs) ''' x -- x轴标量序列,可以为列表、元组、一维数组 height -- 柱形高度 width -- 柱形宽度 alpha -- 颜色透明度
import numpy as np import matplotlib.pyplot as plt x_data = '2015 2014 2013 2012 2011 2010 2009 2008 2007 2006 \ 2005 2004 2003 2002 2001 2000' # x轴数据 y = '12914 11826 12997 12306.41 12327.28 11406 10608 8378 8667.02 8052.78 6922.52 5744 4196 4336 4588 4751' x_data = x_data.split() y = y.split() x_data.reverse() y.reverse() xlabels = x_data y = [float(e) for e in y] # 将字符转变为float,不然做不了图 idx = range(16) plt.xticks(idx, xlabels, rotation=45) # 横轴标签旋转45° plt.yticks(range(4000, 13500, 1000)) # 坐标刻度[4000,13500] 刻度间隔1000 plt.ylim(4000, 13500) # 坐标轴范围[4000,13500] plt.bar(idx, y, color='#800080') plt.show()
堆积柱状图
用for循环或者列表解决
import matplotlib.pyplot as plt import numpy as np xstring = '2015 2014 2013 2012 2011 \ 2010 2009 2008 2007 2006 \ 2005 2004 2003 2002 2001 2000' # x轴标签 n = 6 ystring = [''] * n # y轴对应的6组数据 ystring[0] = '6793 6324 6237 5790.99 5357.1 5032 4681 3800 3863.9 3366.79 3167.66 2778 2359 2250 2170 2112' ystring[1] = '6473 5933 5850 5429.93 4993.17 4725 4459 3576 3645.18 3119.25 2936.96 2608 2197 2092 2017 1948' ystring[2] = '15157 12965 12591 11460.19 10993.92 10934 9662 7801 7471.25 6584.93 5833.95 5576 4145 4154 4348 4288' ystring[3] = '12914 11826 12997 12306.41 12327.28 11406 10608 8378 8667.02 8052.78 6922.52 5744 4196 4336 4588 4751' ystring[4] = '9566 9817 9777 9020.91 8488.21 7747 6871 5886 5773.83 5246.62 5021.75 3884 3675.14 3488.57 3273.53 3260.38' ystring[5] = '4845 5177 4907 4305.73 4182.11 4099 3671 3219 3351.44 3131.31 2829.35 2235 2240.74 1918.83 2033.08 1864.37' labels = ['Commercial housing', 'Residential commercial housing', 'high-end apartments', 'Office Building', 'Business housing', 'Others'] # 图例标签 colors = ['#ff7f50', '#87cefa', '#DA70D6', '#32CD32', '#6495ED', '#FF69B4'] # 指定颜色 bar_width = 0.8 x = xstring.split() x.reverse() xlabels = x idx = np.arange(1, n * len(x), n) for i in range(n): y = ystring[i].split() y.reverse() y = [float(e) for e in y] plt.bar(idx + i * bar_width, y, width=bar_width, color=colors[i]) plt.xticks(idx + bar_width * 2.5, xlabels, rotation=45) # idx + w*2.5 让每一年的数据居中对齐 plt.yticks(range(2000, 15000, 2000)) plt.xlim(-1, 98) plt.ylim(1450, 15300) plt.legend(labels, loc='upper left') # loc属性:调整图例位置 这里为左上方 plt.title('Selling Prices of Six Types of Housing') plt.show()
2.饼图(pie)
matplotlib.pyplot.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, rotatelabels=False, *, data=None)[source] ''' 饼图是逆时针绘制的,参数x表示绘制的序列数据,explode用于突出某个楔形(切片),具体值为偏移圆中心的占比,labels是一个字符串序列,用于给每个楔形打标签,colors用于指定楔形的颜色,autopct参数表示用数值标记楔形,可指定显示方式且标记在内部。
import matplotlib.pyplot as plt labels = ['Frogs', 'Hogs', 'Dogs', 'Logs'] # 标签列表 sizes = [15, 30, 45, 10] # 绘制数据 explode = (0, 0.1, 0, 0) # 只突出第二个切块,偏移比例为0.1 (i.e. 'Hogs') plt.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True, startangle=90) # shadow表示添加阴影,startangle表示旋转角度 autopct 饼图显示数字 plt.axis('equal') # 用于显示为一个长宽相等的饼图 plt.show() #展示图像
figure()设置画布大小
matplotlib.pyplot.figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True, FigureClass=<class 'matplotlib.figure.Figure'>, clear=False, **kwargs)[source] plt.figure(figsize=[14,5]) # 绘制之前设置 ''' 参数num用于返回指定 id 的figure对象,如果此参数没有提供,则一个新的figure对象将被创建。参数figsize用于设置画布的宽高,单位为英尺。参数dpi用于设置分辨率。参数facecolor用于设置背景色,edgecolor用于设置边框颜色。
3.箱型图
plt.boxplot(x, notch=None, sym=None, vert=None, whis=None, positions=None, widths=None, patch_artist=None, meanline=None, showmeans=None, showcaps=None, showbox=None, showfliers=None, boxprops=None, labels=None, flierprops=None, medianprops=None, meanprops=None, capprops=None, whiskerprops=None) ''' x:指定要绘制箱线图的数据; notch:是否是凹口的形式展现箱线图,默认非凹口; sym:指定异常点的形状,默认为+号显示; vert:是否需要将箱线图垂直摆放,默认垂直摆放; whis:指定上下须与上下四分位的距离,默认为1.5倍的四分位差; positions:指定箱线图的位置,默认为[0,1,2…]; widths:指定箱线图的宽度,默认为0.5; patch_artist:是否填充箱体的颜色; meanline:是否用线的形式表示均值,默认用点来表示; showmeans:是否显示均值,默认不显示; showcaps:是否显示箱线图顶端和末端的两条线,默认显示; showbox:是否显示箱线图的箱体,默认显示; showfliers:是否显示异常值,默认显示; boxprops:设置箱体的属性,如边框色,填充色等; labels:为箱线图添加标签,类似于图例的作用; filerprops:设置异常值的属性,如异常点的形状、大小、填充色等; medianprops:设置中位数的属性,如线的类型、粗细等; meanprops:设置均值的属性,如点的大小、颜色等; capprops:设置箱线图顶端和末端线条的属性,如颜色、粗细等; whiskerprops:设置须的属性,如颜色、粗细、线的类型等;
4.散点图
matplotlib.pyplot.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, , data=None, *kwargs) ''' x, y : 相同长度的数组,数组大小(n,),也就是绘制散点图的数据; s:绘制点的大小,可以是实数或大小为(n,)的数组, 可选的参数 ; c:绘制点颜色, 默认是蓝色'b' , 可选的参数 ; marker:表示的是标记的样式,默认的是'o' , 可选的参数 ; cmap:当c是一个浮点数数组的时候才使用, 可选的参数 ; norm:将数据亮度转化到0-1之间,只有c是一个浮点数的数组的时候才使用, 可选的参数 ; vmin , vmax:实数,当norm存在的时候忽略。用来进行亮度数据的归一化 , 可选的参数 ; alpha:实数,0-1之间, 可选的参数 ; linewidths:标记点的长度, 可选的参数 ;
综合示例
import matplotlib.pyplot as plt import numpy as np import pandas as pd plt.rcParams["font.sans-serif"] = "SimHei" plt.rcParams["axes.unicode_minus"] = False df_water = pd.read_csv('2001-2017年北京市水资源情况信息.csv', engine="python") df_water = df_water.T # 转置 df_water.columns = pd.Series([i.replace(" ","") for i in list(df_water.iloc[0,:])]) df_water = df_water.iloc[1:,:] # 出去第一行的文字说明 d = {} for i in list(df_water.columns): d[i]= "float" df_water = df_water.astype(d) #确定画布大小为12*12英寸,分辨率为100 fig = plt.figure(figsize=(12,12),dpi=100) #添加第一幅子图:全年水资源量、地表水资源量、地下水资源量 ax1 = fig.add_subplot(2,2,1) plt.title("全年水资源量折线图") plt.xlabel("年份") plt.ylabel("亿立方米") plt.plot(df_water.index, df_water.iloc[:,0], 'r-') plt.plot(df_water.index, df_water.iloc[:,1], 'g--') plt.plot(df_water.index, df_water.iloc[:,2], 'b:') plt.xticks(range(0,18,2),np.array(df_water.index)[range(0,18,2)],rotation=45) # plt.xticks(range(0,18,2),range(2001, 2018, 2), rotation=45) #x轴刻度为年份,隔2年显示,45度斜显示 plt.yticks([0,5,10,15,20,25,30,35,40]) # plt.yticks(range(0, 41, 5), rotation=45) #y轴刻度为0至40,相隔5 plt.legend(df_water.columns[0:3]) ##添加第二幅子图:人均水资源(单位:立方米/人) ax2 = fig.add_subplot(2,2,2) plt.title("人均水资源量散点图") plt.xlabel("年份") plt.ylabel("立方米/人") plt.scatter(df_water.index, df_water.iloc[:,3],marker='o', c="blue") # 散点图 #绘制点的类型为circle('o'),颜色为蓝色 plt.xticks(range(0,18,2),np.array(df_water.index)[range(0,18,2)],rotation=45) # plt.xticks(range(0, 18, 2), range(2001, 2018, 2), rotation=45) #x轴刻度为年份,隔2年显示,45度斜显示 plt.yticks([i for i in range(100,210,10)]) #列表的推导式 # plt.yticks(range(100, 201, 10)) #y轴刻度为100至200,相隔10 plt.legend(["人均水资源(立方米/人)"]) ##添加第三幅子图:2017年农业用水、工业用水、生活用水、生态环境用水饼图 ax3 = fig.add_subplot(2,2,3) plt.title("2017年用水量饼图") plt.pie(df_water.iloc[-1,10:14],explode=[0.01,0.01,0.01,0.01], labels=list(df_water.columns[10:14]), \ autopct="%1.2f%%") #绘制饼图 #设置饼图中各个饼之间的间距均为0.01,百分比显示格式为小数点后保留2位; ##添加第四幅子图:2001-2017年万元地区生产总值耗水量(立方米) ax3 = fig.add_subplot(2,2,4) plt.title("2001-2017年万元地区生产总值耗水量箱线图") plt.boxplot(df_water.iloc[:,-1], notch=True, labels=["万元地区生产总值耗水量(立方米)"], \ meanline=True) #凹口的形式展现箱线图,用线的形式表示均值 ''' ex = [0.01, 0.01, 0.01, 0.01] plt.pie(df_water.iloc[-1, 10:14], explode=ex, autopct='%1.2f%%',labels=df_water.columns[10:14]) ''' plt.savefig("2001-2017年北京市水资源情况信息0.png")