Matplotlib基本绘图方法

举报
Francek Chen 发表于 2024/11/11 18:39:26 2024/11/11
【摘要】 本文介绍数据可视化包Matplotlib,通过pyplot模块实现常见图像绘制,如散点图、线性图、柱状图、直方图、饼图、箱线图及子图。

一、Matplotlib绘图的基本流程

根据 Matplotlib 图像的4层图像结构,pyplot 模块绘制图形基本都遵循一个流程,使用这个流程可以完成大部分图形的绘制。pyplot 模块基本绘图流程主要分为3个部分,如下图所示。

image.png

  • 创建画布:plt.figure()
  • 创建和选定子图:plt.subplots()
  • 添加标题:plt.title()
  • 添加x/y轴名称:plt.xlabel()、plt.ylabel()
  • 设置x/y轴范围:plt.xlim()、plt.ylim()
  • 设置x/y轴范围:plt.xticks()、plt.yticks()
  • 绘制图形:折线图—plot()、柱状图—bar()、饼图—pie()、散点图—scatter()、箱型图—boxplot()
  • 添加图例:plt.legend()
  • 保存图形:plt.savefig()
  • 显示图形:plt.show()——一般放在最后

在 Jupyter Notebook 中运行时需要加上下面这条魔法命令。

%matplotlib inline  
import numpy as np
import matplotlib.pyplot as plt

(一)最简单的绘图(仅指定y的值)

marker参数观察可知,绘图时使用列表的索引(0、1、2)作为x值,用列表值作为对应的y值(需要取消下一句的注释!)。

plt.plot([1,2,3])
# plt.plot([1,2,3],marker="o")

image.png

(二)更一般的绘图(同时指定x和y的值)

x = np.linspace(-2, 2, 20)    # 产生20个坐标点的横坐标
y = x**2                      # 产生20个坐标点的纵坐标
# 最简单的绘图
plt.rcParams['axes.unicode_minus']= False    # 解决不显示负号的问题
plt.plot(x, y)    # 默认不突出显示坐标点,坐标点之间用蓝色实线连接
plt.show()        # 调用show()函数才真正显示图形

image.png

x = np.linspace(-2, 2, 20)     # 产生20个坐标点的横坐标
y = x**2                       # 产生20个坐标点的纵坐标
px = 0.8                       # 靓点(Beautiful point)之横坐标
py = px**2                     # 靓点之横坐标

plt.title("Square function")   # 图表标题
plt.xlabel("x")                # x轴标签
plt.ylabel("y = x**2")         # y轴标签
plt.grid(True)                 # 显示网格线

plt.plot(x, y, "b*-.", px, py, "ro")    # 同时指定连接线和坐标点的样式、颜色

# 添加文本说明,前两个参数表示第一个字符的横纵坐标,第3个参数是文本字符串。
# 字符串中的 $y=x^2$ 是Latex的等式表示形式
plt.text(0, 2, "Square function\n$y = x^2$", fontsize=20, color='blue', horizontalalignment="center")
plt.text(px - 0.08, py, "Beautiful point", ha="right", weight="heavy")    # ha即horizontalalignment
plt.text(px, py, "x = %0.2f\ny = %0.2f"%(px, py), rotation=50, color='gray')

plt.savefig("my_plot1.png")    # 在当前目录下保存所绘制的图形
plt.show()

image.png

(三)增加更多的绘图元素

x = np.linspace(0,2*np.pi,13)    # 数据点以pi/6(30度)作为分隔间距
y1 = np.sin(x)
y2 = np.cos(x)

