哈喽,我是小白~
今儿和大家分享Matplotlib的一些高级技巧!~
在机器学习实验中,Matplotlib 的高级绘图技巧对于数据可视化非常的重要,因为它们能够有效地揭示数据之间的关系、分布和趋势,帮助大家快速识别模式和异常点。通过使用多种图形(如子图、散点图、箱线图等),可以清晰展示复杂的数据特征,提高数据分析的效率。
最终,良好的可视化不仅有助于模型选择和结果解释,还能够在与团队和利益相关者沟通时传达更具说服力的分析结果。
涉及到的重要的十个绘图技巧有:
子图布局 共享坐标轴 自定义刻度和网格 使用对数坐标 添加注释 彩色映射 三维绘图 双坐标轴 热力图 自定义图形风格
下面,每个部分做更详细的解释,确保每个技巧都深入讲解,并给大家带有完整代码示例。
1. 子图布局(Subplots Layout)
在可视化多维数据时,你可能希望在同一个窗口中展示多个图表进行对比。这时,使用 plt.subplots()
可以非常轻松地实现多子图布局。你可以灵活控制每个子图的大小、位置,甚至每个子图中的内容。
实现方式
plt.subplots(nrows, ncols)
:创建一个包含nrows
行和ncols
列的子图网格。fig
表示整个图形对象(图形容器),axs
是子图对象数组(可以是多维数组)。使用 axs[row, col]
来访问某个特定子图。
Python 示例
import matplotlib.pyplot as plt
import numpy as np
# 生成数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)
y4 = np.exp(x / 3)
# 创建 2x2 的子图布局
fig, axs = plt.subplots(2, 2, figsize=(12, 8))
# 第一个子图
axs[0, 0].plot(x, y1, 'r', label='sin(x)')
axs[0, 0].set_title('Sine Wave')
axs[0, 0].legend()
# 第二个子图
axs[0, 1].plot(x, y2, 'g', label='cos(x)')
axs[0, 1].set_title('Cosine Wave')
axs[0, 1].legend()
# 第三个子图
axs[1, 0].plot(x, y3, 'b', label='tan(x)')
axs[1, 0].set_title('Tangent Wave')
axs[1, 0].legend()
# 第四个子图
axs[1, 1].plot(x, y4, 'm', label='exp(x/3)')
axs[1, 1].set_title('Exponential Function')
axs[1, 1].legend()
# 调整布局
plt.tight_layout()
plt.show()
figsize=(12, 8)
:调整整个画布的大小,确保每个子图有足够的显示空间。plt.tight_layout()
:自动调整子图间的间距,避免标签、标题等重叠。
2. 共享坐标轴 (Shared Axes)
当绘制多张图时,常常希望图表共享同一个坐标轴,以便方便对比。这种情况下,可以使用 sharex
或 sharey
参数来实现不同子图共享 X 轴或 Y 轴。
实现方式
plt.subplots(nrows, ncols, sharex=True, sharey=True)
:子图共享同一个 X 轴或 Y 轴。
Python 示例
import matplotlib.pyplot as plt
import numpy as np
# 生成数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
# 创建共享X轴的子图
fig, axs = plt.subplots(2, 1, figsize=(8, 6), sharex=True)
# 上图
axs[0].plot(x, y1, 'r', label='sin(x)')
axs[0].set_title('Sine Wave')
axs[0].legend()
# 下图
axs[1].plot(x, y2, 'b', label='cos(x)')
axs[1].set_title('Cosine Wave')
axs[1].legend()
# 设置共享的x轴标签
plt.xlabel('X Axis')
plt.tight_layout()
plt.show()
sharex=True
:两个子图共享 X 轴,方便对比。同样可以设置 sharey=True
来共享 Y 轴。
3. 自定义刻度和网格 (Custom Ticks and Grids)
默认的刻度和网格线可能并不适合所有数据。通过自定义,可以让图表变得更清晰和专业。
实现方式
ax.set_xticks()
和ax.set_yticks()
用于设置 X 轴和 Y 轴刻度。ax.grid()
控制网格线的显示。
Python 示例
import matplotlib.pyplot as plt
import numpy as np
# 生成数据
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig, ax = plt.subplots(figsize=(8, 6))
# 绘制基本图形
ax.plot(x, y)
# 自定义 X 轴刻度和网格
ax.set_xticks([0, 2, 4, 6, 8, 10])
ax.set_xticklabels(['Zero', 'Two', 'Four', 'Six', 'Eight', 'Ten'], fontsize=12)
# 设置网格线
ax.grid(True, which='both', linestyle='--', linewidth=0.7)
plt.show()
set_xticks
:设置自定义 X 轴刻度位置。set_xticklabels
:为 X 轴刻度设置标签。grid(True, which='both')
:显示主、副网格线,linestyle
设置网格线样式。
4. 使用对数坐标 (Logarithmic Scales)
对于指数增长或幂律分布的数据,线性坐标系可能无法准确显示趋势。对数坐标可以让变化更为直观。
实现方式
使用 ax.set_xscale('log')
或ax.set_yscale('log')
来设置对数坐标。
Python 示例
# 生成数据
x = np.linspace(1, 1000, 100)
y = x ** 2
fig, ax = plt.subplots(figsize=(8, 6))
# 绘制对数坐标图
ax.plot(x, y)
ax.set_xscale('log')
ax.set_yscale('log')
# 设置标签
ax.set_xlabel('Log X')
ax.set_ylabel('Log Y')
plt.show()
set_xscale('log')
:X 轴使用对数坐标。set_yscale('log')
:Y 轴使用对数坐标。适用于处理大范围数值。
5. 添加注释 (Annotations)
在展示复杂数据时,添加注释可以突出某些关键点,帮助观众更好地理解图表。
实现方式
使用 ax.annotate()
函数在图中标注特定位置的注释信息。
Python 示例
# 生成数据
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig, ax = plt.subplots(figsize=(8, 6))
# 绘制基本图形
ax.plot(x, y)
# 添加注释
ax.annotate('Local Max', xy=(1.57, 1), xytext=(3, 1.5),
arrowprops=dict(facecolor='black', shrink=0.05))
plt.show()
annotate('text', xy=(x, y), xytext=(x_text, y_text))
:在xy
坐标处添加注释,xytext
为文本的实际位置。arrowprops
设置箭头样式。
6. 彩色映射 (Colormaps)
在展示多维数据时,使用彩色映射(colormap)可以通过颜色强度来表示数据的不同取值。
实现方式
使用 plt.scatter()
或plt.imshow()
并结合cmap
参数来应用彩色映射。
Python 示例
# 生成数据
x = np.random.randn(1000)
y = np.random.randn(1000)
colors = np.sqrt(x**2 + y**2)
# 使用彩色映射绘制散点图
plt.scatter(x, y, c=colors, cmap='viridis', s=50)
plt.colorbar() # 显示色条
plt.show()
cmap='viridis'
:使用预定义的彩色映射方案(如 'viridis')。colorbar()
:添加颜色条,表示数值对应的颜色强度。
7. 三维绘图 (3D Plotting)
Matplotlib
支持三维绘图,可以帮助可视化三维数据。
实现方式
使用 mpl_toolkits.mplot3d
提供的Axes3D
创建三维坐标系。
Python 示例
from mpl_toolkits.mplot3d import Axes3D
# 生成数据
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X
, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))
fig = plt.figure(figsize=(10, 7))
ax = fig.add_subplot(111, projection='3d')
# 绘制3D图形
ax.plot_surface(X, Y, Z, cmap='inferno')
plt.show()
projection='3d'
:指定三维绘图。plot_surface()
绘制三维表面,cmap
用于控制颜色映射。
8. 双坐标轴 (Twin Axes)
有时你可能需要在同一张图中展示两组不同单位的数据,双坐标轴可以有效解决这个问题。
实现方式
使用 ax.twinx()
创建第二个 Y 轴。
Python 示例
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.log(x + 1)
fig, ax1 = plt.subplots()
# 第一个坐标轴
ax1.plot(x, y1, 'g-')
ax1.set_ylabel('sin(x)', color='g')
# 第二个坐标轴
ax2 = ax1.twinx()
ax2.plot(x, y2, 'b-')
ax2.set_ylabel('log(x+1)', color='b')
plt.show()
ax.twinx()
:创建第二个 Y 轴,适合对比两组不同单位的数据。
9. 热力图 (Heatmaps)
热力图是一种非常直观的二维数据展示方式,通常用于相关性分析或矩阵数据可视化。
实现方式
使用 plt.imshow()
来绘制二维矩阵的热力图。
Python 示例
data = np.random.rand(10, 10)
plt.imshow(data, cmap='hot', interpolation='nearest')
plt.colorbar()
plt.show()
imshow()
:直接绘制二维数据的热力图。cmap='hot'
:指定热力图的颜色映射方案。
10. 自定义图形风格 (Custom Styles)
Matplotlib
提供了一些预设风格,比如 seaborn
或 ggplot
风格,你可以根据需要自定义图形的整体风格,让图表更美观。
实现方式
使用 plt.style.use()
来应用不同的风格。
Python 示例
plt.style.use('seaborn-darkgrid')
# 生成数据
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.plot(x, y)
plt.show()
plt.style.use()
:应用预定义的绘图风格(如seaborn-darkgrid
)。
下面,咱们实现一个比较综合的案例,展示多个图形(折线图、散点图、直方图和箱线图),并结合颜色映射和共享轴的技巧。此案例适合用于同时分析多个特征之间的关系,揭示不同变量的分布、趋势和异常点。
案例描述:
我们将创建一个虚拟数据集,其中包含三组不同的数据:
A:具有正态分布的随机数,表示某个特征的测量值。 B:通过对 A 进行一些变换得到,表示另一个相关特征。 C:随机生成的离散类别数据,用于展示离散变量的分布。
在这个图中,我们将通过以下图形展示不同特征之间的关系:
折线图展示特征 A 和 B 之间的关系。 散点图展示特征 B 和 A 之间的相关性,同时用颜色区分不同类别。 直方图展示特征 A 和 B 的分布。 箱线图展示不同类别的数据分布和离群点。
完整 Python 代码:
import matplotlib.pyplot as plt
import numpy as np
# 生成虚拟数据集
np.random.seed(42)
n = 1000
A = np.random.normal(loc=50, scale=10, size=n) # 特征 A,正态分布
B = A + np.random.normal(loc=0, scale=5, size=n) # 特征 B,与 A 相关联
C = np.random.randint(0, 3, size=n) # 特征 C,离散类别数据 (0, 1, 2)
# 创建一个图形,包含 2x2 的子图布局
fig, axs = plt.subplots(2, 2, figsize=(12, 10))
fig.suptitle('Data Analysis: Feature A, B, and C', fontsize=16)
# 子图 1: A 和 B 的折线图
axs[0, 0].plot(A, label='Feature A', color='red', linewidth=2)
axs[0, 0].plot(B, label='Feature B', color='blue', linestyle='--', linewidth=2)
axs[0, 0].set_title('Line Plot of Feature A and B')
axs[0, 0].set_xlabel('Index')
axs[0, 0].set_ylabel('Value')
axs[0, 0].legend()
axs[0, 0].grid(True)
# 子图 2: A 和 B 的散点图,C 作为颜色映射
scatter = axs[0, 1].scatter(A, B, c=C, cmap='plasma', s=100, edgecolor='k', alpha=0.8)
axs[0, 1].set_title('Scatter Plot of Feature A vs Feature B (Colored by Feature C)')
axs[0, 1].set_xlabel('Feature A')
axs[0, 1].set_ylabel('Feature B')
# 添加颜色条
cbar = fig.colorbar(scatter, ax=axs[0, 1])
cbar.set_label('Feature C Categories')
# 子图 3: A 和 B 的直方图
axs[1, 0].hist(A, bins=15, color='green', alpha=0.7, label='Feature A')
axs[1, 0].hist(B, bins=15, color='orange', alpha=0.7, label='Feature B')
axs[1, 0].set_title('Histogram of Feature A and B')
axs[1, 0].set_xlabel('Value')
axs[1, 0].set_ylabel('Frequency')
axs[1, 0].legend()
axs[1, 0].grid(True)
# 子图 4: 箱线图,展示不同类别 C 的数据分布 (针对 A 和 B)
axs[1, 1].boxplot([A[C == 0], A[C == 1], A[C == 2]], positions=[1, 2, 3], widths=0.6, patch_artist=True,
boxprops=dict(facecolor='cyan', color='black'),
medianprops=dict(color='black'))
axs[1, 1].boxplot([B[C == 0], B[C == 1], B[C == 2]], positions=[4, 5, 6], widths=0.6, patch_artist=True,
boxprops=dict(facecolor='pink', color='black'),
medianprops=dict(color='black'))
axs[1, 1].set_title('Boxplot of Feature A and B Grouped by Feature C')
axs[1, 1].set_xticks([1.5, 4.5])
axs[1, 1].set_xticklabels(['Feature A', 'Feature B'])
axs[1, 1].set_ylabel('Value')
# 调整子图之间的布局
plt.tight_layout(rect=[0, 0, 1, 0.95])
# 显示图形
plt.show()
虚拟数据集:
A
是一个正态分布的随机数据,代表特征 A。B
是基于 A 的变换(加上噪声),代表另一个相关特征 B。C
是一个离散的类别数据,取值为 0、1 和 2。
折线图:展示特征 A 和 B 的随时间变化的趋势,红色表示 A,蓝色虚线表示 B。该图可以帮助观察两个特征之间的变化趋势,特别是它们的相关性。 散点图:A 和 B 的相关性,用颜色区分不同的类别(C),并通过颜色条解释类别信息。图中颜色的变化可以帮助我们识别不同类别之间的分布差异。 直方图:显示 A 和 B 的频率分布,绿色表示 A,橙色表示 B。该图帮助我们理解两个特征的分布形态及其重叠部分。 箱线图:展示不同类别的 A 和 B 的分布,帮助我们发现不同类别的特征分布差异,并识别潜在的离群点。
其中:
特征 A 和 B 之间的相关性:从折线图和散点图可以观察到特征 A 和 B 之间的强相关性,虽然 B 带有噪声,但总体趋势与 A 非常相似。 类别 C 对 A 和 B 的影响:散点图通过颜色展示了不同类别的数据分布情况,可以看到不同类别的数据分布在 A 和 B 上有一定差异。箱线图进一步揭示了这些类别的分布差异以及可能的离群点。 特征 A 和 B 的分布:直方图帮助我们理解特征 A 和 B 的分布形态,从中可以看到两者的分布范围和频率。
这个案例展示了如何通过多种图形方式对数据进行深入分析,适合用于多维数据的探索性分析(EDA)。
最后