matplotlib画子图!!!(通俗易懂,有图有真相)

matplotlib两种绘图方法比较


import numpy as np
import pandas as pd
from pandas import DataFrame,Series
import matplotlib.pyplot as plt

import matplotlib
matplotlib.rc("font",family='KaiTi')#这一部分是在设置中文字体,不然到图片上中文会不能显示

# 创建数据
st1 = DataFrame([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]],
                 index=['小a', '小b', '小c', '小d'],
                 columns=['数学', '英语', '语文', '物理'])

# 绘制第一个图形
st1.plot(title='sq', kind='line', color=['c', 'm', 'b', 'y'],
         grid=True, fontsize=15, alpha=1, use_index=True,
         linewidth=2, linestyle='-.', marker='o', yticks=[0, 2, 4, 6, 8, 10])
plt.show()

# 创建新的图形
plt.figure()

# 绘制每一条线并设置标签
for i, column in enumerate(st1.columns):
    plt.plot(st1[column],
             color=['r', 'g', 'b', 'y'][i],
             linewidth=2,
             linestyle='dashed',
             marker='o',
             label=column)  # 单独设置每条线的标签
             
#如果不用for,一条一条添加也行
plt.plot(st1['数学'], color='r', linewidth=2, linestyle='dashed', marker='o', label='数学')
plt.plot(st1['英语'], color='g', linewidth=2, linestyle='dashed', marker='o', label='英语')
plt.plot(st1['语文'], color='b', linewidth=2, linestyle='dashed', marker='o', label='语文')
plt.plot(st1['物理'], color='y', linewidth=2, linestyle='dashed', marker='o', label='物理')

# 添加图例并显示图形
plt.legend(loc='upper right')
plt.show()

在这里插入图片描述

在这里插入图片描述
以上是生成的两幅图,两幅图的处理有很大不同。

  • 第一幅图:
    方法:使用 DataFrame.plot() 方法,直接调用 Pandas 的内置绘图功能。
    简洁:代码更加简洁,少量参数即可完成绘图。
    所有列一次性绘制:同时绘制所有列(“数学”,“英语”,“语文”,“物理”)为不同的线条,使用 DataFrame 自带的方法对所有数据进行处理。
  • 第二幅图:
    方法:使用 Matplotlib 的 plt.plot() 方法,手动绘制每一条线。
    灵活性:可以逐列控制每条线的样式和颜色,更加灵活。
    标签设置:每条线都有单独的标签,便于在图例中显示不同列的名称,让图例更加明晰。

总结

  • 第一部分适合快速绘制并且展示简单的数据关系,适用于多数情况下对数据进行初步的可视化。
  • 第二部分则提供更高的自定义能力,适合希望详细控制绘图样式的场景,尤其在需要特定样式和标注的情况下。

代码详解

for i, column in enumerate(st1.columns):
    plt.plot(st1[column],
             color=['r', 'g', 'b', 'y'][i],
             linewidth=2,
             linestyle='dashed',
             marker='o',
             label=column)  # 单独设置每条线的标签入代码片

这段代码是用来画出DataFrame st1 的每一列的折线图。代码的解释如下:

  1. for i, column in enumerate(st1.columns):这是一个循环语句,通过enumerate()函数遍历st1的每一列,并将列索引和列名分别赋值给变量i和column。
  2. plt.plot(st1[column]):plt.plot()是matplotlib.pyplot库中的函数,用于绘制折线图。这里的参数是st1的某一列数据,用于在图形中绘制折线。
  3. color=['r', 'g', 'b', 'y'][i]:设置折线的颜色。在这里使用了一个颜色列表[‘r’, ‘g’, ‘b’, ‘y’],通过索引i选择颜色。
  4. linewidth=2,:折线的宽度。
  5. linestyle='dashed',:折线的样式,这里是虚线。
  6. marker='o',:数据点的标记样式,这里是圆圈。
  7. label=column):给折线添加标签,即折线对应的列名。
    最后的结果是将DataFrame st1的每一列数据绘制成折线图,并在图例中显示每个折线对应的列名。

亮点就是遍历每一列,并给每一列独立处理

多子图操作

1.matplotlib引入:

import matplotlib.pyplot as plt

2.matplotlib的对象都位于figure对象中,所以我们要先创建一个figure对象,我觉得它相当于一个画布fig = plt.figure()

3.很显然,不能通过figure画图,我们还需要在画布上插上一点儿图,也就是我们说的子图,可以插入多个ax1 = fig.add_subplot(2, 2, 1)

4.上面的代码的意思是,我是这么理解的,并非已经建了2 x2个图,而是你自己在脑海中临摹出2*2是什么样子,然后第三个参数就表示你想象出来的图里的位置,从左往右,从上到下,多写两个ax2 = fig.add_subplot(2, 2, 2) ax3 = fig.add_subplot(2, 2, 3)

出来的效果就是下图所示
在这里插入图片描述
可见,这个时候图上还没有任何的数据,轴上的数据也都是默认值。

这里有个注意的点,如果说你是在jupyter notebook上的话,要把所有操作都写在一个窗格里,这样才能同时执行,因为jupyter notebook每次执行图形都会重置!

fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)

如上,我们已经执行这一段代码,如果这个时候我们执行了一(或者n条)条代码(且没有点名是ax几,那么就默认作用于第三条上,如plt.plot(np.random.rand(10), label='Line 1'),作用之后形成的图如下所示
在这里插入图片描述
上面是只执行一条的情况,如果这个时候,我们想要画两条线,分别表示小红和小黑的成绩的话,我们可以这样

fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)
plt.plot(np.random.randint(100,size = 10), label='小红')
plt.plot(np.random.randint(100,size = 10), label='小黑')
plt.legend()
plt.title('小红和小黑的成绩')
plt.xlabel('考试次数')
plt.ylabel('分数')
plt.xticks(range(10))
plt.yticks(range(0,110,10))
fig.show()

然后生成的图片就是这样
在这里插入图片描述
可见,如果不指明具体的子图,我们就只能操作最后一个图,很没用。我们一般有以下几种处理方法:
A要处理哪个子图就调用ax1./ax2./ax3.,如下图所示

# 在第一个子图上绘制
ax1.plot(np.random.randint(100, size=10), label='小红')
ax1.plot(np.random.randint(100, size=10), label='小黑')
ax1.legend()
ax1.set_title('小红和小黑的成绩')
ax1.set_xlabel('考试次数')
ax1.set_ylabel('分数')
ax1.set_xticks(range(10))
ax1.set_yticks(range(0, 110, 10))

在这里插入图片描述
B.每次创建一个子图,就在后面进行plt.plot等操作,用for循环的话会比较方便,用for循环的话,可以直接用subplots操作,它可以创建一个新的Figure,并返回一个含有已创建的subplot对象的NumPy数组

# 创建一个新图形
fig, axs = plt.subplots(2, 2)  # 创建2行2列的子图

'''
注意:
fig是整个图形,axs是子图数组。
axs是一个二维数组,可以用axs[i][j]来访问第i行第j列的子图。
axs.flat 是一个迭代器,可以方便地遍历二维数组中的所有元素。
'''

# 示例数据
data = [np.random.randint(100, size=10) for _ in range(4)]  # 生成4组随机数据
labels = ['小红', '小黑', '数据1', '数据2']  # 标签列表
titles = ['小红和小黑的成绩', '另一个成绩', '第三个成绩', '第四个成绩']  # 标题列表

# 使用循环在每个子图上绘制
for i, ax in enumerate(axs.flat):  # axs.flat 可以方便地遍历二维数组
    ax.plot(data[i], label=labels[i])
    ax.legend()
    ax.set_title(titles[i])
    ax.set_xlabel('考试次数')
    ax.set_ylabel('分数')
    ax.set_xticks(range(10))
    ax.set_yticks(range(0, 110, 10))

plt.tight_layout()  # 调整布局
plt.show()

在这里插入图片描述

5.到这一步的时候,基本的图就可以画出来了,接下来就是一些小调整

a.对折线的调整

