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 的每一列的折线图。代码的解释如下:
for i, column in enumerate(st1.columns):
这是一个循环语句,通过enumerate()
函数遍历st1的每一列,并将列索引和列名分别赋值给变量i和column。plt.plot(st1[column]):
plt.plot()是matplotlib.pyplot库中的函数,用于绘制折线图。这里的参数是st1的某一列数据,用于在图形中绘制折线。color=['r', 'g', 'b', 'y'][i]:
设置折线的颜色。在这里使用了一个颜色列表[‘r’, ‘g’, ‘b’, ‘y’],通过索引i选择颜色。linewidth=2,
:折线的宽度。linestyle='dashed',
:折线的样式,这里是虚线。marker='o',
:数据点的标记样式,这里是圆圈。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.0。
4.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()
1.直方图参数的补充:
-
matplotlib
中的
hist`函数用于绘制直方图,其主要参数如下: -
x
:要绘制直方图的数据,可以是一个一维数组或列表。 -
bins
:直方图的箱数或者箱的边界,默认为10。 -
range
:直方图的值域范围,可以是一个二元组或列表。默认为None
,即使用数据中的最小值和最大值。 -
density
:布尔值,表示是否将直方图归一化,默认为False
。 -
weights
:每个数据点的权重,默认为None
。 -
cumulative
:布尔值,表示是否绘制累积分布图,默认为False
。 -
bottom
:直方图的起始高度,默认为None
。 -
histtype
:直方图的类型,如'bar'
、'barstacked'
、'step'
、'stepfilled'
等,默认为'bar'
。 -
align
:直方图箱子的对齐方式,可以是'left'
、'mid'
、'right'
,默认为'mid'
。 -
orientation
:直方图的方向,可以是'vertical'
、'horizontal'
,默认为'vertical'
。 -
rwidth
:每个箱子的宽度,默认为None
。 -
log
:布尔值,表示是否在y轴上使用对数刻度,默认为False
。 -
color
:直方图的颜色。 -
label
:直方图的标签。 -
stacked
:布尔值,表示是否堆叠不同的直方图,默认为False
。
此外,hist
函数还支持通过**kwargs
传递其他绘图参数,以及data
参数用于指定绘制直方图的数据(通常不需要显式指定,因为x
参数已经足够)。
这些参数提供了对直方图外观和行为的精细控制,使得hist
函数非常灵活和强大。
2.折线图参数补充:
在matplotlib中,plot函数是最基本的函数之一,用于绘制2D数据。这个函数非常灵活,可以用于绘制线条、标记、棒条等。以下是plot函数的一些常用参数:
- x 和 y:这两个参数是必须的,分别代表横轴和纵轴上的数据点。
- fmt:这是一个字符串,用于指定线条的格式。它包括线条的颜色、线型和标记类型。例如,'r-'表示红色实线,'bo’表示蓝色圆圈标记。
- color:用于指定线条的颜色。
- linestyle:用于指定线条的样式,如实线(‘-’)、虚线(‘–’)、点线(‘:’)等。
- linewidth 或 lw:用于指定线条的宽度。
- marker:用于指定数据点的标记类型,如圆圈(‘o’)、星号(‘*’)、叉号(‘x’)等。
- markersize 或 ms:用于指定标记的大小。
- markerfacecolor 或 mfc:用于指定标记的填充颜色。
- markeredgecolor 或 mec:用于指定标记边缘的颜色。
- alpha:用于指定线条和标记的透明度。
- label:用于指定图例的标签。
- line2d:这是一个Line2D对象,包含了线条的所有属性。
- clip_on:如果设置为True,则线条会被限制在轴的范围内。
- clip_box:用于指定剪辑线条的矩形区域。
- data:用于指定要绘制的数据。
- ****kwargs:允许传递其他属性给Line2D对象。
3.饼图
在matplotlib中,pie函数用于绘制饼图。饼图显示了每个类别相对于总数的比例。以下是pie函数的一些常用参数:
x:数据集,用于绘制饼图的各个部分。
- labels:与数据集对应的标签列表。
- autopct:用于显示每个饼图部分的百分比格式的字符串。例如,autopct='%1.1f%%'会显示一位小数的百分比。
- colors:饼图部分的颜色列表。
- startangle:饼图的起始角度。
- explode:用于突出显示某个或某些部分的元组或列表。例如,explode=(0.1, 0, 0)会将第一个部分从中心突出10%的距离。
- counterclock:布尔值,指示饼图是否应该逆时针绘制,默认为True。
- wedgeprops:用于设置饼图各个部分的属性,如边框颜色、填充等。
- textprops:用于设置饼图标签的属性,如字体大小、颜色等。
- center:指定饼图的中心位置。
- radius:指定饼图的半径。
- labeldistance:标签离饼图中心的距离。
- pctdistance:百分比标签离饼图中心的距离。
- shadow:布尔值,指示是否绘制阴影。
- label:为饼图设置一个整体的标签。
- rotatelabels:布尔值,指示是否旋转标签以适应饼图。
- counterclock:布尔值,指示饼图部分是否应该按逆时针方向排序。
- frame:布尔值,指示是否绘制饼图的边框。
- decimal:用于格式化百分比的十进制位数。
- ****kwargs:允许传递其他属性给饼图。
经典案例
#库导入
from matplotlib import pyplot as plt
import numpy as np
#参数设置
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['figure.dpi'] = 100
plt.rcParams['figure.figsize'] = (5,3)
#国家和奖牌数据导入
countries = ['挪威', '德国', '中国', '美国', '瑞典']
gold_medal = [16, 12, 9, 8, 8]
silver_medal = [8, 10, 4, 10, 5]
bronze_medal = [13, 5, 2, 7, 5]
#将横坐标国家转换为数值
x = np.arange(len(countries))
width = 0.2 #条形图的宽度
#计算每一块的起始坐标
gold_x = x
silver_x = x + width
bronze_x = x + 2 * width
#绘图
plt.bar(gold_x,gold_medal,width=width,color="gold",label="金牌")
plt.bar(silver_x,silver_medal,width=width,color="silver",label="银牌")
plt.bar(bronze_x,bronze_medal,width=width, color="saddlebrown",label="铜牌")
#将横坐标数值转换为国家
plt.xticks(x + width,labels=countries)
# 显示柱状图的高度文本
for i in range(len(countries)):
plt.text(gold_x[i], gold_medal[i], gold_medal[i], va="bottom", ha="center", fontsize=8) # 金牌
plt.text(silver_x[i], silver_medal[i], silver_medal[i], va="bottom", ha="center", fontsize=8) # 银牌
plt.text(bronze_x[i], bronze_medal[i], bronze_medal[i], va="bottom", ha="center", fontsize=8) # 铜牌
#设置标题和副标题
plt.title("2021年度奥运会奖牌榜",fontsize=12)
plt.annotate("数据来源:Olympic.org.cn",xy=(0.5,0.01),xytext=(0,0),xycoords="figure fraction",textcoords="offset points",ha="center",va="bottom",fontsize=8,color="gray")
plt.annotate('最多金牌',xy=(0,16.5),xytext=(0,20),textcoords="offset points",ha="center",color="gold",arrowprops=dict(arrowstyle="->",connectionstyle="arc3,rad=-0.2"))
plt.annotate('最多银牌',xy=(1.2,11),xytext=(1,15),textcoords="offset points",ha="center",color="silver",arrowprops=dict(arrowstyle="->",connectionstyle="arc3,rad=-0.2"))
plt.annotate('最多银牌', xy=(3.2, 11), xytext=(1, 15), textcoords="offset points", ha="center", color="silver",arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=-0.2"))
plt.annotate('最多铜牌',xy=(0.38,14),xytext=(0,10),textcoords="offset points",ha="center",color="saddlebrown",arrowprops=dict(arrowstyle="->",connectionstyle="arc3,rad=-0.2"))
#显示图例
plt.legend(loc="upper right")
#显示图形
plt.show()
#保存图形