plt.plot(x,y1,marker='^',color='r',label="sin(x)")    # 默认线型是实线
plt.plot(x,y2,marker='o',color='g',linestyle='-.',label="cos(x)")   # label参数和plt.legend()配合实现图例显示
plt.xlim(0,2*np.pi)    # 设定x轴的取值范围
plt.ylim(-1,1)
plt.xlabel("x")    # 设定x轴的标签
plt.ylabel("y")
plt.title("y=sin(x)/cos(x)")
# 设定x轴的刻度,下一条语句可以注释对比一下效果,
# 其中x[::3]的3表示经过3个数据点加一个标签,可以改成1看的更明显
plt.xticks(x[::3],["0",r"$\pi/2$",r"$\pi$",r"$3\pi/2$",r"$2\pi$"],color='b')   # "$\pi/2$"属于Latex表示法
plt.grid(axis='x',ls='--')
plt.legend()
plt.show()

image.png

二、布局相关的对象——Figure、Subplot

# 创建自己的Figure对象,相当于自定义画布
#(通过注释下条语句,观察使用自己的Figure对象的效果)
fig = plt.figure(figsize=(12,8))    # 指定画板的宽和高分别为12英寸和8英寸
# 上面语句可省略,如果省略就是使用系统内部默认的figure()对象

# 运行配置(run configuration)参数设置
plt.rcParams['font.sans-serif']=['SimHei']    # 在matplotlib中显示汉字
plt.rcParams['axes.unicode_minus']=False      # 用来正常显示负号,否则负号会显示为小方框

# 绘制子图
x = np.linspace(-2, 2, 30)
plt.subplot(2, 2, 1)    # 2 rows, 2 columns, 1st subplot = top left
plt.plot(x, x)
plt.subplot(2, 2, 2)    # 2 rows, 2 columns, 2nd subplot = top right
plt.plot(x, x**2)
plt.subplot(2, 1, 2)    # 2 rows, *1* column, 2nd subplot = bottom
plt.plot(x, x**3)
plt.text(0,-5,"看成按照2行1列重新划分的第2个子图",ha="center",color="red") # ha:horizontal align(水平对齐)
plt.show()

image.png

三、常用图形绘制

(一)折线图

一般绘制较多的的都是折线图,反映一个特征随另一个特征的趋势变化。

