人工智能
- python,大数据,机器学习,深度学习,计算机视觉
-
五、机器学习数据科学包(numpy、pandas、matpotlib)篇(五)matplotlib图表常用功能
python,大数据,机器学习,深度学习,计算机视觉
五、机器学习数据科学包(numpy、pandas、matpotlib)篇(五)matplotlib图表常用功能
注释:plt.annotate()
为了说明图中的某一点或某一处,在图中用箭头指向并加上注释文字。
例1
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-10, 11, 1)
y = x*x
plt.plot(x, y)
# 添加注释:annotate('注释文字', xy=(箭头位置), xytext=(注释文本位置), 注释形状arrowprops=箭头dict(facecolor='箭头颜色', frac='箭头占箭头+箭尾的比例',width=箭尾宽度, headwidth='箭头宽度', shrink='箭头箭尾外部的空白大小'(默认0)))
plt.annotate('this is the bottom', xy=(0, 1), xytext=(0, 20), arrowprops=dict(facecolor='red', width=5))
plt.show()
运行结果:
美化一下注释位置(放在中间):
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-10, 11, 1)
y = x*x
plt.plot(x, y)
plt.annotate('this is the bottom', xy=(0, 1), xytext=(-2.6, 20), arrowprops=dict(facecolor='red', width=5))
plt.show()
运行结果:
例2
import numpy as np
import matplotlib.pyplot as plt
plt.plot([3,1,5,4,2])
## 以下4行:有汉字的,若没有进行中文字体全局设置,需要各自都加上参数 fontproperties='SimHei'
#
plt.xlabel(r'X \axis') #字符串前加r显示原始字符串
plt.ylabel('纵轴值',color='blue',fontsize='24')
# 临时设置中文字体法:plt.ylabel('纵轴值',fontproperties='SimHei',color='blue',fontsize='24')
plt.title('图表标题 $a^{2}+b^{2}=c^{2}$') #可以使用$引入一部分latex文本排版语法和公式
# 临时设置中文字体法:plt.title('图表标题 $a^{2}+b^{2}=c^{2}$',fontproperties='SimHei')
plt.text(0.5,3,'任意位置文本',fontsize='24',rotation=45) #任意文本的x,y坐标值(可用latex语法):x=0.5,y=3,旋转角度rotation=45度
# 临时设置中文字体法:plt.text(0.5,3,'任意位置文本',fontproperties='SimHei',fontsize='24',rotation=45)
# 添加注释annotate()
plt.annotate(
'这里转折', #显示字符串
fontproperties='SimHei', # 中文字体
xy=(3,4), # 箭头位置
xytext=(3.5,4.5), # 文本位置
arrowprops=dict(facecolor='red',shrink=0.1,width=2) # facecolor:箭头颜色;shrink:箭头的起始和结束位置两侧的空白大小;width:箭尾宽度
)
plt.show()
运行结果:
文字:plt.text()
图中添加纯文字,也可以看成注释,但没有箭头
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-10, 11, 1)
y = x*x
plt.plot(x, y)
# 添加文字:text(文字起始位置x,y,'文字内容', family='字体型', color='字体颜色', size=字体大小, weight=粗体大小, style='字体形式形状 如italic斜体', 文本框bbox=dict(facecolor='颜色', alpha=颜色透明度))
plt.text(-2.5, 20, '二次函数: y=x*x', family='SimHei', color='r', size=10, bbox=dict(facecolor='y', alpha=0.5)) # 调整字体 family='SimHei' 或 fontproperties='SimHei'
plt.text(-2.5, 40, '二次函数: y=x*x', family='SimHei', color='g', size=15)
plt.show()
运行结果:
附:透明度参数 alpha即古希腊文
α
\alpha
α
Tex公式:plt.text()
在图中画出数学公式
1.概念:
- matplotlib自带mathtext引擎,不需安装Tex系统
- 以 $ 作为开始和结束符,如 “$ y=x+z $”
2.例子:
同样有plt直接法 和 figure对象法。下面以figure对象法为例。
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
# 设置画布的x,y轴的上下限
ax.set_xlim([1,7])
ax.set_ylim([1,5])
## 添加Tex公式:text(x,y, r"...", size=字体大小)
# 统一标准:数学专有字母、专有函数sin等前要有 转义\ 以便再$...$之间识别。
# 函数参数要用 大括号{}括起来,不用小括号
ax.text(2, 5, r"$ \alpha \beta \pi \omega $") # 下标(2,5)的位置
ax.text(2, 4, r"$ \alpha_i \beta_j \pi \omega $", size=20) # r表字符串内不转义
ax.text(4, 4, r"$ \sin(0)=\cos(\frac{\pi}{2}) $", size=20) # frac{分子}{分母}
ax.text(2, 2, r"$ \lim_{x \rightarrow y} \frac{1}{x^3} $", size=20)
ax.text(4, 2, r"$ \sqrt[4]{x}=\sqrt{y} $", size=20) # 默认 \sqrt[2]{y}即\sqrt{y},默认开2次方。
plt.show()
运行结果:
注:更多详细的字母表达式等 可以看matplotlib的官方文档:https://matplotlib.org/tutorials/text/mathtext.html
附:上面语法类似如csdn的markdown
工具栏
matplotlib显示的图上面有工具栏,有很多实用的功能,如图聚焦放大,调节参数。
下面举例
import numpy as np
import matplotlib.pyplot as plt
N = 1000
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radiuses
plt.scatter(x, y, s=area, c=colors, alpha=0.5)
plt.show()
运行结果:
如上图红圈位置,如选中扩大镜,再到图中圈中要放大的部分,即可放大。
区域填充颜色:plt.fill() 和 plt.fill_between()
如同office办公软件的填充喷色功能,fill
1. 普通填充 fill()
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 5*np.pi, 1000)
y1 = np.sin(x)
y2 = np.sin(2*x)
## 省略显示点线的功能,以便下面填充结果更清晰。
# plt.plot(x, y1)
# plt.plot(x, y2)
## 填充颜色:fill(x, y, '颜色', alpha=透明度大小)
# 直接用fill即可显示图,不需要plt.plot显示点线
plt.fill(x, y1, 'b', alpha=0.3)
plt.fill(x, y2, 'r', alpha=0.3)
plt.show()
2. 在两线间填充颜色 fill_between():
法1:plt直接法
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 5*np.pi, 1000)
y1 = np.sin(x)
y2 = np.sin(2*x)
plt.plot(x, y1, color='r')
plt.plot(x, y2, color='b')
# 在两线间填充颜色:当y1>y2时的区域填充黄色。interpolate=True是将两线直接的空白区域自动补上颜色以美观,空白区域是因为我们生生成的点是离散的点,是离散点数量多导致视觉上近似于连续
plt.fill_between(x, y1, y2, where=y1>y2, facecolor='y', interpolate=True)
# 在两线间填充颜色,当y2>y1时的区域填充绿色
plt.fill_between(x, y1, y2, where=y2>y1, facecolor='g', interpolate=True)
plt.show()
运行结果:
法2:对象法
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 5*np.pi, 1000)
y1 = np.sin(x)
y2 = np.sin(2*x)
fig = plt.figure()
ax = plt.gca() # 获取坐标轴
ax.plot(x, y1, color='r')
ax.plot(x, y2, color='b')
ax.fill_between(x, y1, y2, where=y1>y2, facecolor='y', interpolate=True)
ax.fill_between(x, y1, y2, where=y2>y1, facecolor='g', interpolate=True)
plt.show()
运行结果同上。
形状:mpatches.Circle()、mpatches.Rectangle()、mpatches.RegularPolygon() 和 mpatches.Ellipse() 等
如何在matplotlib图上画出圆、矩形等各种形状的图形呢?
1. 概念:
- 生成形状 patches
- import matplotlib.patches as mpatches
- add_patch
2. 例子:
例1. 画圆
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
fig, ax = plt.subplots()
## 画圆:
xy1 = np.array([0.2, 0.2]) # 圆心
# 圆心为xy1、半径为0.05的圆
circle = mpatches.Circle(xy1, 0.05) # 等价 circle = mpatches.Circle(xy=xy1, radius=0.05)
# 将上面的circle添加到patch ---- 在图中显示出来
ax.add_patch(circle)
# 调整x,y轴的比例为1:1,否则视觉上看到的是椭圆而不是圆了
plt.axis('equal')
# 添加网格
plt.grid()
plt.show()
运行结果:
例2. 画:圆、矩形、多边形、椭圆
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
fig, ax = plt.subplots()
xy1 = np.array([0.2, 0.2]) # 圆心
xy2 = np.array([0.2, 0.8]) # 长方形的左下角的点(特殊)
xy3 = np.array([0.8, 0.2]) # 多边形中心
xy4 = np.array([0.8, 0.8]) # 椭圆中心
# 圆:圆心为xy1=(0.2, 0.2)、半径=0.05
circle = mpatches.Circle(xy1, 0.05) # 等价 circle = mpatches.Circle(xy=xy1, radius=0.05)
ax.add_patch(circle)
# 长方形:以xy2=(0.2, 0.8)为矩形左下角起点,横向x轴矩形长=0.2,纵向y轴矩形宽=0.1
rect = mpatches.Rectangle(xy2, 0.2, 0.1, color='r')
ax.add_patch(rect)
# 多边形:多边形中心xy3=(0.8, 0.2),多边形的边数=5(即五边形),多边形半径=0.1
polygon = mpatches.RegularPolygon(xy3, 5, 0.1, color='g')
ax.add_patch(polygon)
#
# polygon = mpatches.RegularPolygon(xy3, 6, 0.1, color='g') # 六边形
# ax.add_patch(polygon)
#
# polygon = mpatches.RegularPolygon(xy3, 1000, 0.1, color='g') # 1000边形,近似于圆
# ax.add_patch(polygon)
# 椭圆:椭圆中心xy4=(0.8, 0.8),横向x轴直径=0.4,纵向y轴直径=0.2
ellipse = mpatches.Ellipse(xy4, 0.4, 0.2, color='y') # 横向长直径0.4,纵向短直径0.2
ax.add_patch(ellipse)
# 调整x,y轴的比例为1:1,否则视觉上看到的是椭圆而不是圆了
plt.axis('equal')
# 添加网格
plt.grid()
plt.show()
运行结果:
美化
对matplotlib生成的图形进行美化,使视觉上效果更好。可以使用自带样式进行美化
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot') # 可以通过 print(plt.style.available)来查看
# 生成子图两种方式:
# 法1. fig = plt.figure()
# fig.add_subplot(221)
# 法2. plt.subplots(2,2) # 注意是subplots不是subplot
# 下面用法2
fig, axes = plt.subplots(nrows=2, ncols=2) # 生成2行2列的子图
ax1, ax2, ax3, ax4 = axes.ravel()
# 散点
x, y = np.random.normal(size=(2, 100))
ax1.plot(x, y, 'o')
# 直线:当多条直线时,颜色依次渐变
x = np.arange(0, 10)
y = np.arange(0, 10)
shift = np.linspace(0, 10, 7) # 0~10均分成7份。 # 以便看出7种颜色的线
for s in shift:
ax2.plot(x, y+s, '-')
# 柱状图:颜色不是依次渐变,需手动指定颜色
x = np.arange(5)
y1, y2, y3 = np.random.randint(1, 25, size=(3, 5))
width = 0.25
ax3.bar(x, y1, width)
ax3.bar(x+width, y2, width, color='r')
ax3.bar(x+2*width, y2, width, color='g')
# 画圆形图案
for i, color in enumerate(['b','g','r','c','m','y','k','w']):
xy = np.random.normal(size=2)
ax4.add_patch(plt.Circle(xy, radius=0.3, color=color))
ax4.axis('equal')
plt.show()
极坐标
极坐标是高中知识:用角度和半径表示的极坐标。
下面在matplotlib生成极坐标系,用的是子图方法,代码与直角坐标系类似,区别是在生成子图的同时就投影成极坐标系。
例1.
import numpy as np
import matplotlib.pyplot as plt
r = np.arange(1, 6, 1) # 半径[1 2 3 4 5]
theta = [0, np.pi/2, np.pi, 3/2*np.pi, 2*np.pi] # 角度[0, np.pi/2, np.pi, 3/2*np.pi, 2*np.pi]
# 生成子图的同时就投影成 polar极坐标体系的(若不设置则默认是直角坐标系的)
ax = plt.subplot(111, projection='polar')
ax.plot(theta, r) # 还可以设置下参数 ax.plot(theta, r, color='r', linewidth=3)
# ax.grid(True) 开启网格
# 开启网格的同时设置网格线为虚线,默认实线
ax.grid(linestyle='--')
plt.show()
运行结果:
同样可以设置一下颜色、线宽度等参数:
import numpy as np
import matplotlib.pyplot as plt
r = np.arange(1, 6, 1)
theta = [0, np.pi/2, np.pi, 3/2*np.pi, 2*np.pi]
# 生成子图的同时就投影成 polar极坐标体系的(若不设置则默认是直角坐标系的)
ax = plt.subplot(111, projection='polar')
ax.plot(theta, r, color='r', linewidth=3)
ax.grid(linestyle='--')
plt.show()
运行结果:
例2. 用极坐标系画出正方形
import numpy as np
import matplotlib.pyplot as plt
r = np.empty(5) # [0. 0.25 0.5 0.75 1. ]
r.fill(5) # 将列表元素全部替换为5。 print(r) # 结果:[5. 5. 5. 5. 5.]
theta = [0, np.pi/2, np.pi, 3/2*np.pi, 2*np.pi] # 角度[0, np.pi/2, np.pi, 3/2*np.pi, 2*np.pi]
# 生成子图的同时就投影成 polar极坐标体系的(若不设置则默认是直角坐标系的)
ax = plt.subplot(111, projection='polar')
ax.plot(theta, r, color='r', linewidth=3)
# 开启网格的同时设置网格线为虚线,默认实线
ax.grid(linestyle='--')
plt.show()
运行结果:
上面是正方形,要想视觉上观察的效果更好,可以修改代码用ax.grid(False)
关闭网格。
函数积分
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon # 求积分用
def func(x):
return -(x-2)*(x-8)+40
x = np.linspace(0, 10)
y = func(x)
fig, ax = plt.subplots()
plt.plot(x, y, 'r', linewidth=2)
### 下面设置属性:
a = 2
b = 9
# x轴下标刻度全替换成a,b的值
ax.set_xticks([a, b])
# y轴下标刻度全不显示
ax.set_yticks([])
# x轴下标刻度全替换成a,b变量。上面是显示a,b的值,这里显示a,b“变量”
ax.set_xticklabels(['$a$', '$b$']) # 加上$使字体像数学体美观。 ax.set_xticklabels(['a', 'b'])
ix = np.linspace(a, b) # a~b,准备积分
iy = func(ix)
# zip() 将x,y拼接在一起
ixy = zip(ix, iy)
verts = [(a, 0)] + list(ixy) + [(b, 0)]
# 画出积分阴影部分。
poly = Polygon(verts, facecolor='0.9', edgecolor='0.5') # 阴影部分灰度0.9,边缘灰度0.5
# 添加到patch使之生效
ax.add_patch(poly)
# 加上 x, y名字
plt.figtext(0.9, 0.05, '$x$')
plt.figtext(0.1, 0.9, '$y$')
x_math = (a+b)*0.5
y_math = 35
plt.text(x_math, y_math, r'$\int_a^b (-(x-2)*(x-8)+40)dx$', fontsize=12, horizontalalignment='center') # horizontalalignment='center' 表自适应放到中间
plt.ylim(ymin=25)
plt.show()
散点-条形图
例:写代码,用matplotlib画出下图。
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
x = np.random.randn(200)
y = x + np.random.randn(200)*0.5
margin_border = 0.1
width = 0.5
margin_between = 0.02
height = 0.2
# 左下角的散点图
left_s = margin_border
bottom_s = margin_border
height_s = width
width_s = width
# 左上角的条形图
left_x = margin_border
bottom_x = margin_border + width + margin_between
height_x = height
width_x = width
# 右下角的横向条形图
left_y = margin_border + width + margin_between
bottom_y = margin_border
height_y = width
width_y = height
plt.figure(1, figsize=(8, 8))
rect_s = [left_s, bottom_s, width_s, height_s] # 左下角的散点图
rect_x = [left_x, bottom_x, width_x, height_x] # 左上角的条形图
rect_y = [left_y, bottom_y, width_y, height_y] # 右下角的横向条形图
# 画出左下角的散点图的背影刻度图
axScatter = plt.axes(rect_s)
# 画出左上角的条形图的背影刻度图
axHisX = plt.axes(rect_x)
# 画出右下角的横向条形图的背影刻度图
axHisY = plt.axes(rect_y)
# 隐藏坐标刻度
axHisX.set_xticks([]) # 隐藏 左上角条形图的x轴坐标刻度,因为左下角散点图已显示坐标刻度故避免重合
axHisY.set_yticks([]) # 隐藏 右下角横向条形图的y轴坐标刻度,因为左下角散点图已显示坐标刻度故避免重合
# 画出左下角散点图
axScatter.scatter(x, y)
# 设置属性,调整散点图的显示
bin_width = 0.25 # 固定散点图每个小格的宽度
xymax = np.max([np.max(np.fabs(x)), np.max(np.fabs(y))])
lim = int(xymax/bin_width + 1)*bin_width
axScatter.set_xlim(-lim, lim)
axScatter.set_ylim(-lim, lim)
bins = np.arange(-lim, lim+bin_width, bin_width)
# 画出左上角条形图
axHisX.hist(x, bins=bins)
# 画出右下角横向条形图
axHisY.hist(y, bins=bins, orientation='horizontal') # horizontal水平
# 设置属性,调整条形图的显示
axHisX.set_xlim(axScatter.get_xlim())
axHisY.set_ylim(axScatter.get_ylim())
# 加标题
plt.title('Scatter and Hist')
plt.show()
运行结果: