matplotlib:python数据处理三剑客之一

1.基本使用

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# 生成一系列x
x = np.linspace(-1, 1, 50)
# 生成对应的y
y1 = 2 * x +1
y2 = x ** 2
# 传入对应的x和y,调用plot方法,绘制图像
# plot会将所有的点连起来
plt.plot(x, y1)
plt.plot(x, y2)
plt.show()

2.调整图像大小

x = np.linspace(-1, 1, 50)
y1 = 2 * x +1
y2 = x ** 2
# 图像是画在画布上面的
plt.figure(figsize=(8, 5))
plt.plot(x, y1)
plt.plot(x, y2)
plt.show()

3.绘制基本图形(折线图)

3.1 基本绘制

x = np.linspace(-1, 1, 50)
y1 = 2 * x +1
y2 = x ** 2
plt.figure(figsize=(8, 5))
# 其实之前介绍过了,就是使用plot方法即可
plt.plot(x, y1)
plt.plot(x, y2)
plt.show()

3.2 设置样式

x = np.linspace(-1, 1, 50)
y1 = 2 * x +1
y2 = x ** 2
plt.figure(figsize=(8, 5))

# linestyle:表示线段的样式
# color:表示颜色
# marker:表示点的样式
plt.plot(x, y1, linestyle="-", color="cyan", marker="o")
plt.plot(x, y2, linestyle="--", color="red", marker="<")
plt.show()

关于样式:

  • linestyle

    '-' solid line style
    '--' dashed line style
    '-.' dash-dot line style
    ':' dotted line style
    
  • marker

    '.'       point marker
    ','       pixel marker
    'o'       circle marker
    'v'       triangle_down marker
    '^'       triangle_up marker
    '<'       triangle_left marker
    '>'       triangle_right marker
    '1'       tri_down marker
    '2'       tri_up marker
    '3'       tri_left marker
    '4'       tri_right marker
    's'       square marker
    'p'       pentagon marker
    '*'       star marker
    'h'       hexagon1 marker
    'H'       hexagon2 marker
    '+'       plus marker
    'x'       x marker
    'D'       diamond marker
    'd'       thin_diamond marker
    '|'       vline marker
    '_'       hline marker
    

4.设置坐标轴

4.1 设置坐标轴范围和描述

# 将x修改一下, 改成-10到10
x = np.linspace(-10, 10, 50)
y1 = 2 * x +1
y2 = x ** 2
plt.figure(figsize=(8, 5))

plt.plot(x, y1, linestyle="-", color="cyan", marker="o")
plt.plot(x, y2, linestyle="--", color="red", marker="<")

plt.xlim([-5, 5])  # 设置x坐标轴的范围是-5到5
plt.ylim([-10, 20])  # 设置y坐标轴的范围是-10到20
# 调整坐标轴范围还可以使用plt.axis([-5, 5, -10, 20])这种形式
plt.xlabel("i am x axis")  # 设置x轴描述
plt.ylabel("i am y axis")  # 设置y轴描述
plt.show()

4.2 设置坐标轴刻度

x = np.linspace(-10, 10, 50)
y1 = 2 * x +1
y2 = x ** 2
plt.figure(figsize=(8, 5))

plt.plot(x, y1, linestyle="-", color="cyan", marker="o")
plt.plot(x, y2, linestyle="--", color="red", marker="<")

plt.xlim([-5, 5])  
plt.ylim([-10, 20])  
plt.xlabel("i am x axis")  
plt.ylabel("i am y axis")  

# 坐标轴属性可以通过gca = plt.gca()获取
# 然后通过gca.属性去调节
# 但是对于坐标轴刻度的话,和坐标轴范围一样,是可以直接通过plt来调节的
plt.locator_params(nbins=20)  # 表示将轴分成20份
# 如果只想对某一个轴,比如x轴去调节的话,可以通过plt.locator_params("x", nbins=20)

plt.show()
# 怎么样,是不是变密了呢?

4.3 设置坐标轴倾斜角度以及曲线标记

我们注意到x轴的刻度虽然多了,但是快连在一起,我们可不可以让其歪一些呢?这样就不会连接一起了,而且图上面有两个曲线,我们可不可以给每个曲线做个标记呢?

x = np.linspace(-10, 10, 50)
y1 = 2 * x +1
y2 = x ** 2
plt.figure(figsize=(8, 5))

# 做标记的话,只需要加上一个label参数即可
plt.plot(x, y1, linestyle="-", color="cyan", marker="o", label="2 * x + 1")
plt.plot(x, y2, linestyle="--", color="red", marker="<", label="x ** 2")

plt.xlim([-5, 5])  
plt.ylim([-10, 20])  
plt.xlabel("i am x axis")  
plt.ylabel("i am y axis")  
plt.locator_params(nbins=20)  

# 通过plt.xticks调整x轴刻度,同理y轴的话就是yticks
plt.xticks(rotation=60)  # 倾斜60度

# 这一步是为了让plot中设置的label显示出来,没有这一句是不会显示的
# 而且会自动帮我们找到一个合适的位置
plt.legend() # 还可以加上一个loc='best',会寻找最好的位置,这里没有加,位置也是不错的
plt.show()

4.4 设置网格

背景光秃秃的,不是很好看,我们也可以设置一些网格

x = np.linspace(-10, 10, 50)
y1 = 2 * x +1
y2 = x ** 2
plt.figure(figsize=(8, 5))
plt.plot(x, y1, linestyle="-", color="cyan", marker="o", label="2 * x + 1")
plt.plot(x, y2, linestyle="--", color="red", marker="<", label="x ** 2")

plt.xlim([-5, 5])  
plt.ylim([-10, 20])  
plt.xlabel("i am x axis")  
plt.ylabel("i am y axis")  
plt.locator_params(nbins=20)  
plt.xticks(rotation=60) 
plt.legend() 

# 设置网格
plt.grid(color="pink")  # 此外plt.title("title")还可以设置标题
plt.show()

可以看到,需要什么样式,直接设置即可,会叠加在一起。我们这里的plot是折线图,而这些样式、属性啊在其他大部分图形上都是通用的

4.5 自定义坐标轴

x = np.linspace(-10, 10, 50)
y1 = 2 * x +1
y2 = x ** 2
plt.figure(figsize=(8, 5))
plt.plot(x, y1, linestyle="-", color="cyan", marker="o", label="2 * x + 1")
plt.plot(x, y2, linestyle="--", color="red", marker="<", label="x ** 2")

plt.xlim([-5, 5])  
plt.ylim([-10, 20])  
plt.xlabel("i am x axis")  
plt.ylabel("i am y axis")  
plt.locator_params(nbins=20)  
plt.xticks(rotation=60) 
# 将2 4 6 8换成对应的英文
plt.yticks([2, 4, 6, 8], ["two", "four", "six", "eight"])
plt.legend() 

plt.grid(color="green")
plt.show()

但是这样其他的刻度就没了,因此我们只能手动调整。

x = np.linspace(-10, 10, 50)
y1 = 2 * x +1
y2 = x ** 2
plt.figure(figsize=(8, 5))
plt.plot(x, y1, linestyle="-", color="cyan", marker="o", label="2 * x + 1")
plt.plot(x, y2, linestyle="--", color="red", marker="<", label="x ** 2")

plt.xlim([-5, 5])  
plt.ylim([-10, 20])  
plt.xlabel("i am x axis")  
plt.ylabel("i am y axis")  
plt.locator_params(nbins=20)  
plt.xticks(rotation=60) 

# 将坐标轴替换
y_axis = list(range(-10, 20, 2))
new_y_axis = list(map(lambda x: "two" if x == 2 else "four" if x == 4 else "six" if x == 6 else "eight" if x == 8 else x, y_axis))
plt.yticks(y_axis, new_y_axis)
plt.legend() 

plt.grid(color="green")
plt.show()

4.6 设置边框属性

我们发现目前的图形是一个矩形,也就是有四条线,如果我们想只有左边和下边的线呢?

x = np.linspace(-10, 10, 50)
y1 = 2 * x +1
y2 = x ** 2
plt.figure(figsize=(8, 5))
plt.plot(x, y1, linestyle="-", color="cyan", marker="o", label="2 * x + 1")
plt.plot(x, y2, linestyle="--", color="red", marker="<", label="x ** 2")

plt.xlim([-5, 5])  
plt.ylim([-10, 20])  
plt.xlabel("i am x axis")  
plt.ylabel("i am y axis")  
plt.locator_params(nbins=20)  
plt.xticks(rotation=60) 
plt.legend() 

# 获取坐标轴
gca = plt.gca()  # get current axis
# gca.spines拿到四个坐标轴,left、right、top、bottom,将上边和右边的坐标轴的颜色设置为none,隐藏起来即可
gca.spines["right"].set_color("none")  
gca.spines["top"].set_color("none")  
# 将左边和下边的颜色设置成粉色和绿色,显眼一点
gca.spines["left"].set_color("pink")
gca.spines["bottom"].set_color("green")
plt.show()

4.7 调整移动坐标轴

目前坐标轴不是我们上学学的那种二维直角坐标系,怎么变成那种坐标系呢?

x = np.linspace(-10, 10, 50)
y1 = 2 * x +1
y2 = x ** 2
plt.figure(figsize=(8, 5))
plt.plot(x, y1, linestyle="-", color="cyan", marker="o", label="2 * x + 1")
plt.plot(x, y2, linestyle="--", color="red", marker="<", label="x ** 2")

plt.xlim([-5, 5])  
plt.ylim([-10, 20])  
plt.xlabel("i am x axis")  
plt.ylabel("i am y axis")  
plt.locator_params(nbins=20)  
plt.xticks(rotation=60) 
plt.legend() 

gca = plt.gca()  # get current axis
gca.spines["right"].set_color("none")  
gca.spines["top"].set_color("none")  
gca.spines["left"].set_color("pink")
gca.spines["bottom"].set_color("green")

# 写法比较固定,将下边的左边的轴的位置设置为('data', 0)
gca.spines['bottom'].set_position(('data', 0))
gca.spines['left'].set_position(('data',0))

plt.show()

可以看到,坐标轴移动了。但是这样有一个缺陷,那就是坐标轴的描述还处在原来的位置,和坐标轴以及刻度重叠了

x = np.linspace(-10, 10, 50)
y1 = 2 * x +1
y2 = x ** 2
plt.figure(figsize=(8, 5))
plt.plot(x, y1, linestyle="-", color="cyan", marker="o", label="2 * x + 1")
plt.plot(x, y2, linestyle="--", color="red", marker="<", label="x ** 2")

plt.xlim([-5, 5])  
plt.ylim([-10, 20])  
plt.xlabel("i am x axis")  
plt.ylabel("i am y axis")  
plt.locator_params(nbins=20)  
plt.xticks(rotation=60) 
plt.legend() 

gca = plt.gca()  # get current axis
gca.spines["right"].set_color("none")  
gca.spines["top"].set_color("none")  
gca.spines["left"].set_color("pink")
gca.spines["bottom"].set_color("green")

gca.spines['bottom'].set_position(('data', 0))
gca.spines['left'].set_position(('data',0))

# 将x轴刻度设置为上方
# y轴刻度设置为右方
gca.xaxis.set_ticks_position("top")
gca.yaxis.set_ticks_position("right")

plt.show()

感觉这样好白痴啊,不过无所谓,知道有这么个语法就可以了,也不常用

4.8 添加注释

x = np.arange(-10, 11)
y = x ** 2
plt.plot(x, y)
plt.annotate("my name is satori",
            xy=(0, 5),  # 箭头坐标
            xytext=(0, 20),  # 文本坐标
            arrowprops={
                "facecolor": "red",  # 颜色
                "headlength": 10,  # 箭头长度
                "headwidth": 30,  # 箭头的头的宽度,
                "width": 20  # 箭头的身体的宽度
            })
plt.show()

5.绘制基本图形(散点图)