1.x, y:第一个和第二个参数,指定绘制的点的横坐标和纵坐标。
2.color:设置线条和点的颜色,可以使用颜色名称(如 'red''blue')(也可以直接用缩写)、十六进制代码(如 '#FF0000')或 RGB 元组(如 (1, 0, 0))。
3.linewidth (或 lw):设置线条的宽度,默认值为 1.04.linestyle (或 ls):设置线条的样式,可以是:
		'-':实线(默认)
		'--':虚线
		':':点线
		'-.':点划线
5.marker:
设置数据点的标记样式,例如:
		'o':圆圈标记
		's':方块标记
		'^':三角形标记
		'D':菱形标记
您还可以使用 markersize 参数来设置标记的大小。
6.alpha:设置线条颜色的透明度,值范围从 0(完全透明)到 1(完全不透明)。
7.label:设置图例中显示的标签,通常与 plt.legend() 一起使用。
以上都是plot的参数

b.对坐标轴的处理

# 添加标题和坐标轴标签
plt.title('正弦函数图像')           # 图形标题
plt.xlabel('X 轴')               # X 轴标签
plt.ylabel('Y 轴')               # Y 轴标签

# 设置坐标轴范围
plt.xlim(0, 10)                  # X 轴范围
plt.ylim(-1.5, 1.5)             # Y 轴范围

# 设置坐标轴的刻度
plt.xticks(np.arange(0, 11, 1))  # X 轴刻度
plt.yticks(np.arange(-1, 2, 0.5)) # Y 轴刻度

# 显示网格线
plt.grid(True)

# 添加图例
plt.legend()  
#这个很重要,必须调用,无论你绘图时是否传递label标签选项
#,这是用来展示图例的!!!用于区分很好用,没有它,图例展
#示不出来,就是上面参数中label = xxx,这一项就得靠legend来展示


plt.tight_layout()  # 调整布局
plt.show()

注意:这里直接用plt调用时,直接就是xticks的这种,但是如果是让子图来调用,函数名会改成set_xticks,否则会报错的,因为一个是全局接口,一个是对象接口,plt 是一个全局状态机,允许你随时对当前活动的图形或轴进行操作。比如,plt.xlabel() 会设置当前活动子图的 X 轴标签。若有多个子图,每次调用时,需要确保当前子图是你想要操作的那个。set_xlabel() 是 Axes 类的方法,直接作用于特定的 Axes 对象。这提供了更明确的界定,减少了对全局状态的依赖。例如,axs[0].set_xlabel(‘X 轴’) 直接在第一个子图上设置 X 轴标签,确保不会修改其他子图。grid和legend则通用,我觉得也不用特意去记住吧,反正报错了就改一改!

为了防止你们不理解图例的重要性,请看下面随机漫步的例子:
In [44]: from numpy.random import randn

In [45]: fig = plt.figure(); ax = fig.add_subplot(1, 1, 1)

In [46]: ax.plot(randn(1000).cumsum(), 'k', label='one')
Out[46]: [<matplotlib.lines.Line2D at 0x7fb624bdf860>]

In [47]: ax.plot(randn(1000).cumsum(), 'k--', label='two')
Out[47]: [<matplotlib.lines.Line2D at 0x7fb624be90f0>]

In [48]: ax.plot(randn(1000).cumsum(), 'k.', label='three')
Out[48]: [<matplotlib.lines.Line2D at 0x7fb624be9160>]

在这里插入图片描述
c.注解啥的(text.arrow,annotate)

import numpy as np
import pandas as pd
from pandas import DataFrame,Series
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rc("font",family='KaiTi')


# 创建数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

# 创建 2 行 1 列的子图
fig, axs = plt.subplots(2)

# 绘制第一个子图
axs[0].plot(x, y1, label='sin(x)')
axs[0].set_title('正弦函数图像')
axs[0].set_xlabel('X 轴')
axs[0].set_ylabel('Y 轴')
axs[0].set_xlim(0, 10)
axs[0].set_ylim(-1.5, 1.5)
axs[0].set_xticks(np.arange(0, 11, 1))
axs[0].set_yticks(np.arange(-1, 2, 0.5))
axs[0].grid(True)
axs[0].legend()

