微信公众号:想进化的猿
头条号:python进阶者
在刚开始接触Matplotlib时,按下列步骤写好注释,再着手写代码,会是一个不错的熟练Matplotlib使用的方法。
# 0、导入包
import matplotlib.pyplot as plt
# 1、准备数据
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
# 2、创建图像
fig = plt.figure()
# 3、绘图
ax = fig.add_subplot(111)
ax.plot(x, y)
# 4、自定义设置
ax.set_xlim(1, 5)
# 5、保存图形(按需要使用)
plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
上述例子简单绘制了一条直线,结果如下:
为了美化我们的图形,我们经常会设置图形的各种属性。
图表属性
在第一步的创建图像方法plt.figure()中,我们可以通过传入参数来改变图像的显示属性。查阅官方文档,figure方法的参数包括figsize、dpi、facecolor、edgecolor、linewidth、frameon、subplotpars、tight_layout、constrained_layout。其中 subplotpars、tight_layout这两个参数与子图相关,暂时不详细展开,其他参数的含义如下:
figsize:图像宽高,单位为英寸。(1英寸等于2.5cm)
dpi:图像分辨率,即每英寸多少个像素,默认值80。
facecolor:图像背景颜色。
edgecolor:图像边框颜色。
linewidth:图像边框线宽。
frameon:是否显示边框。
constrained_layout:是否自动布局,若为True则使用constrained_layout,会自动调整plot的位置。
修改plt.figure(),传入相关参数,代码如下:
import matplotlib.pyplot as plt
# 1、准备数据
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
# 2、创建图像
fig = plt.figure(figsize=(3, 3),
dpi=100,
facecolor=(0,1,0,1), # (0,1,0,1)为颜色属性,四个值分别为r,g,b和透明度
edgecolor=(1,0,0,1),
frameon=True,
linewidth=1)
# 3、绘图
ax = fig.add_subplot(111)
ax.plot(x, y)
# 4、自定义设置
ax.set_xlim(1, 5)
# 5、保存图形(按需要使用)
plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行后可以看到如下图表,可以通过调整参数进行尝试熟练各个参数的用法和用途。
坐标属性
在作拥有坐标轴的图表时,我们往往需要对坐标轴进行设置,例如坐标轴的名称、坐标轴的范围、坐标轴的刻度等。下面介绍几种常见的坐标轴设置。
设置坐标轴的名称:plt.xlabel,plt.ylabel分别设置x轴和y轴的标签,这里我们使用ax=fig.add_subplot在figure中分出子图进行操作,故使用ax.set_xlabel,ax.set_ylabel进行设置,后续的属性也都是同一道理。
下面我们给x轴添加标签“x”,给y轴添加标签“y”,代码如下:
# 0、导入包
import matplotlib.pyplot as plt
# 1、准备数据
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
# 2、创建图像
fig = plt.figure(figsize=(3, 3), dpi=100, facecolor=(0,1,0,1),
edgecolor=(1,0,0,1), frameon=True, linewidth=1)
# 3、绘图
ax = fig.add_subplot(111)
ax.plot(x, y)
ax.set_xlabel('x')
ax.set_ylabel('y')
# 4、自定义设置
ax.set_xlim(1, 5)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行后可以看到,坐标轴已经拥有了标签:
设置坐标轴的范围:plt.xlim, plt.ylim分别设置x轴和y轴的大小范围。另外,plt.xticks, plt.yticks虽然用于设置刻度,但其同样可以用来设置坐标轴的范围。
根据x, y的值我们设置x的范围为1-4,y的范围为10-40。两种设置方式分别如下:
# 0、导入包
import matplotlib.pyplot as plt
# 1、准备数据
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
# 2、创建图像
fig = plt.figure(figsize=(8, 3), dpi=100, facecolor=(0,1,0,1),
edgecolor=(1,0,0,1), frameon=True, linewidth=1)
# 3、绘图
ax1 = fig.add_subplot(121)
ax1.plot(x, y)
ax2 = fig.add_subplot(122) # 这里为了比较创建两个子图
ax2.plot(x, y)
# 4、自定义设置
ax1.set_title('lim')
ax2.set_title('ticks')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax1.set_xlim([1, 4]) # 设置边界
ax1.set_ylim([10, 40])
ax2.set_xticks(range(1, 5)) # 设置刻度
ax2.set_yticks([(i*10) for i in range(1, 5)])
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行结果如下,可以看到,使用xlim/ylim设置的时候是严格的范围,而使用xticks/yticks设置的时候边界值上下都会有一定的间隙。
设置坐标轴的刻度:除了上面介绍的xticks/yticks,有时我们会根据需求设置不同的刻度表示形式,例如小数、百分数等等,此时我们使用plt.set_xticklabels/plt.set_yticklabels。假设我们要将上述的横坐标和纵坐标的刻度都用两位小数展示,用法如下:
# 0、导入包
import matplotlib.pyplot as plt
# 1、准备数据
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
# 2、创建图像
fig = plt.figure(figsize=(3, 3), dpi=100, facecolor=(0,1,0,1),
edgecolor=(1,0,0,1), frameon=True, linewidth=1)
# 3、绘图
ax = fig.add_subplot(111)
ax.plot(x, y)
# 4、自定义设置
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_xlim([1, 4]) # 设置边界
ax.set_ylim([10, 40])
ax.set_xticklabels('%.2f' %i for i in range(1, 5)) # 设置刻度表示形式
ax.set_yticklabels('%.21f' %(i*5) for i in range(2, 9))
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行结果如下:
线条属性
在第3步绘图的ax.plot()方法中,我们可以通过传入参数来改变线条的显示属性。常见的有color、 marker、linestyle、linewidth等。
color:线条颜色。常用的有r红, g绿, b蓝, c青, m紫红, y黄, k黑, w白。
marker:坐标点标记。
linestyle:线条形状。如"--","-", '-.'等。
linewidth: 线条宽度。
修改ax.plot(),传入相关参数,代码如下:
# 0、导入包
import matplotlib.pyplot as plt
# 1、准备数据
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
# 2、创建图像
fig = plt.figure(figsize=(3, 3), dpi=100, facecolor=(0,1,0,1),
edgecolor=(1,0,0,1), frameon=True, linewidth=1)
# 3、绘图
ax = fig.add_subplot(111)
ax.plot(x, y, color='y', marker='.', linestyle='--', linewidth=1.5)
# 4、自定义设置
ax.set_xlabel('x')
ax.set_ylabel('y')
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行后可以看到如下图表,可以通过调整参数进行尝试熟练各个参数的用法和用途。
其他属性
legend:图例。可传参数包括handles,labels,loc等。handles是图线序列,labels是要显示的图例标签,loc是图例显示的位置,共有11种可选,传参时用String或Code均可。
给之前的图简单添加一个图例,位置用best,自适应方式。
# 0、导入包
import matplotlib.pyplot as plt
# 1、准备数据
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
# 2、创建图像
fig = plt.figure(figsize=(3, 3), dpi=100, facecolor=(0,1,0,1),
edgecolor=(1,0,0,1), frameon=True, linewidth=1)
# 3、绘图
ax1 = fig.add_subplot(111)
ax1.plot(x, y)
# 4、自定义设置
ax1.set_xlabel('x')
ax1.set_ylabel('y')
# 设置边界
ax1.set_xlim([1, 4])
ax1.set_ylim([10, 40])
# 设置图例
ax1.legend(['legend'], loc=0)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
效果如下。当然,legend还有很多可选参数,在日后的学习工作中遇到了再记录。
grid:给图表添加网格。可传参数包括b, which, axis和其他可选参数。b是否显示网格线,当提供color,linestyle等可选参数时,会默认b为True。which应用网格线,可传'major', 'minor', 'both'分别表示使用主刻度、次刻度、两者。axis应用轴,可传 'x', 'y', 'both'分别表示使用x轴、y轴、两者。可选参数包括color、linestyle、linewidth等。下面添加一个简单的网格线:
# 0、导入包
import matplotlib.pyplot as plt
# 1、准备数据
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
# 2、创建图像
fig = plt.figure(figsize=(3, 3), dpi=100, facecolor=(0,1,0,1),
edgecolor=(1,0,0,1), frameon=True, linewidth=1)
# 3、绘图
ax1 = fig.add_subplot(111)
ax1.plot(x, y)
# 4、自定义设置
ax1.set_xlabel('x')
ax1.set_ylabel('y')
# 设置边界
ax1.set_xlim([1, 4])
ax1.set_ylim([10, 40])
# 设置图例
ax1.legend(['legend'], loc=0)
# 添加网格线(使用主次刻度需要先设置,这里暂时忽略,直接用both)
ax1.grid(True, which='both', axis='both', color='y', linestyle='--', linewidth=1)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
结果如下:
MultipleLocator, FormatStrFormatter:修改主次刻度。主刻度和次刻度就类似于一把直尺上cm与mm的关系。MultipleLocator生成刻度标签,FormatStrFormatter生成刻度标签格式,然后分别用set_major_locator、set_major_formatter、set_minor_locator、set_minor_formatter进行主次刻度的设置。下面对x轴进行主次刻度的设置:
# 0、导入包
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FormatStrFormatter
# 1、准备数据
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
# 2、创建图像
fig = plt.figure(figsize=(3, 3), dpi=100, facecolor=(0,1,0,1),
edgecolor=(1,0,0,1), frameon=True, linewidth=1)
# 3、绘图
ax1 = fig.add_subplot(111)
ax1.plot(x, y)
# 4、自定义设置
ax1.set_xlabel('x')
ax1.set_ylabel('y')
# 设置边界
ax1.set_xlim([1, 4])
ax1.set_ylim([10, 40])
# 设置图例
ax1.legend(['legend'], loc=0)
# 设置主刻度 次刻度
x_major_locator = MultipleLocator(1) #将x轴主刻度标签设置为1的倍数
ax1.xaxis.set_major_locator(x_major_locator)
x_major_formatter = FormatStrFormatter('%.0f') #设置x轴标签文本的格式
ax1.xaxis.set_major_formatter(x_major_formatter)
x_minor_locator = MultipleLocator(0.5) #将x轴次刻度标签设置为0.5的倍数ax.xaxis.set_minor_locator(xminorLocator)
ax1.xaxis.set_minor_locator(x_minor_locator)
# 添加网格线
ax1.grid(True, which='both', axis='both', color='y', linestyle='--', linewidth=1)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
结果如下。可以看到x轴上1.5、2.5、3.5的位置上已经出现了次刻度。
text:在坐标上添加文本,参数有x,y,s,fontdict,withdash。x,y是放置文本的位置。s是要添加的文本。fontdict用于覆盖默认文本属性的字典,例如fontsize等,如果fontdict为none,则默认值由rc参数(matplotlib.rcParams)决定。withdash创建一个TextWithDash实例用于代替Text实例。下面我们在(2, 20)这个位置添加一个文本。
# 0、导入包
import matplotlib.pyplot as plt
# 1、准备数据
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
# 2、创建图像
fig = plt.figure(figsize=(3, 3), dpi=100, facecolor=(0,1,0,1),
edgecolor=(1,0,0,1), frameon=True, linewidth=1)
# 3、绘图
ax1 = fig.add_subplot(111)
ax1.plot(x, y)
# 4、自定义设置
ax1.set_xlabel('x')
ax1.set_ylabel('y')
# 设置边界
ax1.set_xlim([1, 4])
ax1.set_ylim([10, 40])
# 设置图例
ax1.legend(['legend'], loc=0)
# 添加网格线
ax1.grid(True, which='both', axis='both', color='y', linestyle='--', linewidth=1)
# 添加注释
plt.text(2, 20, 'text', fontsize=10)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
结果如下:
最后再简单介绍几个比较常用的属性方法,matplotlib.rcParams['xtick_direction'] 、matplotlib.rcParams['ytick.direction']可以设置刻度的方向,rcParams是pylot使用rc配置文件来自定义图形各种默认属性的方法,也叫rc配置或rc参数,通过rc参数可以修改图表的默认属性,包括窗体大小、每英寸的点数、线条宽度、颜色、样式、坐标轴、坐标和网络属性、文本、字体等。plt.axis('off')可以关闭坐标轴,如果想只关闭x轴或y轴,可以使用frame = plt.gca()获取当前子图,然后用frame.axes.get_xaxis().set_visible(False)或frame.axes.get_yaxis().set_visible(False)对x轴或y轴设置是否显示。
在Matplotlib中,整个图像就是一个Figure对象,在Figure对象中可以包含一个或多个Axes对象,而每个Axes对象都是拥有自己的坐标系系统的绘图区域。在同一个Figure图像下的每个图表都代表这个图像的一个子图。
子图的创建方法
常用的子图创建方法一般有三种。
第一种,利用Figure对象的add_subplot方法生成子图然后再向其中填充图表。add_subplot方法的参数包括nrows, ncols, index以及可选参数。其中nrows, ncols是子图的行列大小,index是当前创建的子图的索引,即作为图像的第几个子图。
为了更好地展示图表,用到了numpy和pandas来创建数据。首先创建一个2*2共4个子图区域的图像,然后向其中的3个子图区域填充图表。注意,这里创建的4个区域只是占位符,不一定要去填充,而且不一定要根据顺序去填充。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
data1 = np.random.rand(100).cumsum()
data2 = 50-np.random.rand(100).cumsum()
# 2、创建图像
fig = plt.figure(figsize=(6, 6), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = fig.add_subplot(2, 2, 1)
ax1.plot(data1)
ax2 = fig.add_subplot(2, 2, 2)
ax2.plot(data2)
ax3 = fig.add_subplot(2, 2, 3)
df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
ax3.plot(df)
# 4、自定义设置
ax1.set_title("No.1")
ax2.set_title("No.2")
ax3.set_title("No.3")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行后可以看到,在左上、右上、左下三个位置分别生成了图表,当然我们也可以根据需要或自己的喜好在4个子图区域中随意选择摆放图表的位置。
第二种,使用plt.add_subplots方法同时生成Figure对象和axes对象数组,每个axes对象就相当于一个子图。add_subplots方法的参数包括nrows, ncols, sharex, sharey, squeeze, subplot_kw, gridspec_kw。其中nrows, ncols就是子图的行列大小,共生成nrows*ncols个子图。sharex, sharey设置是否共享x轴或y轴,默认不共享。squeeze默认True,挤压多余尺寸,一般默认即可。subplot_kw、gridspec_kw可选参数,用来设置子图的属性。
首先使用subplots方法得到axes对象数组,然后分别取出相应子图进行设置,同样,这里创建的axes也只是占位符。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
data1 = np.random.rand(100).cumsum()
data2 = 50-np.random.rand(100).cumsum()
# 2、创建图像
fig, axes = plt.subplots(2, 2, figsize=(6, 6), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = axes[0, 0]
ax1.plot(data1)
ax2 = axes[0, 1]
ax2.plot(data2)
ax3 = axes[1, 0]
df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
ax3.plot(df)
# 4、自定义设置
ax1.set_title("No.1")
ax2.set_title("No.2")
ax3.set_title("No.3")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行结果如下图所示。 可以看到,与之前先生成子图区域再填充的方法相比,生成axes数组会将坐标轴事先生成,即使不向其中添加图表,坐标轴也会展示在相应的位置。
第三种,利用pandas的DataFrame生成多系列图,然后拆分成子图。上述两种创建子图方法中的第三个子图都使用了pandas创建数据并在图表中展示了4条折线。这里我们依旧使用这个pandas数据,然后进行拆分直接生成子图。
# 导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 准备数据
df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
# 拆分生成子图
df.plot(figsize=(6, 6), subplots=True, layout=(2, 2))
plt.show()
运行效果如下。这种拆分方式生成的子图默认就有图例,并共用了一个x轴。
在前两种子图创建方法中,我们发现各个子图之间的间距非常小,尤其是垂直方向上的间距,看着很不舒服,我们使用subplots_adjust方法来调整子图间的间距,subplots_adjust方法接收wspace, hspace两个参数分别表示水平方向和垂直方向上的间距。以第二种方法为例,我们向其中加入subplots_adjust方法。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
# 1、准备数据
data1 = np.random.rand(100).cumsum()
data2 = 50-np.random.rand(100).cumsum()
# 2、创建图像
fig, axes = plt.subplots(2, 2, figsize=(6, 6), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = axes[0, 0]
ax1.plot(data1)
ax2 = axes[0, 1]
ax2.plot(data2)
ax3 = axes[1, 0]
df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
ax3.plot(df)
# 4、自定义设置
ax1.set_title("No.1")
ax2.set_title("No.2")
ax3.set_title("No.3")
# 调整子图间间距
plt.subplots_adjust(wspace=0.2, hspace=0.4)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
再次运行后可以看到,各个子图之间已经不再那么拥挤了。
内嵌图
除了像子图这种图表比较外,我们有时候也常常在已有的图表中再生成图表来进行比较,这种方式就叫做内嵌。
# 0、导入包
import matplotlib.pyplot as plt
# 1、准备数据
x = [1, 2, 3, 4]
y1 = [10, 20, 30, 40]
y2 = [40, 30, 20, 10]
# 2、创建图像
fig = plt.figure(figsize=(3, 3), dpi=100, facecolor=(0,1,0,1),
edgecolor=(1,0,0,1), frameon=True, linewidth=1)
# 3、绘图
ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8])
# 在ax1中内嵌
ax2 = fig.add_axes([0.2, 0.6, 0.25, 0.25])
# 4、自定义设置
ax1.plot(x, y1, 'r')
ax1.set_title('No.1')
ax2.plot(x, y2, 'b')
ax2.set_title('No.2')
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行结果如下:
线状图
线状图又称为曲线图,是最简单的图形。这种图形清楚地记录变动过程,以点标示变化,并连点成线。 在Matplotlib中,plot方法默认生成的就是线状图。
# 0、导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1、准备数据
data = pd.Series(np.random.randn(10))
# 2、创建图像
fig = plt.figure(figsize=(5, 5), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
ax.plot(data)
# 4、自定义设置
ax.set_xlabel('x')
ax.set_ylabel('y')
# 5、保存图像
# plt.savefig('xxx.png')
# 6、显示图像
plt.show()
利用Pandas的Series方法生成一组数据,然后读取后使用plot方法直接生成线状图,运行结果如下:
柱状图
柱状图是一种以长方形的长度为变量的图表,由一系列高度不等的纵向条纹表示数据分布的情况,可以用来同时比较多个事物的变化,通常利用于较小的数据集分析。在Matplotlib中,柱状图的创建方法有两种:plot(kind='bar')或plot.bar()。
首先看第一种方法,我们分别创建一个单系列柱状图和多系列柱状图。
# 0、导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1、准备数据
data1 = pd.Series(np.random.randn(10))
data2 = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd'))
# 2、创建图像
fig, axes = plt.subplots(1, 2, figsize=(12, 5), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = axes[0]
ax2 = axes[1]
data1.plot(kind='bar', ax=ax1)
data2.plot(kind='bar', ax=ax2)
# 4、自定义设置
ax1.set_title('No.1')
ax2.set_title('No.2')
# 5、保存图像
# plt.savefig('xxx.png')
# 6、显示图像
plt.show()
利用Pandas的Series和DataFrame方法分别生成一组单系列数据和多系列数据,然后使用plot(kind='bar')创建柱状图。运行结果如下图所示。如果创建的时候未指定color属性,柱状图的颜色是随机生成的。在多系列柱状图中,会自动显示图例。
第二种方法只需要将上面代码中的data1.plot(kind='bar', ax=ax1)、data2.plot(kind='bar', ax=ax2)改成data1.plot.bar(ax=ax1)、data2.plot.bar(ax=ax2)就可以了。
柱状图除了纵向排列外,有时也会用到横向排列进行比较。要使用横向排列只需要将kind='bar'或bar()换成kind='barh'或barh()即可,这里以barh()为例。
# 0、导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1、准备数据
data1 = pd.Series(np.random.randn(10))
data2 = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd'))
# 2、创建图像
fig, axes = plt.subplots(1, 2, figsize=(12, 5), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = axes[0]
data1.plot.barh(ax=ax1)
ax2 = axes[1]
data2.plot.barh(ax=ax2)
# 4、自定义设置
# 5、保存图像
# plt.savefig('xxx.png')
# 6、显示图像
plt.show()
运行后柱状图就变成横向展示了。
柱形图还可以设置成堆叠的形式,我们将上述的多系列柱状图修改成堆叠形式,只需要将stacked属性设置成True即可。
# 0、导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1、准备数据
data = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd'))
# 2、创建图像
fig = plt.figure(figsize=(5, 5), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
data.plot.bar(ax=ax, stacked=True)
# 4、自定义设置
ax.set_xlabel('x')
ax.set_ylabel('y')
# 5、保存图像
# plt.savefig('xxx.png')
# 6、显示图像
plt.show()
堆叠后同一个分类下的数据不再是依次排列而是依次从上到下堆叠在一起。
柱状图的主要作用是比较数据,观察柱状图的高度就可以判断数据的大小,但有时候两组数据非常接近时,肉眼无法通过观察高度判断大小,这时我们可以通过text()给柱状图添加文本。
# 0、导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1、准备数据
x = np.arange(10)
y = np.random.rand(10)
# 2、创建图像
fig = plt.figure(figsize=(5, 5), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
ax.bar(x, y, width=1, facecolor='yellowgreen', edgecolor='white')
# 4、自定义设置
ax.set_xlabel('x')
ax.set_ylabel('y')
for i, j in zip(x, y):
ax.text(i, j, '%.2f'%j, ha='center', va='bottom', fontsize=7)
# 5、保存图像
# plt.savefig('xxx.png')
# 6、显示图像
plt.show()
通过for循环给每个柱体添加值,i,j确定文本位置,然后设置文本显示格式,ha和va分别表示水平和垂直方向上的显示方式,fontsize设置字体大小,还可以根据喜好设置字体颜色等。
直方图
直方图又称为质量分布图,由一系列高度不等的纵向条纹或线段表示数据分布的情况。 一般用横轴表示数据类型,纵轴表示分布情况。直方图跟柱状图很类似,通常也可以将直方图当作是柱状图的一种,但柱状图主要用来比较数据的大小,而直方图的主要目的是展示数据的分布。
和柱状图一样,直方图也可以通过plot(kind='hist')或plot.hist()两种方法进行创建,我们以plot.hist()为例。
# 0、导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1、准备数据
data = pd.Series(np.random.randn(1000))
# 2、创建图像
fig = plt.figure(figsize=(5, 5), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
data.hist(ax=ax, bins=20, histtype='bar', align='mid', orientation='vertical', normed=True)
# data.plot(kind='kde', style='k--')
# 4、自定义设置
ax.set_title('hist')
# 5、保存图像
# plt.savefig('xxx.png')
# 6、显示图像
plt.show()
bins表示边数,给定bins,返回bins+1条边, 也即bins个矩形。histtype是直方图的类型,共有四种,bar传统条形直方图,barstacked堆叠条形直方图,step未填充的线图,stepfilled填充的线图,默认为bar。align设置直方图的对齐方式。orientation设置直方图纵向vertical或横向horizontal展示。normed是标准化,将数据标准化为0-1之间的数。
直方图同样也可以堆叠,方法与柱状图一样,只要设置stacked属性为True即可。
# 0、导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1、准备数据
data = pd.DataFrame(np.random.randn(1000, 4), columns=list('abcd'))
# 2、创建图像
fig = plt.figure(figsize=(5, 5), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
data.plot.hist(ax=ax, stacked=True, bins=20, histtype='bar', align='mid', orientation='vertical')
# 4、自定义设置
ax.set_title('hist')
# 5、保存图像
# plt.savefig('xxx.png')
# 6、显示图像
plt.show()
运行结果如下。
密度图
密度图是一种表现与数据值对应的边界或域对象的理论图形表示方法,一般用于呈现连续变量。 在图表展示中,密度图通常会与直方图一起出现进行展示。密度图用plot(kind='kde')或plot.kde()创建。
# 0、导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1、准备数据
data = pd.Series(np.random.randn(1000))
# 2、创建图像
fig = plt.figure(figsize=(5, 5), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
data.plot.hist(ax=ax, bins=20, histtype='bar', align='mid', orientation='vertical', normed=True)
data.plot.kde(ax=ax, ylim=(0, 1), style='k--')
# 4、自定义设置
ax.set_title('hist')
# 5、保存图像
# plt.savefig('xxx.png')
# 6、显示图像
plt.show()
运行后可以看到,密度图反映了我们创建的数据是服从正态分布的。
面积图
面积图又称为区域图,强调数量随时间而变化的程度,也可用于引起人们对总值趋势的注意。堆积面积图和百分比堆积面积图还可以显示部分与整体的关系。Matplotlib中,使用area()方法创建面积图,基本用法如下。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
data = pd.DataFrame(np.random.rand(10, 5), columns=list('abcde'))
# 2、创建图像
fig = plt.figure(figsize=(4, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
data.plot.area(ax=ax) # colormap='Greens_r'
# 4、自定义设置
ax.set_title("area")
ax.set_xlim(0, 8)
ax.set_ylim(0, 4)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行结果如下,由于没有设置颜色,每个图形呈现的颜色是随机的,设置色系可使用colormap属性。在Matplotlib中,面积图默认是堆叠的,即stacked值默认为True。
若不想堆叠显示,可以将stacked值设为False。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
data = pd.DataFrame(np.random.rand(10, 5), columns=list('abcde'))
# 2、创建图像
fig = plt.figure(figsize=(4, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
data.plot.area(ax=ax, stacked=False)
# 4、自定义设置
ax.set_title("area")
ax.set_xlim(0, 8)
ax.set_ylim(0, 1)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
设置面积图不堆叠后,呈现效果跟下面讲到的填充图的重叠很像,运行效果如下图所示。
填充图
填充图用于基本图表的填充,分为多边形填充(简单来说,就是填充函数和坐标轴之间的区域)和函数间区域填充。Matplotlib中,分别用fill(*args, **kwargs)和fill_between()来实现多边形填充和函数间区域填充。
多边形填充fill(*args, **kwargs)中,args参数是x, y的序列,以及可选的color参数。kwargs是图形的可选属性参数,例如标签label,透明度alpha等。用法如下。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
x = np.linspace(0, 1, 1000)
y1 = np.sin(3 * np.pi * x) * np.exp(2 * x)
y2 = -np.sin(3 * np.pi * x) * np.exp(2 * x)
# 2、创建图像
fig, axes = plt.subplots(2, 2, figsize=(8, 8), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = axes[0, 0]
ax2 = axes[0, 1]
ax3 = axes[1, 0]
ax4 = axes[1, 1]
ax1.fill(x, y1, label='y1')
ax2.fill(x, y2, 'r', alpha=0.5, label='y2')
ax3.fill(x, y1, x, y2)
ax4.fill(x, y1, 'r', x, y2, 'b')
# 4、自定义设置
ax1.set_title("No.1")
ax1.legend(loc=0)
ax2.set_title("No.2")
ax2.legend(loc=2)
ax3.set_title("No.3")
ax4.set_title("No.4")
plt.subplots_adjust(wspace=0.1, hspace=0.3)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
上述代码创建了4个填充图,分别是使用默认颜色填充一个图形 ,使用红色填充一个图形,使用默认颜色填充两个图形,使用红色和蓝色填充两个图形。运行结果如下。
当图形多于一个时添加图例,我们可以使用两次fill()方法,分别设置对应的图例名称。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
x = np.linspace(0, 1, 1000)
y1 = np.sin(3 * np.pi * x) * np.exp(2 * x)
y2 = -np.sin(3 * np.pi * x) * np.exp(2 * x)
# 2、创建图像
fig = plt.figure(figsize=(4, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
ax.fill(x, y1, 'r', label='y1')
ax.fill(x, y2, 'b', label='y2')
# 4、自定义设置
ax.legend(loc=2)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行效果如下。
当图形之间有重叠时,填充图的呈现效果就类似于不堆叠的面积图。我们在上述代码的基础上再添加一个填充图,为了便于观察重叠部分,我们将y3的透明度值设置成0.5。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
x = np.linspace(0, 1, 1000)
y1 = np.sin(3 * np.pi * x) * np.exp(2 * x)
y2 = -np.sin(3 * np.pi * x) * np.exp(2 * x)
y3 = -np.sin(2 * np.pi * x) * np.exp(3 * x)
# 2、创建图像
fig = plt.figure(figsize=(4, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
ax.fill(x, y1, 'r', label='y1')
ax.fill(x, y2, 'b', label='y2')
ax.fill(x, y3, 'c', alpha=0.5, label='y3')
# 4、自定义设置
ax.legend(loc=2)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行效果如下,可以看到基本与不设置堆叠的面积图一样,重叠部分的颜色效果是由重叠的各个图形颜色叠加生成。
函数间区域填充fill_between()常用的参数包括x, y1, y2, where等。x, y1, y2分别表示了两条曲线,where是条件表达式,可以排除一些不想被包括的区域。此外,还可以传入可选的属性参数。fill_between基本用法如下。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
x = np.linspace(0, 1, 1000)
y1 = -np.sin(3 * np.pi * x) * np.exp(2 * x)
y2 = -np.sin(2 * np.pi * x) * np.exp(3 * x)
# 2、创建图像
fig = plt.figure(figsize=(4, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
ax.fill_between(x, y1, y2, facecolor="b")
# 4、自定义设置
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行结果如下图所示。
饼图
饼图是显示一个数据系列中各项数据的大小与各项数据总和的比例的一种图表。饼图中的数据点显示为整个饼图的百分比。Matplotlib中,饼图使用pie()方法实现。pie()的参数包括x, explode, labels, colors, autopct, pctdistance, shadow, labeldistance, startangle, radius, counterclock, wedgeprops, textprops, center, frame, rotatelabels。
各参数意义:x是绘制饼图所用的数据。explode是每部分相对于半径的偏移量。labels是每部分标签的字符串序列。colors是饼图循环使用的颜色参数序列。autopct是饼图上的标签显示方式。pctdistance是每个饼图切片的中心与通过autopct生成的文本开始之间的比例。shadow可以设置在饼图下画一个阴影。labeldistance是饼图标签的径向距离。startangle是开始角度(从X轴逆时针旋转饼图的起点角度)。radius是饼图的半径,默认为1。counterclock指定顺时针或逆时针。wedgeprops是传递给饼图对象的参数字典。textprops是传递给文本对象的参数的dict。center设置图表的中心位置。frame为True使用图表绘制轴框架。rotatelabels为True将每个标签旋转到相应切片的角度。
绘制数据x的饼图。每个楔块的分数区域由x/sum(x)给出。如果sum(x)<1,则x的值将直接给出分数区域,且数据x将不规范化,生成的饼图将有一个大小为1-x/sum(x)的空楔块。我们分别绘制sum(x)>1和sum(x)<1两种情况下的饼图,为了比较一些属性,第二个饼图我们取消偏移量,同时设置成顺时针方向。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
data1 = pd.Series(3 * np.random.rand(4), index=list('abcd'), name='index')
data2 = [0.15, 0.30, 0.25, 0.10]
# 2、创建图像
fig, axes = plt.subplots(1, 2, figsize=(5, 5), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = axes[0]
ax1.pie(data1, explode=[0.1, 0, 0, 0], labels=data.index,
colors=['r', 'g', 'b', 'c'], autopct='%.2f%%',
pctdistance=0.6, labeldistance=1.1,
shadow=True, startangle=0, radius=1.5, frame=False)
ax2 = axes[1]
ax2.pie(data2, labels=data.index, colors=['r', 'g', 'b', 'c'],
autopct='%.2f%%', pctdistance=0.6, labeldistance=1.1,
counterclock=False, shadow=True, startangle=0, radius=1.5, frame=False)
# 4、自定义设置
ax1.set_title("Pie1")
ax2.set_title("Pie2")
plt.subplots_adjust(wspace=0.5)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行效果如下图所示,可以看到, 第二个饼图由于sum(x)<1,不再以x/sum(x)给出每部分,而是直接用了x的值,并且会空出一块。
饼图还可以进行嵌套,即嵌套饼图。在这种情况下,饼图采用与组中的计数相对应的值。我们首先生成一些对应于三个组的假数据,在外环中,我们将它们绘制为原始3个组的成员,然后在内环中,我们把每个数字视为属于自己的组。 用法如下。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
size = 0.3
vals = np.array([[60., 32.], [37., 40.], [29., 10.]])
cmap = plt.get_cmap("tab20c")
outer_colors = cmap(np.arange(3)*4)
inner_colors = cmap(np.array([1, 2, 5, 6, 9, 10]))
# 2、创建图像
fig, ax = plt.subplots(1, 1, figsize=(6, 6), facecolor=(0, 1, 0, 1))
# 3、绘图
ax.pie(vals.sum(axis=1), radius=1+size, colors=outer_colors, autopct='%.2f%%',
wedgeprops=dict(width=size, edgecolor='w'))
ax.pie(vals.flatten(), radius=1-size, colors=inner_colors, autopct='%.2f%%',
wedgeprops=dict(width=size, edgecolor='w'))
# 4、自定义设置
ax.set(aspect="equal", title='Pie plot with `ax.pie`')
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
为了便于比较,我们将外环的radius设置成1.3,将内环的radius设置成0.7。这里利用了numpy数组的sum()方法和flatten()方法,sum()设置axis=1对行方向上求和,得到外环的数据,flatten()方法将二维数组降成一维得到内环的数据。运行结果如下图所示。
散点图
散点图是指在回归分析中,数据点在直角坐标系平面上的分布图。散点图表示因变量随自变量变化的大致趋势,据此可以选择合适的函数对数据点进行拟合。散点图通常用两组数据构成多个坐标点,考察坐标点的分布,判断两变量之间是否存在某种关联或总结坐标点的分布模式。散点图将序列显示为一组点,值由点在图表中的位置表示,类别由图表中的不同标记表示。散点图通常用于比较跨类别的聚合数据。
Matplotlib中,散点图用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:绘制散点图的数据点。
s:可选参数。散点的大小,为一个实数或数组。默认大小为20。
c:可选参数。散点图的颜色序列。这里要注意c不是一个单一的RGB或RGBA序列,而是一个RGB或RGBA的二维数组。
marker:可选参数。散点图的散点样式,可选样式可参考之前介绍Matplotlib属性时的相关内容。
cmap:可选参数。颜色映射实例或注册的颜色映射名称。只有当c是一个浮点数组时,才使用cmap。
norm:可选参数。若为True,则将数据正则化为0-1之间的数。
vmin, vmax:可选参数。数据边界化,但是若norm已设置为True,则参数无效。
alpha:可选参数。设置散点透明度。
linewidths:可选参数。标记点的长度。
edgecolors:可选参数。颜色或颜色序列,标记边缘颜色。
绘制散点图用法如下。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
x = np.random.randn(1000)
y = np.random.randn(1000)
# 2、创建图像
fig = plt.figure(figsize=(4, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
ax.scatter(x, y, marker='.')
# 4、自定义设置
ax.set_title("scatter")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
上述代码绘制了一个简答的散点图,运行结果如下图所示。
通过修改属性参数,可以绘制各种样式的散点图。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
x = np.random.randn(200)
y = np.random.randn(200)
# 2、创建图像
fig, axes = plt.subplots(2, 2, figsize=(6, 6), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = axes[0, 0]
ax1.scatter(x, y, marker='.', s=10)
ax2 = axes[0, 1]
ax2.scatter(x, y, marker='.', s=60, c=x, alpha=0.8)
ax3 = axes[1, 0]
ax3.scatter(x, y, marker='^', c=x)
ax4 = axes[1, 1]
ax4.scatter(x, y, marker='.', s=np.random.randn(1000)*100, c=x, edgecolors=(1, 0, 0, 1))
# 4、自定义设置
ax1.set_title("scatter1")
ax2.set_title("scatter2")
ax3.set_title("scatter3")
ax4.set_title("scatter4")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
上述代码绘制了4个散点图。图1设置散点的大小s=10小于默认值;图2设置散点的大小s=60大于默认值,同时将numpy数组x作为颜色数组传入c,并设置透明度alpha=0.8;图3设置散点的样式为三角形;图4将s将散点的大小s设置成随机数数组,同时设置散点的边颜色edgecolors。运行效果如下图所示。
有时我们会需要考察多个变量之间的相关关系,我们可以使用散点图矩阵。由于Matplotlib中没有介绍到散点图矩阵,我们借用pandas来实现,另一个绘制图表库seaborn中有专门的绘制散点图矩阵的方法,如果有机会介绍我们再详细展开。pandas中通过scatter_matrix()方法实现散点图矩阵。scatter_matrix()方法接收数据,主要参数为diagonal,只能传hist或kde,hist为直方图表示方式,kde为密度图表示方式,此外还可传marker, alpha等相关属性参数。基本用法如下。
# 导入包
import numpy as np
import pandas as pd
# 准备数据
data = pd.DataFrame(np.random.randn(200, 3), columns=list('abc'))
# 绘制图表
pd.plotting.scatter_matrix(data, marker='.', diagonal='hist') # diagonal还可以传kde,只能二选一
我们以hist直方图表示方式为例,运行结果如下。
设置中文
在Matplotlib的使用中,如果给图表添加中文,我们会发现出现了乱码。我们给图表标题设置一个中文名称。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
x = np.random.randn(1000)
y = np.random.randn(1000)
# 2、创建图像
fig = plt.figure(figsize=(5, 5), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111)
ax.scatter(x, y, marker='.', s=np.random.randn(1000)*100, c=y, alpha=0.8)
# 4、自定义设置
ax.set_title("散点图")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行后发现无法正常显示,所有中文都变成了一个个的小框框。
解决方法如下。
1、找到matplotlibrc文件所在路径,使用matplotlib的matplotlib_fname方法可以获取。
import matplotlib as mpl
print(mpl.matplotlib_fname())
进入matplotlibrc所在目录,该目录下会有如下内容。
2、下载中文字体包,这里我们用简体中文字体包(SimHei.ttf),可以用下面给出的下载链接进行下载。将下载好的字体包放入上述目录的fonts文件夹下。
简体中文字体包下载链接: https://pan.baidu.com/s/1soOXkgCVkl125CquOpOHCQ 提取码: 6rcp
3、打开matplotlibrc文件,全局搜索找到font.family、font.sans-serif两个地方,然后去掉注释,即前面的“#”,并在font.sans-serif后面添加我们要加入的字体,这里我们添加SimHei。再全局搜索找到axes.unicode_minus,去掉注释,并将True改成False,最后保存退出。
4、清除缓存。mac用户直接在“/User/当前用户名”下,Windows用户在“C:/用户/当前用户名”下,找到.matplotlib文件夹,直接删除它即可。
5、如果使用Jupyter,需要先重启。然后再重新运行代码,即可正常显示中文,效果如下。
极坐标图
有些几何轨迹问题如果用直角坐标法来处理会比较困难,极坐标法就在基于此之上应运而生。许多直角坐标法难以处理的问题换用极坐标法来处理就会相对简单许多,作图也会比较方便。
在平面内取定点O,称为极点,引一条射线Ox,称为极轴,再选定一个长度单位和角度的正方向(通常取逆时针方向)。对于平面内任何一点M,用ρ或r表示线段OM的长度,称为极径,θ表示从Ox到OM的角度,称为极角,有序数对(ρ,θ)就叫点M的极坐标,这样建立的坐标系就是极坐标系。在极坐标系下的图表就是极坐标图。
在Matplotlib中,直角坐标系换成极坐标系只需要在创建子图的时候设置参数projection='polar'或polar=True即可。下面我们简单看一下极坐标图。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
data = pd.Series(np.arange(10))
# 2、创建图像
fig = plt.figure(figsize=(10, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = fig.add_subplot(121)
ax1.plot(data, linestyle='-', marker='.', linewidth=1)
ax2 = fig.add_subplot(122, projection='polar')
ax2.plot(data, linestyle='-', marker='.', linewidth=1)
# 4、自定义设置
ax1.set_title("直角坐标系")
ax2.set_title("极坐标系\n")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
为了便于比较,我们让同一组数据分别绘制在直角坐标系和极坐标系下,运行后效果如下,可以看到极坐标系下的角度正方向默认是逆时针方向。
下面我们看一下极坐标图的一些常用属性。set_rmax(),set_rmin(),set_rlim()分别设置显示的极径最大值最小值以及极径显示范围。修改极坐标系下的角度方向用set_theta_direction(),默认为逆时针,传-1时修改为顺时针方向。set_thetagrids()、set_rgrids()分别设置极坐标角度线和极径网格线,其中极径网格线的参数必须是正数。set_theta_offset()设置角度偏移,按逆时针方向,例子中我们设置偏移π/2,即逆时针方向旋转90度。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
theta = np.arange(0, 2*np.pi, 2*np.pi/8) # 角度数据
radius = np.arange(1,9,1) # 极径数据
# 2、创建图像
fig = plt.figure(figsize=(10, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = fig.add_subplot(121, projection='polar')
ax1.plot(theta, radius, '-')
ax2 = fig.add_subplot(122, polar=True)
ax2.plot(theta, radius, '-', linewidth=2)
# 4、自定义设置
ax1.set_title("No.1\n")
ax1.set_rmax(9) # 设置显示的极径最大值
ax2.set_title("No.2\n")
ax2.set_theta_direction(-1) # 坐标轴方向 默认逆时针 -1为顺时针
ax2.set_thetagrids(np.arange(0.0, 360.0, 90), list('abcd')) # 设置极坐标角度线显示及标签 网格和标签数量一致
ax2.set_rgrids(np.arange(0, 9, 2)) # 设置极径网格线显示 其中参数必须是正数
ax2.set_theta_offset(np.pi/2) # 设置角度偏移 逆时针 弧度制
ax2.set_rlim(0, 9) # 设置显示的极径范围
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
创建两个子图,我们给图二设置各种属性,对比效果如下。
极坐标图还可以将坐标系设置成扇形和环形。设置扇形使用set_thetamin()和set_thetamax()指定截取角度,按逆时针方向,例子中我们截取45度~135度的区域。设置环形使用set_rorigin(),设置起点与极点之间的距离,传入负数。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
theta = np.arange(0, 2*np.pi, 2*np.pi/8) # 角度数据
radius = np.arange(1,9,1) #极径数据
# 2、创建图像
fig = plt.figure(figsize=(10, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = fig.add_subplot(121, projection='polar')
ax1.plot(theta, radius, '-')
ax2 = fig.add_subplot(122, polar=True)
ax2.plot(theta, radius, '-', linewidth=2)
# 4、自定义设置
ax1.set_thetamin(45)
ax1.set_thetamax(135)
ax2.set_rorigin(-3)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行效果如下图所示。
使用fill()方法可以对极坐标图进行填充,如果想让折线首尾相连,我们可以给数据组添加第一个数据。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
theta = np.arange(0, 2*np.pi, 2*np.pi/10)
radius = np.arange(1, 11, 1)
# 2、创建图像
fig = plt.figure(figsize=(8, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = fig.add_subplot(121, projection='polar')
ax1.plot(theta, radius, '.-')
ax1.fill(theta, radius1, alpha=0.5) # 填充
ax2 = fig.add_subplot(122, projection='polar')
theta = np.append(theta, theta[0])
radius = np.append(radius, radius[0])
ax2.plot(theta, radius, '.-')
ax2.fill(theta, radius, alpha=0.5)
# 4、自定义设置
ax1.set_rlim(0, 10)
ax2.set_rlim(0, 10)
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行后效果如下,为了便于观察,我们将透明度设置为0.5。
极区图
极区图又叫南丁格尔玫瑰图,是一种圆形的柱状图或直方图,形状上看很像是半径不等的扇形图。Matplotlib中使用极区图可以看成是在极坐标系下创建柱状图,即创建子图时设置projection='polar',然后调用ax.bar(),具体用法如下,作为对比,我们同时创建一个折线的极坐标图。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
theta = np.arange(0, 2*np.pi, 2*np.pi/10)
radius = np.random.randint(0, 10, 10)
# 2、创建图像
fig = plt.figure(figsize=(8, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = fig.add_subplot(121, projection='polar')
bar = ax1.bar(theta, radius, alpha=0.5)
for r, bar in zip(radius, bar):
bar.set_facecolor(plt.cm.jet(r/10)) # 设置颜色
ax2 = fig.add_subplot(122, projection='polar')
ax2.plot(theta, radius)
# 4、自定义设置
ax1.set_title("极区图\n")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行结果如下图所示。
极散点图
极散点图就是在极坐标系下的散点图。散点图主要用来探索变量之间存在的关联性,有时直角坐标系下观察不出的关系换到极坐标系下或许就会比较明朗了。基本使用方法如下。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
N = 150
r = 2 * np.random.rand(N)
theta = 2 * np.pi * np.random.rand(N)
area = 50 * r**2
colors = theta
# 2、创建图像
fig = plt.figure(figsize=(4, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax = fig.add_subplot(111, polar=True)
ax.scatter(theta, r, c=colors, s=area, cmap='hsv', alpha=0.75)
# 4、自定义设置
ax.set_title("极散点图\n")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行结果如下图所示。
箱形图
箱形图又称为盒须图、盒式图或箱线图,是一种用作显示一组数据分散情况资料的统计图。因形状如箱子而得名。在各种领域也经常被使用,常见于品质管理。它主要用于反映原始数据分布的特征,还可以进行多组数据分布特征的比较。
要绘制箱形图,我们需要了解最大值、最小值、中位数、两个四分位数(上四分位数和下四分位数)和异常值的概念。
最大值、最小值:一组数据中最大的数和最小的数。
中位数:按顺序排列的一组数据中居于中间位置的数,即在这组数据中,平均会有一半的数据比他大,有一半的数据比他小。
四分位数:也称四分位点,是指在统计学中把所有数值由小到大排列并分成四等份,处于三个分割点位置的数值。四分位数指的是一组数据排序后处于25%和75%位置上的值。四分位数是通过3个点将全部数据等分为4部分,其中每部分包含25%的数据。很显然,中间的四分位数就是中位数,因此通常所说的四分位数是指处在25%位置上的数值(称为下四分位数)和处在75%位置上的数值(称为上四分位数)。四分位数的计算有(n+1)/4、(n+1)*3/4和(n-1)、(n-1)*3/4两种,我们一般使用前一种那么下四分位数Q1=(n+1)/4,上四分位数Q3=(n+1)*3/4。
异常值:箱形图中的异常值判断以四分位数(Q3、Q1)和四分位距(IQR=Q3-Q1)为基础,异常值被定义为小于下边缘(Q1-1.5IQR)或大于上边缘(Q3+1.5IQR)的值。除了上下边缘,箱形图中还有极上限(Q3+3IQR)和极下限(Q1-3IQR)的概念。小于下边缘或大于上边缘的异常值称为中度异常,小于极下限或大于极上限的异常值称为极度异常。
有了上述的概念,就可以绘制出箱形图了。一个基本的箱形图如下所示,主要包含六个数据节点,将一组数据从大到小排列,分别计算出他的上边缘,上四分位数,中位数,下四分位数和下边缘,以及可能存在的异常值。
在Matplotlib中,箱形图使用box()或boxplot()绘制。我们使用box()方法分别绘制一个简单的箱形图和一个横向的箱形图。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
data = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd'))
print(data)
# 2、创建图像
fig, axes = plt.subplots(1, 2, figsize=(8, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
color = dict(boxes='g', whiskers='r', medians='b', caps='k') # 着色
ax1 = axes[0]
data.plot.box(ylim=[0, 1], grid=True, color=color, ax=ax1)
ax2 = axes[1]
data.plot.box(vert=False, positions=[1, 4, 5, 7], ax=ax2, grid=True, color=color)
# 4、自定义设置
ax1.set_title("箱型图")
ax2.set_title("横向箱型图")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
设置vert参数为False绘制横向的箱形图,positions确定横向的箱形图在竖直方向上的位置,color传一个dict字典,boxes、whiskers、medians、caps分别表示箱形图的箱子、盒须、中位线、边缘线的颜色。运行后效果如下。
下面介绍boxplot()创建箱形图的方法。可传参数较多,这里尝试了几个常用的。sym是异常点的形状,whis是四分位距IQR的值,默认为1.5,可以设置一个值,也可以设置成一个区间,表示强制上下边缘数据。showmeans和meanline设置是否显示均值线及其形状,meanline为True时,均值线为虚线,False时均值线为一个点。showbox、showcaps、showfliers分别表示是否显示箱线、边缘线、异常值,这里需要注意,没有showmedians这个属性。boxprops、whiskerprops、medianprops、flierprops传入一个字典,分别用于设置箱线、盒须线、中位线、异常值的属性。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
data = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd'))
# 2、创建图像
fig = plt.figure(figsize=(4, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = fig.add_subplot(111)
data.boxplot(sym='^', vert=True, whis=1.5,
patch_artist=False, meanline=True, showmeans=True,
showbox=True, showcaps=True, showfliers=True,
boxprops=dict(linewidth=2),
whiskerprops=dict(linewidth=1),
medianprops=dict(linewidth=2),
flierprops=dict(linewidth=1),
notch=False)
# 4、自定义设置
ax1.set_title("箱型图")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行结果如下图所示。
使用boxplot()方法绘制箱形图,着色还有另一种比较灵活的方法:传入参数return_type='dict'返回一个字典类型,然后从字典类型中取出相关的元素进行属性设置。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 1、准备数据
data = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd'))
# 2、创建图像
fig = plt.figure(figsize=(4, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = fig.add_subplot(111)
f = data.boxplot(ax=ax1, return_type='dict')
for box in f['boxes']:
box.set(color='g', linewidth=1)
for whisker in f['whiskers']:
whisker.set(color='r', linewidth=0.5, linestyle='-')
for cap in f['caps']:
cap.set(color='gray', linewidth=2)
for median in f['medians']:
median.set(color='b', linewidth=2)
for flier in f['fliers']:
flier.set(marker='*', color='k', linewidth=0.5)
# 4、自定义设置
ax1.set_title("箱型图")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
除了设置颜色外,我们还设置了线宽和异常值的形状等其他属性。由于我们的数据集是随机数,所以运行后可能没有异常值,可以多运行几遍或者自己构造一个有异常值的数据集。利用这种方法还可以给每个箱型设置不同的属性。运行结果如下。
处理Image
Matplotlib可以利用其image库对图片进行处理,我们加载一张本地图片。首先导入matplotlib的image包,然后使用imread()方法读取图片,再用pyplot的imshow()方法显示图片。
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
pic_path = '/Users/qhzc-imac-02/Downloads/python.jpg'
img = mpimg.imread(pic_path)
plt.imshow(img)
运行后图片就顺利加载了。
利用colorbar()方法可以给图片添加颜色条,默认为纵向颜色条,换成横向只需要将参数orientation设置为horizontal即可。
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
pic_path = '/Users/qhzc-imac-02/Downloads/python.jpg'
img = mpimg.imread(pic_path)
plt.imshow(img)
# 关闭坐标轴
frame = plt.gca()
frame.axes.get_xaxis().set_visible(False)
frame.axes.get_yaxis().set_visible(False)
# 设置颜色条
plt.colorbar()
plt.colorbar(orientation='horizontal')
运行结果如下图所示。
每个图像都有R、G、B三通道,当我们只保留一个通道时,图像就变成了单通道图像,此时再用imshow方法时,Matplotlib会自动显示成一副伪彩色图像。当显示伪彩色图像时,我们可以通过属性设置其他色彩。
# 0、导入包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import matplotlib.image as mpimg
# 1、准备数据
data = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd'))
pic_path = '/Users/qhzc-imac-02/Downloads/python.jpg'
img = mpimg.imread(pic_path)
# 2、创建图像
fig, axes = plt.subplots(1, 2, figsize=(8, 4), facecolor=(0, 1, 0, 1))
# 3、绘图
ax1 = axes[0].imshow(img)
fig.colorbar(ax1, ax=axes[0])
new_img = img[:,:,0]
ax2 = axes[1].imshow(new_img)
ax2.set_cmap('nipy_spectral')
fig.colorbar(ax2, ax=axes[1])
# 4、自定义设置
axes[0].set_title("原图")
axes[1].set_title("修改图")
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
我们创建两个子图分别显示原图和修改后的图,可以看到,修改后的图的色彩发生了变化。
在Python中处理图片的库有很多,Matplotlib结果OpenCV,Pillow等图片处理库可以做很多有意义的事。
由于图片也是一组数据,我们可以通过构造数据来生成一张图片。利用numpy生成一个4*4的二维数组,然后通过imshow()显示生成的图片。
import matplotlib.pyplot as plt
import numpy as np
# 定义图像数据
data = np.linspace(0, 1, 16).reshape(4, 4)
print(data)
# 显示图像数据
plt.imshow(data)
# 添加颜色条
plt.colorbar()
plt.show()
运行结果如下。
3D图
这里的3D图指的是相对于二维图形来讲的三维图形,可以理解为在原先x、y坐标轴的基础上再加一个z轴。Matpoltlib中创建3D图表与创建2D图表类似,首先创建一个新的图像figure,然后向其添加一个类型为axes3d的新轴,使用关键字projection='3d'创建axes3d对象,基本创建方法如下。
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
上述代码我们创建了一个3D坐标系,因为创建3D图表需要用到axes3d对象,导入的包除了matplotlib的pyplot包之外,还需要从mpl_toolkits的mplot3d包中引入Axes3D,运行结果如下图所示。
3D线状图
3D线状图就是在2D线状图x,y数据组的基础上再加一组数据z。下面我们创建x,y,z三组数据,然后作为对比,分别绘制2D线状图和3D线状图。
# 0、导入包
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
# 设置图例字体大小
mpl.rcParams['legend.fontsize'] = 10
# 1、准备数据
theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)
z = np.linspace(-2, 2, 100)
r = z**2 + 1
x = r * np.sin(theta)
y = r * np.cos(theta)
# 2、创建图像
fig = plt.figure(figsize=(10, 4))
# 3、绘图
ax1 = fig.add_subplot(121)
ax1.plot(x, y, label='2D线状图')
ax2 = fig.add_subplot(122, projection='3d')
ax2.plot(x, y, z, label='3D线状图')
# 4、自定义设置
ax1.legend()
ax2.legend()
# 5、保存图形(按需要使用)
# plt.savefig(‘xxx.png’)
# 6、显示图形
plt.show()
运行后结果如下。可以看到,3D线状图相比于2D线状图就像是把2D图像往第三轴拉一样。
3D散点图
3D散点图和2D散点图之间的关系与3D线状图和2D线状图之间的关系类似,只是对散点的坐标增加了第三轴。Matplotlib中3D散点图的绘制与2D散点图一样,仍然使用scatter()方法,只是在原先的基础上增加了参数z和zdir分别表示第三轴数据和第三轴命名,不难想到,2D散点图只是将z置为了0。基本用法如下,我们分别绘制2D散点图和3D散点图。
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
def randrange(n, vmin, vmax):
'''
创建n个分布在vmin~vmax的数据
'''
return (vmax - vmin)*np.random.rand(n) + vmin
fig = plt.figure(figsize=(10, 4))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122, projection='3d')
n = 100
# 对于每一组样式和范围设置,在框中绘制n个随机点
# defined by x in [23, 32], y in [0, 100], z in [zlow, zhigh].
for c, m, zlow, zhigh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zlow, zhigh)
ax1.scatter(xs, ys, c=c, marker=m)
ax2.scatter(xs, ys, zs, c=c, marker=m)
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
ax1.set_title('2D散点图')
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
ax2.set_zlabel('Z')
ax2.set_title('3D散点图')
plt.show()
运行结果如下。
线框图
线框图类似于网格图,Matplotlib中绘制线框图使用Axes3D的plot_wireframe()方法,传入参数除了数据组x,y,z之外,还有两组重要参数,分别是rstride、cstride和rcount、ccount。rstride、cstride分别表示行列之间的跨度,rcount、ccount分别表示行列之间的间隔个数,两组参数只能二选一设置,如果同时设置,会抛出ValueError异常错误。rstride、cstride和rcount、ccount设置的时候如果其中一个值设置为0,线框图就会变成3D线图。我们利用axes3d对象的get_test_data()方法创建一组测试数据,然后绘制三个线框图,并将其中两个分别设置行之间跨度为0,列之间跨度为0。
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(12, 3))
ax1 = fig.add_subplot(131, projection='3d')
# 从get_test_data方法中获取一些测试数据
X, Y, Z = axes3d.get_test_data(0.05)
ax1.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
ax2 = fig.add_subplot(132, projection='3d')
ax2.plot_wireframe(X, Y, Z, rstride=10, cstride=0)
ax3 = fig.add_subplot(133, projection='3d')
ax3.plot_wireframe(X, Y, Z, rstride=0, cstride=10)
plt.show()
运行结果如下。可以看到,行列之间的跨度其中有一个设置为0时,就不再是线框图了,会变得像3D线图一样。
曲面图
曲面图可以观察分析不同系列数据之间的关系,在连续曲面上跨两维显示数值的趋势。Matplotlib中曲面图的绘制使用Axes3D的plot_surface()方法,默认情况下,曲面图是以纯色的阴影着色的。plot_surface()方法与上述讲到的绘制线框图plot_wireframe()方法一样,也有rstride、cstride和rcount、ccount两组参数,且二者只能二选一使用,与plot_wireframe()方法不同的是,plot_surface()方法中,rstride、cstride和rcount、ccount两组参数不管选哪一组使用任意一个参数都不能为0,否则会报错。此外,antialiased参数为设置抗锯齿,默认为True。基本用法如下。
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure(figsize=(17, 5))
ax1 = fig.add_subplot(131, projection='3d')
ax2 = fig.add_subplot(132, projection='3d')
ax3 = fig.add_subplot(133, projection='3d')
# 构造数据
x1 = np.arange(-5, 5, 0.25)
y1 = np.arange(-5, 5, 0.25)
x1, y1 = np.meshgrid(x1, y1)
r1 = np.sqrt(x1**2 + y1**2)
z1 = np.sin(r1)
u2 = np.linspace(0, 2 * np.pi, 100)
v2 = np.linspace(0, np.pi, 100)
x2 = 10 * np.outer(np.cos(u2), np.sin(v2))
y2 = 10 * np.outer(np.sin(u2), np.sin(v2))
z2 = 10 * np.outer(np.ones(np.size(u2)), np.cos(v2))
x3 = np.arange(-5, 5, 0.25)
y3 = np.arange(-5, 5, 0.25)
xlen = len(x3)
ylen = len(y3)
x3, y3 = np.meshgrid(x3, y3)
r3 = np.sqrt(x3**2 + y3**2)
z3 = np.sin(r3)
# 设置颜色
colortuple = ('y', 'b')
colors = np.empty(x1.shape, dtype=str)
for y in range(ylen):
for x in range(xlen):
colors[x, y] = colortuple[(x + y) % len(colortuple)]
# 绘图 antialiased是否关闭抗锯齿
ax1.plot_surface(x1, y1, z1, cmap=cm.coolwarm, linewidth=0, antialiased=False)
ax2.plot_surface(x2, y2, z2, color='b')
ax3.plot_surface(x3, y3, z3, facecolors=colors, linewidth=0, antialiased=True)
# 自定义Z轴
ax1.set_zlim(-1.01, 1.01)
ax1.zaxis.set_major_locator(LinearLocator(10))
ax1.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
ax3.set_zlim(-1, 1)
ax3.w_zaxis.set_major_locator(LinearLocator(6))
plt.show()
运行结果如下图所示。我们创建了3个不同形状的曲面图,第一个图和第三个图分别设置antialiased为False和True,显示的纹路清晰度是不一样的(这里为了展示不同的色彩,第一个图和第三个图的纹路对比可能不是很清晰,可以尝试设置第三个图的antialiased分别为False、True进行对比)。
三角形曲面图
三角形曲面图顾名思义就是用一个个小三角形堆起来的曲面图,Matplotlib中使用Axes3D中的plot_trisurf()方法绘制。plot_trisurf()方法的常用参数及意义如下。
x,y,z:作为数据值作为一维数组。
color:表面贴片的颜色。
cmap:表面补丁的颜色图。
norm:规范化的一个实例,用于将值映射到颜色。
vmax,vmin:要映射的最大、最小值。
shade:是否对面色进行投影。
基本用法如下,核心是创建用于构成曲面图的小三角形。我们绘制三个不同形状的三角形曲面图。
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.tri as mtri
fig = plt.figure(figsize=(17, 5))
n_radii = 8
n_angles = 36
# 创建半径和角度空间
radii = np.linspace(0.125, 1.0, n_radii)
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)
# 对每个半径重复所有角度
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)
# 将极坐标(半径、角度)转换为笛卡尔坐标(X、Y)。(0,0)是在此阶段手动添加的,因此不会有重复项(x,y)平面上的点。
x = np.append(0, (radii*np.cos(angles)).flatten())
y = np.append(0, (radii*np.sin(angles)).flatten())
# 计算z创建曲面
z = np.sin(-x*y)
ax = fig.add_subplot(131, projection='3d')
ax.plot_trisurf(x, y, z, linewidth=0.2, antialiased=True)
n_angles = 36
n_radii = 8
min_radius = 0.25
radii = np.linspace(min_radius, 0.95, n_radii)
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)
angles[:, 1::2] += np.pi/n_angles
# 将半径、角度对映射到X、Y、Z点
x = (radii*np.cos(angles)).flatten()
y = (radii*np.sin(angles)).flatten()
z = (np.cos(radii)*np.cos(angles*3.0)).flatten()
# 创建三角测量 没有三角形,因此创建了Delaunay三角测量
triang = mtri.Triangulation(x, y)
# 去掉不需要的三角形
xmid = x[triang.triangles].mean(axis=1)
ymid = y[triang.triangles].mean(axis=1)
mask = np.where(xmid**2 + ymid**2 < min_radius**2, 1, 0)
triang.set_mask(mask)
ax = fig.add_subplot(132, projection='3d')
ax.plot_trisurf(triang, z, cmap=plt.cm.CMRmap)
# 在参数化变量u和v的空间中创建一个网格
u = np.linspace(0, 2.0 * np.pi, endpoint=True, num=50)
v = np.linspace(-0.5, 0.5, endpoint=True, num=10)
u, v = np.meshgrid(u, v)
u, v = u.flatten(), v.flatten()
x = (1 + 0.5 * v * np.cos(u / 2.0)) * np.cos(u)
y = (1 + 0.5 * v * np.cos(u / 2.0)) * np.sin(u)
z = 0.5 * v * np.sin(u / 2.0)
# 三角化参数空间确定三角形
tri = mtri.Triangulation(u, v)
ax = fig.add_subplot(133, projection='3d')
ax.plot_trisurf(x, y, z, triangles=tri.triangles, cmap=plt.cm.Spectral)
ax.set_zlim(-1, 1)
plt.show()
运行结果如下图所示。
3D等高线图
Matplotlib中使用Axes3D的contour()方法绘制等高线图。contour()方法的常用参数及意义如下。
x,y,z:作为数据值作为一维数组。
extend3d:是否在3d中扩展轮廓(默认值:False)。
stride:用于延伸轮廓的步幅(步幅大小)。
zdir:要使用的方向:x、y或z(默认)。
offset:偏移。如果指定了偏移,则在垂直于Zdir的平面上绘制该位置上轮廓线的投影。
基本用法如下。
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
fig = plt.figure(figsize=(17, 5))
ax1 = fig.add_subplot(131, projection='3d')
X, Y, Z = axes3d.get_test_data(0.05)
cset = ax1.contour(X, Y, Z, cmap=cm.coolwarm)
ax1.clabel(cset, fontsize=9, inline=1)
ax2 = fig.add_subplot(132, projection='3d')
X, Y, Z = axes3d.get_test_data(0.05)
cset = ax2.contour(X, Y, Z, extend3d=True, cmap=cm.coolwarm)
ax2.clabel(cset, fontsize=9, inline=1)
ax3 = fig.add_subplot(133, projection='3d')
X, Y, Z = axes3d.get_test_data(0.05)
ax3.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3)
cset = ax3.contour(X, Y, Z, zdir='z', offset=-100, cmap=cm.coolwarm)
cset = ax3.contour(X, Y, Z, zdir='x', offset=-40, cmap=cm.coolwarm)
cset = ax3.contour(X, Y, Z, zdir='y', offset=40, cmap=cm.coolwarm)
ax3.set_xlabel('X')
ax3.set_xlim(-40, 40)
ax3.set_ylabel('Y')
ax3.set_ylim(-40, 40)
ax3.set_zlabel('Z')
ax3.set_zlim(-100, 100)
plt.show()
以上代码创建了三个不同的3D等高线图,运行结果如下图所示。
3D填充等高线图
3D填充等高线图其实就是对3D等高线图进行填充,Matplotlib中使用Axes3D的contourf()方法绘制3D填充等高线。我们针对上述的第一和第三个3D等高线图数据绘制3D填充等高线图。
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
fig = plt.figure(figsize=(11, 5))
ax1 = fig.add_subplot(121, projection='3d')
X, Y, Z = axes3d.get_test_data(0.05)
cset = ax1.contourf(X, Y, Z, cmap=cm.coolwarm)
ax1.clabel(cset, fontsize=9, inline=1)
ax2 = fig.add_subplot(122, projection='3d')
X, Y, Z = axes3d.get_test_data(0.05)
ax2.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3)
cset = ax2.contourf(X, Y, Z, zdir='z', offset=-100, cmap=cm.coolwarm)
cset = ax2.contourf(X, Y, Z, zdir='x', offset=-40, cmap=cm.coolwarm)
cset = ax2.contourf(X, Y, Z, zdir='y', offset=40, cmap=cm.coolwarm)
ax2.set_xlabel('X')
ax2.set_xlim(-40, 40)
ax2.set_ylabel('Y')
ax2.set_ylim(-40, 40)
ax2.set_zlabel('Z')
ax2.set_zlim(-100, 100)
plt.show()
运行结果如下图所示。
多边形图
多边形图顾名思义就是类似多边形的一个图表,Matplotlib中使用Axes3D的add_collection3d()方法绘制
多边形图,基本用法如下。我们在三维坐标系下绘制4个多边形,为便于区别,我们使用4种颜色。
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import PolyCollection
import matplotlib.pyplot as plt
from matplotlib import colors as mcolors
import numpy as np
fig = plt.figure(figsize=(6, 5))
ax = fig.gca(projection='3d')
def cc(arg):
return mcolors.to_rgba(arg, alpha=0.6)
xs = np.arange(0, 10, 0.4)
verts = []
zs = [0.0, 1.0, 2.0, 3.0]
for z in zs:
ys = np.random.rand(len(xs))
ys[0], ys[-1] = 0, 0
verts.append(list(zip(xs, ys)))
poly = PolyCollection(verts, facecolors=[cc('r'), cc('g'), cc('b'),
cc('y')])
poly.set_alpha(0.7)
ax.add_collection3d(poly, zs=zs, zdir='y')
ax.set_xlabel('X')
ax.set_xlim3d(0, 10)
ax.set_ylabel('Y')
ax.set_ylim3d(-1, 4)
ax.set_zlabel('Z')
ax.set_zlim3d(0, 1)
plt.show()
严格来讲,我们绘制的多边形并不是3D图表,只是在3维坐标系下绘制了4个二维多边形。运行结果如下图所示。
3D柱状图
3D柱状图就是在三维坐标系下的柱状图,Matplotlib中使用Axes3D的bar()方法绘制
3D柱状图,常用参数及其含义如下。
left:柱状图左侧的X坐标。
height:柱状图的高度。
zs:z坐标,如果指定了一个值,则它们都将放置在同一个z上。
zdir:在绘制二维集时用作z(“x”、“y”或“z”)的方向。
基本用法如下。
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(6, 5))
ax = fig.add_subplot(111, projection='3d')
for c, z in zip(['r', 'g', 'b', 'y'], [30, 20, 10, 0]):
xs = np.arange(20)
ys = np.random.rand(20)
# You can provide either a single color or an array. To demonstrate this,
# the first bar of each set will be colored cyan.
cs = [c] * len(xs)
cs[0] = 'c'
ax.bar(xs, ys, zs=z, zdir='y', color=cs, alpha=0.8)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()
与多边形图一样,我们绘制的3D柱状图实际上并不是3D图表,只是在3维坐标系下绘制的柱状图。运行结果如下图所示。
3D箭图
3D箭图就是一个箭头的三维区域,Matplotlib中使用Axes3D的quiver()方法绘制箭图
,常用参数及其含义如下。
x,y,z:箭头位置的X、Y和Z坐标(默认为箭头的尾部)。
u,v,w:箭头向量的x、y和z分量。参数可以是数组或标量,也可以是屏蔽数组。如果任何参数中的元素被屏蔽,则不会绘制相应的quiver元素。
length:每个震颤的长度,默认为1.0,单位与轴相同。
arrow_length_ratio:箭头相对于箭袋的比率,默认为0.3。
pivot:位于网格点的箭头部分。箭头围绕该点旋转,因此命名为Pivot。默认为“tail”。
normalize:正则化。如果为True,则所有箭头的长度都相同。默认为False,其中箭头的长度将根据u、v、w值的不同而不同。
基本用法如下,哇满绘制一系列箭头。
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
# Make the grid
x, y, z = np.meshgrid(np.arange(-0.8, 1, 0.2),
np.arange(-0.8, 1, 0.2),
np.arange(-0.8, 1, 0.8))
# Make the direction data for the arrows
u = np.sin(np.pi * x) * np.cos(np.pi * y) * np.cos(np.pi * z)
v = -np.cos(np.pi * x) * np.sin(np.pi * y) * np.cos(np.pi * z)
w = (np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) *
np.sin(np.pi * z))
ax.quiver(x, y, z, u, v, w, length=0.1, normalize=True)
plt.show()
运行结果如下图所示。
3D图中的2D数据
在三维坐标系中,我们可以任取二维展示我们的2D数据。下面我们分别在(x,y)平面下绘制线状图,在(x,z)平面下绘制散点图。
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8, 6))
ax = fig.gca(projection='3d')
# 以x轴、y轴为面绘制线状图
x = np.linspace(0, 1, 100)
y = np.sin(x * 2 * np.pi) / 2 + 0.5
ax.plot(x, y, zs=0, zdir='z', label='(x,y)下的线状图')
# 以x轴、z轴为面绘制散点图
colors = ('r', 'g', 'b', 'k')
x = np.random.sample(20*len(colors))
y = np.random.sample(20*len(colors))
c_list = []
for c in colors:
c_list.extend([c]*20)
ax.scatter(x, y, zs=0, zdir='y', c=c_list, label='(x,z)下的散点图')
ax.legend()
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# Customize the view angle so it's easier to see that the scatter points lie
# on the plane y=0
ax.view_init(elev=20., azim=-35)
plt.show()
运行后结果如下图所示。
3D图表添加文本
和2D图表一样,我们也可以在三维坐标系中添加文本,Matplotlib中使用Axes3D的
text
()方法给3D图表添加文本。text()方法的常用参数和意义如下。
x,y,z:确定文本在三维坐标线中的位置。
s:文本内容。
zdir:设置用作z方向的方向。
此外,还可以使用text2D()方法在三维坐标系所在平面添加文本。下面是绘制文本的基本用法。
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8, 6))
ax = fig.gca(projection='3d')
zdirs = (None, 'x', 'y', 'z', (1, 1, 0), (1, 1, 1))
xs = (1, 4, 4, 9, 4, 1)
ys = (2, 5, 8, 10, 1, 2)
zs = (10, 3, 8, 9, 1, 8)
for zdir, x, y, z in zip(zdirs, xs, ys, zs):
label = '(%d, %d, %d), dir=%s' % (x, y, z, zdir)
ax.text(x, y, z, label, zdir)
ax.text(9, 0, 0, "red", color='red')
# 前两个参数表示位置 (0, 0)在左下方, (1, 1)在右上方
ax.text2D(0.05, 0.95, "2D Text", transform=ax.transAxes)
ax.set_xlim(0, 10)
ax.set_ylim(0, 10)
ax.set_zlim(0, 10)
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')
plt.show()
运行后结果如下图所示。