x = np.random.normal(0, 1, 1024)
y = np.random.normal(0, 1, 1024)
# 散点图使用scatter函数,半藏的散
plt.scatter(x, y)
plt.show()

当然散点图也可以指定样式

plt.figure(figsize=(10, 8))
x = np.random.normal(0, 1, 100)
y = np.random.normal(0, 1, 100)

# s:点的大小
# color:颜色,不指定默认为蓝色
# marker:形状,不指定默认为点。marker和plot里面的marker是一样的
# alpha:透明度,不指定默认为1
plt.scatter(x, y, s=75, color="green", marker="<", alpha=0.2)
plt.show()

关于颜色的问题,其实还有一个参数c,这个c是一个数组。举个例子吧,plt.scatter([1, 2, 3, 4], [2, 4, 6, 8], c=[0, 1, 1, 0]),首先x和y组合会形成四个点,坐标分别是(1, 2), (2, 4), (3, 6), (4, 8),而c是与之等长的数组,c是[0, 1, 1, 0],那么按照索引对应,如果对应c中是0的都是一个颜色,对应到1的都是一个颜色。我们在机器学习,对样本进行聚类的时候,就可以将样本标签(label)做为c,这样的话,不同的样本特征就会对应不同的颜色,这样通过颜色我们可以看出聚类的效果好不好。

plt.figure(figsize=(10, 8))
# x和y都是-10到10
x = np.random.randint(-10, 10, 100)
y = np.random.randint(-10, 10, 100)
c = []
for v in zip(x, y):
    # 如果x+y<0,我们分类为0
    # 如果0<=x+y<10,我们分类为1
    # 如果10<=x+y<20,我们分类为2
    if sum(v) < 0:
        c.append(0)
    elif sum(v) < 10:
        c.append(1)
    else:
        c.append(2)
        
plt.scatter(x, y, c=c)
plt.show()

可以看出紫色的点是两个坐标之和小于0的,绿色的则是坐标之和位于0到10的,黄色的是坐标之和位于10到20的。

plt.figure(figsize=(10, 8))
# x和y都是-10到10
x = np.random.normal(-1, 1, 1000)
y = np.random.normal(-1, 1, 1000)
c = np.arctan2(y, x)

plt.axis([-1.5, 1.5, -1.5, 1.5])
gca = plt.gca()
gca.spines["left"].set_color("none")
gca.spines["right"].set_color("none")
gca.spines["top"].set_color("none")
gca.spines["bottom"].set_color("none")
# 如果xticks或者yticks里面传入一个空元祖或者空列表的话表示隐藏掉坐标轴
plt.xticks(())
plt.yticks([])

plt.scatter(x, y, s=100, c=c, alpha=0.5)
plt.show()

6.绘制基本图形(条形图)

plt.figure(figsize=(10, 8))
# 还记得每一个图对应的每一个函数吗?
# 散点图:scatter
# 折线图:plot
# 条形图:bar

# 这个函数可以只接收两个参数,分别是条形图中每一条的索引和高度
plt.bar(x=[0, 1, 2, 3, 4, 5], height=[11, 22, 33, 44, 55, 66])
plt.show()

当然也可以指定样式

plt.figure(figsize=(10, 8))

# facecolor:条形图内部填充色
# edgecolor:条形图边框颜色
# width:宽度
plt.bar(x=[0, 1, 2, 3, 4, 5], height=[11, 22, 33, 44, 55, 66],
        edgecolor="blue",
        color="green",
        width=0.2)
plt.show()

绘制多个条形图

plt.figure(figsize=(10, 8))
X =[0, 1, 2, 3, 4, 5]
height1 = [11, 22, 33, 44, 55, 66]
height2 = [-11, -22, -33, -44, -55, -66]
plt.bar(X,height1,
        edgecolor="blue",
        color="green",
        width=0.2)

plt.bar(X, height2,
        edgecolor="pink",
        color="red",
        width=0.2)

# 但是这样不够用美观,我们可以把轴隐藏掉
# 对应值标记在对应条形图的上下方
for x, y in zip(X, height1):
    # x, y表示坐标,我们上移一点,那么x保持不变,y增大一点
    # 第三个y则表示的是对应值
    # ha表示横向,v表示纵向,center是居中,bottom向下对其
    plt.text(x, y+0.1, y, ha="center", va="bottom")
    