# 添加注解(主要看这一行的使用)
axs[0].annotate('局部最大值', xy=(np.pi/2, 1), xytext=(np.pi/2 + 1, 1.2),
                arrowprops=dict(facecolor='black', shrink=0.05))

# 绘制第二个子图
axs[1].plot(x, y2, label='cos(x)', color='orange')
axs[1].set_title('余弦函数图像')
axs[1].set_xlabel('X 轴')
axs[1].set_ylabel('Y 轴')
axs[1].set_xlim(0, 10)
axs[1].set_ylim(-1.5, 1.5)
axs[1].set_xticks(np.arange(0, 11, 1))
axs[1].set_yticks(np.arange(-1, 2, 0.5))
axs[1].grid(True)
axs[1].legend()

# 添加注解(主要看这一行的使用)
axs[1].annotate('局部最小值', xy=(np.pi, -1), xytext=(np.pi + 1, -1.2),
                arrowprops=dict(facecolor='black', shrink=0.05))

# 调整布局以避免重叠
plt.tight_layout()

# 显示图形
plt.show()

注解参数说明
text:注解的文本内容。
xy:被注解的点的坐标(x, y)。
xytext:注解文本的坐标(x, y)。
arrowprops:箭头的属性,例如颜色、样式等。
在这里插入图片描述

当然,也可以直接用text,当你不需要箭头的时候
axs[0].text(np.pi/2 + 0.5, 1.5, '标注文本', fontsize=18, color='black')
在这里插入图片描述
d.还有一个很好玩的,那就是在表格里面画图形~~~~is it interesting???!!!
图形的绘制要麻烦一些。matplotlib有一些表示常见图形的对象。这些对象被称为块(patch)。其中有些(如Rectangle和Circle),可以在matplotlib.pyplot中找到,但完整集合位于matplotlib.patches。
要在图表中添加一个图形,你需要创建一个块对象shp,然后通过ax.add_patch(shp)将其添加到subplot中。

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

rect = plt.Rectangle((0.2, 0.75), 0.4, 0.15, color='k', alpha=0.3)
circ = plt.Circle((0.7, 0.2), 0.15, color='b', alpha=0.3)
pgon = plt.Polygon([[0.15, 0.15], [0.35, 0.4], [0.2, 0.6]],
                   color='g', alpha=0.5)

ax.add_patch(rect)
ax.add_patch(circ)
ax.add_patch(pgon)

在这里插入图片描述

6.我们画了那么多图,肯定要保存啊

plt.savefig('figpath.png', dpi=400, bbox_inches='tight')
在这里插入图片描述
其实matplotlib还有很多其他的图,但是原理都是大同小异!我觉得编程这种东西真的要多动手!你就会发现它的趣味所在!我爱coding!!!

最后补充以下各种图形

import numpy as np
import pandas as pd
from pandas import DataFrame,Series
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rc("font",family='KaiTi')

import numpy as np
import matplotlib.pyplot as plt

# 生成数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

# 创建折线图
plt.figure(figsize=(10, 8))

# 折线图
plt.subplot(3, 2, 1)
plt.plot(x, y1, label='sin(x)')
plt.title('折线图')

# 散点图
plt.subplot(3, 2, 2)
plt.scatter(x, y1, color='orange')
plt.title('散点图')

# 柱状图
plt.subplot(3, 2, 3)
plt.bar([1, 2, 3], [3, 5, 2])
plt.title('柱状图')

# 直方图
plt.subplot(3, 2, 4)
plt.hist(np.random.randn(1000), bins=30)
plt.title('直方图')

# 饼图
plt.subplot(3, 2, 5)
plt.pie([30, 20, 50], labels=['A', 'B', 'C'], autopct='%1.1f%%')
plt.title('饼图')

# 箱线图
plt.subplot(3, 2, 6)
plt.boxplot(np.random.randn(100, 5))
plt.title('箱线图')

plt.tight_layout()
plt.show()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值