plt.plot()函数的参数及其解释如下:

  • x:x轴数据序列,可以是列表、数组或者其他可迭代对象。如果未提供此参数,将使用默认的索引作为x轴数据。
  • y:y轴数据序列,也可以是列表、数组或者其他可迭代对象。
  • fmt:格式化字符串,用于设置线条的颜色、线型和标记样式。例如,'r–'表示红色虚线,'bo’表示蓝色圆点。该参数可以单独使用,也可以与下面的参数一起使用。
  • linestyle:线型,例如’-‘表示实线,’–‘表示虚线,’:'表示点线。
  • linewidth:线条宽度,可以是一个数字。
  • color:线条颜色,可以是颜色名称(如’red’、‘blue’)或十六进制RGB值(如’#FF5733’)。
  • marker:标记类型,例如’.'表示小圆点,'o’表示大圆点,'s’表示正方形。
  • markersize:标记大小,可以是一个数字。
  • label:线条标签,用于图例的显示。
  • **kwargs:还可以传入其他关键字参数来设置图的属性,如xlabelylabeltitlexlimylimgrid等。
rad = np.arange(0,np.pi*2,0.01)
plt.title("y=sin(x)",fontsize=12)
plt.xlabel("rad",fontsize=12)
plt.ylabel("value",fontsize=12)
plt.xlim((0,np.pi*2))
plt.ylim((-1,1))
plt.xticks([0,np.pi/2,np.pi,np.pi*3/2,np.pi*2])
plt.yticks([-1,-0.5,0,0.5,1])
plt.grid(True)
plt.plot(rad,np.sin(rad))
plt.show()

image.png

# 带子图的折线图
x = np.array([1,2,3])
plt.subplot(221)
plt.plot(x,x,marker="o")
plt.text(1.5,2.6,"y=x",fontsize=12)
plt.subplot(222)
plt.plot(x,-x,"-*r")
plt.text(2.5,-1.3,"y=-x",fontsize=12)
plt.subplot(223)
plt.plot(x,x**2,"-.+g")
plt.text(1.5,6.0,"y=x**2",fontsize=12)
plt.subplot(224)
plt.plot(x,np.sin(x),"--^y")
plt.text(1.5,0.6,"y=sin(x)",fontsize=12)
plt.show()

image.png

(二)柱状图

绘制柱状图,比较值大小。

plt.bar()函数用于绘制柱状图,参数及其解释如下:

  • x:柱状图的x轴位置,一般为类别或者组名,可以是一个数字序列或字符串序列。
  • height:柱状图的高度,即对应x位置上的数值,可以是一个数字序列。
  • width:柱状图的宽度,默认为0.8。
  • bottom:柱状图底部的位置,在堆叠柱状图中使用,表示下方柱状图的顶部位置。
  • align:控制柱状图的对齐方式,可选值包括’center’(居中,默认值)、‘edge’(以x为边缘对齐)。
  • color:柱状图的颜色,可以是单个颜色或颜色序列。
  • edgecolor:柱状图边缘的颜色。
  • linewidth:柱状图边缘的宽度。
  • tick_label:指定每个柱状图的标签,一般用于指定x轴刻度的标签。
  • xerr:用于绘制误差条的水平误差。
  • yerr:用于绘制误差条的垂直误差。
  • ecolor:误差条的颜色。
  • capsize:误差条顶端和底端的线条长度。
  • error_kw:控制误差条的属性,如线型、线宽等。
  • log:在y轴上使用对数刻度。
  • orientation:柱状图的方向,'vertical’表示垂直柱状图,'horizontal’表示水平柱状图。
  • label:柱状图的标签,用于图例的显示。
position = np.arange(5)    # 确定每个柱的垂直中线位置,相当于x轴坐标
data1 = [2,10,4,8,6]       # 确定每个柱的高度,相当于y轴坐标
data2 = np.random.randint(1,9,5)#[5,3,6,7,6]
plt.bar(position,data1)
plt.bar(position,-data2)

for x, y in zip(position, data1):    # 显示数据标签
    plt.text(x, y, '{}'.format(y), ha='center', va='bottom',fontsize=11,color='r')
    # va='bottom'表示文本的底部在(x,y)处,还可以取top和center值
for x, y in zip(position, data2):    # 显示数据标签
    plt.text(x, -y, '{}'.format(y), ha='center', va='top',fontsize=11,color='r')
plt.show()

image.png

(三)直方图

绘制直方图,反映数据分布。

plt.hist()用于绘制直方图。该函数的常用参数及解释如下:

  • x: 是要绘制直方图的数据。可以是一维数组、列表或Series对象。
  • bins: 指定直方图的柱形数量或给定的划分方式。可以是一个整数,表示要绘制的柱形数量;也可以是一个列表或数组,表示每个柱形的边界值。
  • range: 指定直方图的取值范围,以元组形式表示,例如range=(0, 10)表示只绘制取值在0到10之间的数据的直方图。
  • density: 是否将直方图的纵轴设置为频率而非计数。当density=True时,纵轴表示相应区间内的频率,使得直方图的面积总和为1。
  • cumulative: 是否绘制累积分布图。当cumulative=True时,每个柱形的高度表示小于等于该柱形右侧边界值的数据点的数量累积和。
  • histtype: 指定直方图的类型。可选值有 ‘bar’(默认)、‘barstacked’、‘step’、‘stepfilled’。‘bar’ 表示普通的柱形直方图,‘barstacked’ 表示堆叠的柱形直方图,‘step’ 表示阶梯状直方图,‘stepfilled’ 表示填充的阶梯状直方图。
  • align: 指定柱形的对齐方式。可选值有 ‘left’(默认)、‘mid’、‘right’。‘left’ 表示柱形左侧与给定边界对齐,‘mid’ 表示柱形中间与给定边界对齐,‘right’ 表示柱形右侧与给定边界对齐。
  • color: 指定柱形的颜色。可以是单个颜色字符串,也可以是颜色字符串的列表或数组,用于指定每个柱形的颜色。
  • edgecolor: 指定柱形的边框颜色。
  • linewidth: 指定柱形的边框线宽度。
  • alpha: 指定柱形的透明度。
  • log: 是否绘制对数坐标的直方图。
  • label: 指定直方图的标签,用于图例显示。
x = [22,87,5,43,56,73,55,54,11,20,51,5,79,31,27]	# x轴数据
plt.hist(x, bins = [0,25,50,75,100])				# 绘制直方图,bins为区间
plt.show()										    # 显示图表

image.png

进一步拓展。

df = pd.read_excel('grade1.xls')		# 读取Excel文件
plt.rcParams['font.sans-serif']=['SimHei']			# 解决中文乱码
x = df['得分']										# x轴数据
plt.xlabel('分数')									# x轴标题
plt.ylabel('学生数量')								# y轴标题
plt.title("高一数学成绩分布直方图")					# 设置图表标题
# 绘制直方图,bins为区间,facecolor为前景色,edgecolor为边框颜色,alpha为透明度
plt.hist(x, bins = [0,25,50,75,100,125,150],facecolor="blue", edgecolor="black", alpha=0.7)
plt.show()										# 显示图表

image.png

(四)饼图

绘制饼图,展示整体的构成情况。

plt.pie()函数用于绘制饼图,其常用参数及解释如下:

  • x:指定绘制饼图的数据,可以是一个数组或者列表,表示每个扇形的大小。
  • explode:指定是否要突出显示某些扇形,可以是一个数组或者列表,其中每个元素表示是否要突出显示对应位置的扇形。
  • labels:指定每个扇形的标签,可以是一个数组或者列表,用于标记每个扇形所代表的含义。
  • colors:指定每个扇形的颜色,可以是一个数组或者列表,用于设置每个扇形的颜色。
  • autopct:指定扇形上的文本标签显示格式,可以是一个格式化字符串,例如"%1.1f%%",表示以百分比的格式显示数值。
  • shadow:指定是否绘制阴影效果,True表示绘制阴影,False表示不绘制,默认为False。
  • startangle:指定饼图的起始角度,0表示从3点钟方向开始,逆时针旋转。
  • radius:指定饼图的半径大小,默认为1。
  • counterclock:指定绘制饼图的方向,True表示逆时针绘制,False表示顺时针绘制,默认为True。
  • wedgeprops:指定扇形的属性,可以是一个字典,用于设置扇形的样式,如颜色、边界宽度等。
  • textprops:指定文本标签的属性,可以是一个字典,用于设置文本标签的样式,如字体大小、颜色等。
  • center:指定饼图的中心位置坐标,默认为(0, 0)。
  • frame:指定是否绘制饼图的图框,True表示绘制,False表示不绘制,默认为False。
x = [2,4,6,8]

labels = ['a','b','c','d']    # 各部分的标签
colors = ['r','y','b','g']    # 各部分的颜色

explode = (0,0.1,0,0)    # explode用于突出显示特定的部分
# explode=(0.1,0.3,0.1,0.1) 

plt.pie(x,explode=explode,labels=labels,colors=colors,autopct='%.1f%%')  # pct表示percent,%%用于输出一个百分号
plt.axis("equal")    ##使饼图两个轴的单位长度相等,从而使得饼图接近圆形
plt.show()

image.png

(五)散点图

绘制散点图,展示数据聚集模式、观察两个一维数据序列间的关系。

plt.scatter()函数用于绘制散点图,其常用参数及解释如下:

  • x:指定散点图中点的x轴数据,可以是一个数组或者列表。
  • y:指定散点图中点的y轴数据,可以是一个数组或者列表。
  • s:指定散点的大小,可以是一个标量,也可以是与x和y相同长度的数组,用于指定每个点的大小。
  • c:指定散点的颜色,可以是一个颜色或者颜色序列,用于指定每个点的颜色。
  • marker:指定散点的形状,可以是一个字符,例如’x’、‘o’、’+’、’*'等。
  • cmap:指定颜色映射,如果c是一个浮点数数组,并且没有指定cmap,则默认使用viridis颜色映射。
  • alpha:指定散点的透明度,0表示完全透明,1表示完全不透明。
  • linewidths:指定散点边界的宽度,可以是一个标量或者与x和y相同长度的数组。
  • edgecolors:指定散点边界的颜色,可以是一个颜色或者颜色序列,用于指定每个点边界的颜色。
  • label:指定散点图的标签,用于图例显示。
  • zorder:指定散点图绘制的层次顺序,值越大表示绘制在更上层。
# 基本的常用于线性回归分析中
np.random.seed(0)   # 作用相当于random.seed(),但它返回一个伪随机数生成器对象,可用该对象生成随机数
x = np.linspace(0,1,100)
y = x+np.random.randn(100)
plt.scatter(x,y)
plt.plot(x,x)
plt.show()

image.png

rd = np.random.RandomState(0)   # 作用相当于random.seed(),但它返回一个伪随机数生成器对象,可用该对象生成随机数
x = rd.randn(100)
y = rd.randn(100)

colors = rd.rand(100)
sizes = 1000*rd.rand(100)
# 画散点图最重要的5个参数:x-横坐标,y-纵坐标,c-颜色(要求是0~1范围内的浮点值),s-点大小(像素),alpha-透明度
# 当颜色和尺寸使用数组时,常用来表示不同的类别;cmap用来指定颜色的风格,viridis表示翠绿色
plt.scatter(x,y,c=colors,s=sizes,alpha=0.3,cmap='viridis')
plt.colorbar()    # 显示颜色条
plt.show()

image.png

(六)箱线图

使用箱线图,常用于检测与处理异常值。

import pandas as pd
import matplotlib.pyplot as plt

数据集meal_order_detail.xlsx下载地址:
链接:https://pan.quark.cn/s/7dfb546c8cc4
提取码:cBn3

data = pd.read_excel('meal_order_detail.xlsx')
data.head()

image.png

完整数据框如下:

detail_id order_id dishes_id logicprn_name parent_class_name dishes_name itemis_add counts amounts cost place_order_time discount_amt discount_reason kick_back add_inprice add_info bar_code picture_file emp_id
0 2956 417 610062 NaN NaN 蒜蓉生蚝 0 1 49 NaN 2016-08-01 11:05:00 NaN NaN NaN 0 NaN NaN caipu/104001.jpg 1442
1 2958 417 609957 NaN NaN 蒙古烤羊腿 0 1 48 NaN 2016-08-01 11:07:00 NaN NaN NaN 0 NaN NaN caipu/202003.jpg 1442
2 2961 417 609950 NaN NaN 大蒜苋菜 0 1 30 NaN 2016-08-01 11:07:00 NaN NaN NaN 0 NaN NaN caipu/303001.jpg 1442
3 2966 417 610038 NaN NaN 芝麻烤紫菜 0 1 25 NaN 2016-08-01 11:11:00 NaN NaN NaN 0 NaN NaN caipu/105002.jpg 1442
4 2968 417 610003 NaN NaN 蒜香包 0 1 13 NaN 2016-08-01 11:11:00 NaN NaN NaN 0 NaN NaN caipu/503002.jpg 1442

plt.boxplot()函数用于绘制箱线图,其常用参数及解释如下:

  • x:指定绘制箱线图的数据,可以是一个数组或者列表,表示每个箱线图的数据。
  • notch:指定是否绘制盒形图的缺口,True表示绘制缺口,False表示不绘制,默认为False。
  • sym:指定异常值的标记符号,可以是一个字符,例如’+’、'o’等。
  • vert:指定箱线图的方向,True表示纵向绘制,False表示横向绘制,默认为True。
  • widths:指定箱线图的宽度,可以是一个标量或者与x相同长度的数组。
  • patch_artist:指定是否使用Patch对象来绘制箱线图,默认为False。
  • labels:指定每个箱线图的标签,可以是一个数组或者列表,用于标记每个箱线图所代表的含义。
  • showmeans:指定是否显示均值,True表示显示均值,False表示不显示,默认为False。
  • meanline:指定是否显示均值的线段,True表示显示,False表示不显示,默认为False。
  • whiskerprops:指定须线的属性,可以是一个字典,用于设置须线的样式,如颜色、线型等。
  • medianprops:指定中位数线的属性,可以是一个字典,用于设置中位数线的样式,如颜色、线型等。
  • flierprops:指定异常值的属性,可以是一个字典,用于设置异常值的样式,如颜色、标记符号等。
  • boxprops:指定箱体的属性,可以是一个字典,用于设置箱体的样式,如颜色、填充等。
  • capprops:指定顶端和底端的界限线的属性,可以是一个字典,用于设置界限线的样式,如颜色、线型等。
  • whiskers:指定须的长度,可以是一个标量或者数组,用于设置须的长度。
  • caps:指定顶端和底端的界限线的长度,可以是一个标量或者数组,用于设置界限线的长度。
  • showfliers:指定是否显示异常值,True表示显示异常值,False表示不显示,默认为True。
  • bootstrap:指定是否使用自助法计算置信区间,可以是一个整数,表示自助采样的次数,默认为None。
  • usermedians:指定中位数的位置,可以是一个数组或者列表,用于指定每个箱线图的中位数位置。
  • conf_intervals:指定置信区间的范围,可以是一个数组或者列表,用于指定每个箱线图的置信区间。
plt.boxplot(data['amounts'])
# plt.boxplot(data['amounts'],vert=False)     # vert=False设置水平显示箱形图
plt.show()

image.png

检测与处理异常值

箱型图提供了识别异常值的一个标准,即异常值通常被定义为小于 QL-1.5IQR 或大于 QU+1.5IQR 的值。

  • QL称为下四分位数,表示全部观察值中有四分之一的数据取值比它小。
  • QU称为上四分位数,表示全部观察值中有四分之一的数据取值比它大。
  • IQR称为四分位数间距,是上四分位数QU与下四分位数QL之差,其间包含了全部观察值的一半。

箱线图依据实际数据绘制,真实、直观地表现出了数据分布的本来面貌,且没有对数据做任何限制性要求,其判断异常值的标准以四分位数和四分位数间距为基础。

四分位数给出了数据分布的中心、散布和形状的某种指示,具有一定的鲁棒性,即25%的数据可以变得任意远而不会很大地扰动四分位数,所以异常值通常不能对这个标准施加影响。鉴于此,箱线图识别异常值的结果比较客观,因此在识别异常值方面具有一定的优越性。

3σ3\sigma 原则又称为拉依达法则。该法则就是先假设一组检测数据只含有随机误差,对原始数据进行计算处理得到标准差,然后按一定的概率确定一个区间,认为误差超过这个区间的就属于异常值。

这种判别处理方法仅适用于对正态或近似正态分布的样本数据进行处理,如下表所示,其中 σ\sigma 代表标准差,μ\mu 代表均值,x=μx=\mu 为图形的对称轴。数据的数值分布几乎全部集中在区间 (μ3,μ+3)(\mu-3,\mu+3) 内,超出这个范围的数据仅占不到 0.3%0.3\%。故根据小概率原理,可以认为超出 3σ3\sigma 的部分数据为异常数据。

image.png

# 自定义函数用于将数据中的异常值替换为缺失值
def replace(x):
    import numpy as np
    QU = x.quantile(0.75)
    QL = x.quantile(0.25)
    IQR = QU -QL
    x[(x > (QU + 1.5*IQR)) | (x < (QL - 1.5*IQR))] = np.nan
    return x
data['amounts'].isnull().sum()
0
replace(data['amounts']).isnull().sum()
C:\Users\Administrator\Anaconda3\lib\site-packages\ipykernel_launcher.py:7: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  import sys





173
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。