for x, y in zip(X, height2):
    # 这里的y要减少一点,因为向下的条形图部分
    plt.text(x, y-0.1, y, ha="center", va="top")
    
plt.show()

7.绘制基本图形(等高线图)

n=256
x=np.linspace(-3,3,n)
y=np.linspace(-3,3,n)
X,Y=np.meshgrid(x,y)

#f函数用来计算高度值 
def f(x,y):
    return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)

# 利用contour函数把颜色加进去 位置参数依次为X,Y,f(X,Y),8, 透明度为0.75,并将f(X,Y)的值对应到camp之中
plt.contourf(X,Y,f(X,Y),8,alpha=0.75,cmap=plt.cm.hot)# 8表示等高线分成多少份 alpha表示透明度 cmap表示color map
#使用plt.contour函数进行等高线绘制 参数依次为x,y,f(x,y),颜色选择黑色,线条宽度为0.5
C=plt.contour(X,Y,f(X,Y),8,colors='black',linewidth=0.5)
#使用plt.clabel添加高度数值 inline控制是否将label画在线里面,字体大小为10
plt.clabel(C,inline=True,fontsize=10)
plt.xticks(())#隐藏坐标轴
plt.yticks(())
plt.show()

8.绘制基本图形(直方图)

mu = 100
sigma = 20
x = mu + sigma * np.random.randn(2000)

# 设置直方图
# bins:表示要分成多少个区间
# normed:表示是否进行标准化,标准化之后,阿么纵坐标不在是个数,而是频率
plt.hist(x, bins=30, color="green", density=True)
plt.show()

9.绘制基本图形(双变量直方图)

x = np.random.randn(1000)+2
y = np.random.randn(1000)+3
 
 
plt.hist2d(x, y, bins=40)
 
plt.show()

10.基本图形绘制(饼图)

labels = ["satori", "mashiro", "nagisa"]
fracs = [40, 30, 30]
 
# 最重要的两个参数
# x:所占的份额
# labels:对应的标签
plt.pie(x=fracs, labels=labels)
plt.show()

也可以指定样式

labels = ["satori", "mashiro", "nagisa"]
fracs = [40, 30, 30]
 
# autopct:表示每一块的比例
# explode:突出显示,每个部分不会贴在一块
# shadow:加上一层阴影,指定为True即可
plt.pie(x=fracs, labels=labels, autopct="%.0f%%", explode=[0.01, 0.2, 0.1], shadow=True)
plt.show()

11.基本图形绘制(箱型图)

np.random.seed(100)
data = np.random.normal(0, 1, size=1000)

# sym:形状,表示异常值的形状
# whis:表示虚线的长度,可以控制异常值显示的多少,越大虚线越长
plt.boxplot(data, sym="<", whis=1.5)
plt.show()

12.3D图形绘制(不常用)

from mpl_toolkits.mplot3d import Axes3D as A3
fig = plt.figure(figsize=(10, 8))
ax = A3(fig) 
x = np.arange(-4, 4, 0.2)
y = np.arange(-4, 4, 0.2)
x, y = np.meshgrid(x, y)
z = np.power(x, 2) + np.power(y, 2)
plt.title("satori")

# rstride,cstride表示行列每隔多少个点建一个面,cmap表示颜色
ax.plot_surface(x, y, z, rstride=1,
                cstride=1,
                cmap=plt.cm.CMRmap,
                alpha=0.4)
ax.set_xlabel('x_label', color='r')
ax.set_ylabel('y_label', color='g')
ax.set_zlabel('z_label', color='b')
 
plt.show()

13.多图绘制

规则排列

方法一:

x = np.arange(1, 100, 5)
 
# 生成一个画布
fig = plt.figure(figsize=(10, 8))
 
# 往画布上添加对象
# 这里的221表示,将画布分成2X2份,并处于第一个位置
# 222则是第二个位置,注意是先从左往右,再从上往下
s1 = fig.add_subplot(221)
s2 = fig.add_subplot(222)
s3 = fig.add_subplot(223)
s4 = fig.add_subplot(224)
y1 = np.log(x)
y2 = np.sin(x)
y3 = np.cos(x)
y4 = x ** 2

# 这里不再使用plt.plot,而是使用s
s1.plot(x, y1, color="green", marker="x", linestyle="--")
s2.plot(x, y2, color="blue", marker="o", linestyle="-.")
s3.plot(x, y3, color="cyan", marker="<", linestyle="--")
s4.plot(x, y4, color="yellow", marker=">", linestyle="-.")
plt.show()

方法二:

import numpy as np
import matplotlib.pyplot as plt
 
x = np.arange(1, 100, 5)

plt.figure(figsize=(10, 8))
# 这里可以直接使用plt.subplot
plt.subplot(221)
plt.plot(x, np.log(x))
plt.subplot(222)
plt.plot(x, np.sin(x))
plt.subplot(223)
plt.plot(x, np.cos(x))
plt.subplot(224)
plt.plot(x, x**2)
 
plt.show()

这里没有设置样式,但是基本上是一样的。

不规则排列

x = np.arange(1, 100, 5)
 
# 生成一个画布
fig = plt.figure(figsize=(10, 8))


# 分成3行3列
"""
1 2 3
4 5 6
7 8 9
"""
s1 = fig.add_subplot(331)
s2 = fig.add_subplot(335)
s3 = fig.add_subplot(337)
s4 = fig.add_subplot(339)
y1 = np.log(x)
y2 = np.sin(x)
y3 = np.cos(x)
y4 = x ** 2

# 这里不再使用plt.plot,而是使用s
s1.plot(x, y1, color="green", marker="x", linestyle="--")
s2.plot(x, y2, color="blue", marker="o", linestyle="-.")
s3.plot(x, y3, color="cyan", marker="<", linestyle="--")
s4.plot(x, y4, color="yellow", marker=">", linestyle="-.")
plt.show()

这样尽管不规则,但是一张图还是只占据一份的面积,比如第一张图,如果我想让其填满其所在的一整行,该怎么办呢?

x = np.arange(1, 100, 5)
 
# 生成一个画布
fig = plt.figure(figsize=(10, 8))

# 先计算好,我要分为几行显示
# 比如第一张图显示第一行,填满
# 第二张和第三张显示在第二行
# 第四张显示在第三行,填满

# 先分成3行1列,选择311,会把第一行占满
s1 = fig.add_subplot(311)  
s2 = fig.add_subplot(323)  # 由于第一张图把第一张占满了,那么3X2的基础上相当于1和2被占了,所以这里是323
s3 = fig.add_subplot(324)
s4 = fig.add_subplot(313)  # 这里是313,表示3X1,占满第三行
y1 = np.log(x)
y2 = np.sin(x)
y3 = np.cos(x)
y4 = x ** 2

# 这里不再使用plt.plot,而是使用s
s1.plot(x, y1, color="green", marker="x", linestyle="--")
s2.plot(x, y2, color="blue", marker="o", linestyle="-.")
s3.plot(x, y3, color="cyan", marker="<", linestyle="--")
s4.plot(x, y4, color="yellow", marker=">", linestyle="-.")
plt.show()

分格显示

方法一:

fig = plt.figure(figsize=(10, 8))

# subplot2grid创建小图
# (3, 3)表示将整个图像分格为3行3列,(0, 0)表示从第1行和第1列开始
# colspan表示跨3列,还有一个rowspan,不指定默认为1
ax1 = plt.subplot2grid((3,3), (0, 0), colspan=3)
# 从第2行第1列开始,跨两列
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
# 从第2行第3列开始,跨两行
ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
# 从第3行第1列开始,默认跨一行、一列
ax4 = plt.subplot2grid((3, 3), (2, 0))
# 从第3行第2列开始
ax5 = plt.subplot2grid((3, 3), (2, 1))
x = np.arange(1, 100, 5)
y1 = np.log(x)
y2 = np.sin(x)
y3 = np.cos(x)
y4 = x ** 2
y5 = (1 + np.exp(-x))

# 这里不再使用plt.plot,而是使用ax
ax1.plot(x, y1, color="green", marker="x", linestyle="--")
ax2.plot(x, y2, color="blue", marker="o", linestyle="-.")
ax3.plot(x, y3, color="cyan", marker="<", linestyle="--")
ax4.plot(x, y4, color="yellow", marker=">", linestyle="-.")
ax5.plot(x, y5, color="yellow", marker=">", linestyle="-.")
plt.show()

当然也可以这么写

fig = plt.figure(figsize=(10, 8))

x = np.arange(1, 100, 5)
y1 = np.log(x)
y2 = np.sin(x)
y3 = np.cos(x)
y4 = x ** 2
y5 = (1 + np.exp(-x))

plt.subplot2grid((3,3), (0, 0), colspan=3)
plt.plot(x, y1, color="green", marker="x", linestyle="--")

plt.subplot2grid((3, 3), (1, 0), colspan=2)
plt.plot(x, y2, color="blue", marker="o", linestyle="-.")

plt.subplot2grid((3, 3), (1, 2), rowspan=2)
plt.plot(x, y3, color="cyan", marker="<", linestyle="--")

plt.subplot2grid((3, 3), (2, 0))
plt.plot(x, y4, color="yellow", marker=">", linestyle="-.")

plt.subplot2grid((3, 3), (2, 1))
plt.plot(x, y5, color="yellow", marker=">", linestyle="-.")

plt.show()

方法二:

import matplotlib.gridspec as grid_spec  # 引入新的模块
 
fig = plt.figure(figsize=(10, 8))

x = np.arange(1, 100, 5)
y1 = np.log(x)
y2 = np.sin(x)
y3 = np.cos(x)
y4 = x ** 2
y5 = (1 + np.exp(-x))

gs = grid_spec.GridSpec(3, 3)  # 还是将图像分成3行3列

# plt.subplot2grid((3,3), (0, 0), colspan=3)
plt.subplot(gs[0, :])  # 占第一行和所有列
plt.plot(x, y1, color="green", marker="x", linestyle="--")

# plt.subplot2grid((3, 3), (1, 0), colspan=2)
plt.subplot(gs[1, : 2])
plt.plot(x, y2, color="blue", marker="o", linestyle="-.")

# plt.subplot2grid((3, 3), (1, 2), rowspan=2)
plt.subplot(gs[1: , 2])
plt.plot(x, y3, color="cyan", marker="<", linestyle="--")

# plt.subplot2grid((3, 3), (2, 0))
plt.subplot(gs[2, 0])
plt.plot(x, y4, color="yellow", marker=">", linestyle="-.")

# plt.subplot2grid((3, 3), (2, 1))
plt.subplot(gs[2, 1])
plt.plot(x, y5, color="yellow", marker=">", linestyle="-.")

plt.show()

14.添加坐标轴

plt.figure(figsize=(10, 8))

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

# 调用subplot不加参数,得到相应坐标轴
ax1 = plt.subplot()
# 生成一个双胞胎y轴
ax2 = ax1.twinx()

# 直接使用plt绘制即可,无需使用ax1和ax2,当然使用这两个也能绘制。
plt.plot(x, y1, color="red", label="sin")
plt.plot(x, y2, color="green", label="cos")
plt.legend()
plt.show()

15.动画

曲线的生成过程

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anime

%matplotlib notebook
fig = plt.figure(figsize=(10, 8))
plt.grid(color="pink", linestyle="--")

# 生成x,y数据
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)

# plt.plot可以有返回值,这里必须是"ani,"  不是"ani" ,切记,否则动图是不会生成的
# 这里的ani,拿到的是整个曲线
ani, = plt.plot(x, y)


# 构造函数,用来更新每一帧的x和y的值
# 参数i表示第i帧
def update_x_y(i):
    # 设置每一帧对应的曲线的坐标
    # 这里我们每次将x增大或者减小一点,这样图像才会移动
    # 至于增大或者减小的程度,由x决定
    # 让图像上的x的每个元素都随着帧数的增加而增大,这样就有了图像向右边走的效果
    ani.set_ydata(np.sin(x+i/100))
    return ani,   # 这里是要返回的,但是记住同样是"ani," 不是"ani"


# 这里也要赋值,否则动图不会显示
# fig:绘图对象
# func:更新动画的函数
# frames:一共要多少帧,这里是一个数组,也可以直接传入200
# interval:间隔
# blit:是否开启渲染
f = anime.FuncAnimation(
    fig=fig,
    func=update_x_y,
    frames=np.arange(200),
    interval=20,
    blit=True
)

plt.show()

大概长这样,声明一下,我这图像是在notebook里面生成的,但是我没有ffmpeg,无法自动合并。因此只能以html形式保存,然后到本地变成了一大堆的png,然后手动使用imageio模块,转成了gif,因此曲线变化的速度可能不和notebook不一样。

曲线不动,一个点在曲线上面走

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anime

%matplotlib notebook
fig = plt.figure(figsize=(10, 8))
plt.grid(color="pink", linestyle="--")

# 生成x,y数据
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)

# 绘制整个图像
plt.plot(x, y)
# 使用第一个点
ani, = plt.plot(x[0], y[0], color="green", marker="o")

# 构造函数,用来更新每一帧的x和y的值
# 参数i表示第i帧
def update_x_y(i):
    # set_ydata表示更新y的值,之前的ani,是用plt.plot(x, y)生成的,是一整条曲线
    # 这里的ani,是用plt.plot(x[0], y[0])生成的,是一个点
    # 而且这里是set_data,表示set_ydata,所以这里要传入两个参数,两个参数组成一个点。
    # 随着i的变化,这个点的坐标也在变化
    ani.set_data(x[i], y[i])
    return ani,   # 这里是要返回的,但是记住同样是"ani," 不是"ani"


# 这里也要赋值,否则动图不会显示
# fig:绘图对象
# func:更新动画的函数
# frames:一共要多少帧,这里是一个数组,也可以直接传入200
# interval:间隔
# blit:是否开启渲染
f = anime.FuncAnimation(
    fig=fig,
    func=update_x_y,
    frames=np.arange(100),
    interval=100,
    blit=True
)

plt.show()

我们把点的坐标也加上去吧

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anime

%matplotlib notebook
fig = plt.figure(figsize=(10, 8))
plt.grid(color="pink", linestyle="--")

x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)

plt.plot(x, y)
ani, = plt.plot(x[0], y[0], color="green", marker="o")
text = plt.text(4, 0.5, "", fontsize=16)
# 构造函数,用来更新每一帧的x和y的值
# 参数i表示第i帧
def update_x_y(i):
    if i % 2 == 0:
        ani.set_marker("*")
        ani.set_markersize(20)
        ani.set_color("pink")
    else:
        ani.set_marker("o")
        ani.set_markersize(14)
        ani.set_color("blue")
    ani.set_data(x[i], y[i])
    text.set_position((x[i], y[i]))
    text.set_text(f"x={round(x[i], 3)} y={round(y[i], 3)}")
    return ani, text


f = anime.FuncAnimation(
    fig=fig,
    func=update_x_y,
    frames=np.arange(100),
    interval=100,
    blit=True
)
plt.show()

常见问题:

1.子图重合的时候

加上plt.tight_layout()即可

2.当出现中文,显示为乱码的时候

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(5)
y = x + 3

plt.plot(x, y)
plt.xlabel("我是x轴")
plt.ylabel("我是y轴")
plt.show()

可以看到,label无法正常显示

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(5)
y = x + 3

plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体)
plt.rcParams['axes.unicode_minus'] = False   # 步骤二(解决坐标轴负数的负号显示问题)

plt.plot(x, y)
plt.xlabel("我是x轴")
plt.ylabel("我是y轴")
plt.show()

正常显示

posted @ 2019-08-28 17:47  古明地盆  阅读(1216)  评论(0编辑  收藏  举报