Matplotlib绘制散点图趋势线:全面指南与实例

Matplotlib绘制散点图趋势线:全面指南与实例

参考:Drawing Scatter Trend Lines Using Matplotlib

Matplotlib是Python中最流行的数据可视化库之一,它提供了强大的工具来创建各种类型的图表和图形。在数据分析和科学研究中,散点图是一种常用的可视化方法,用于展示两个变量之间的关系。而趋势线则可以帮助我们更好地理解数据的整体趋势和模式。本文将详细介绍如何使用Matplotlib绘制散点图并添加趋势线,包括线性、多项式和指数趋势线等多种类型。

1. 基础散点图绘制

在开始绘制趋势线之前,我们首先需要创建一个基础的散点图。以下是一个简单的示例:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 10, 50)
y = 2 * x + 1 + np.random.normal(0, 1, 50)

# 创建散点图
plt.figure(figsize=(10, 6))
plt.scatter(x, y, color='blue', alpha=0.6, label='Data points')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Basic Scatter Plot (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

在这个例子中,我们首先导入了必要的库:Matplotlib的pyplot模块和NumPy。然后,我们生成了一些示例数据:x是一个从0到10的线性空间,y是基于x的线性函数加上一些随机噪声。使用plt.scatter()函数,我们创建了一个基本的散点图,并添加了轴标签、标题和图例。

2. 线性趋势线

线性趋势线是最简单和最常用的趋势线类型。它假设数据点之间存在线性关系,可以用一条直线来近似表示。

import matplotlib.pyplot as plt
import numpy as np
from scipy import stats

# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 10, 50)
y = 2 * x + 1 + np.random.normal(0, 1, 50)

# 计算线性回归
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
line = slope * x + intercept

# 绘制散点图和趋势线
plt.figure(figsize=(10, 6))
plt.scatter(x, y, color='blue', alpha=0.6, label='Data points')
plt.plot(x, line, color='red', label=f'Trend line (R² = {r_value**2:.2f})')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Scatter Plot with Linear Trend Line (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

在这个例子中,我们使用了SciPy库的stats.linregress()函数来计算线性回归。这个函数返回斜率、截距、R值(相关系数)等统计信息。然后,我们使用计算得到的斜率和截距来绘制趋势线。R²值被添加到图例中,以显示拟合的好坏程度。

3. 多项式趋势线

当数据呈现非线性关系时,多项式趋势线可能更适合。以下是一个二次多项式趋势线的例子:

import matplotlib.pyplot as plt
import numpy as np

# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 10, 50)
y = 2 * x**2 - 5 * x + 3 + np.random.normal(0, 10, 50)

# 计算多项式回归
coeffs = np.polyfit(x, y, 2)
poly = np.poly1d(coeffs)

# 绘制散点图和趋势线
plt.figure(figsize=(10, 6))
plt.scatter(x, y, color='blue', alpha=0.6, label='Data points')
plt.plot(x, poly(x), color='red', label='Polynomial trend line')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Scatter Plot with Polynomial Trend Line (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

在这个例子中,我们使用np.polyfit()函数来计算多项式系数,然后使用np.poly1d()创建一个多项式函数。这里我们使用了二次多项式(degree=2),但你可以根据需要调整多项式的阶数。

4. 指数趋势线

对于呈指数增长或衰减的数据,指数趋势线可能是一个好选择。以下是一个示例:

import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit

# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 5, 50)
y = 2 * np.exp(0.5 * x) + np.random.normal(0, 0.5, 50)

# 定义指数函数
def exp_func(x, a, b):
    return a * np.exp(b * x)

# 拟合指数函数
popt, _ = curve_fit(exp_func, x, y)

# 绘制散点图和趋势线
plt.figure(figsize=(10, 6))
plt.scatter(x, y, color='blue', alpha=0.6, label='Data points')
plt.plot(x, exp_func(x, *popt), color='red', label='Exponential trend line')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Scatter Plot with Exponential Trend Line (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

在这个例子中,我们首先定义了一个指数函数exp_func。然后,我们使用SciPy的curve_fit()函数来拟合这个指数函数到我们的数据点。最后,我们使用拟合得到的参数来绘制指数趋势线。

5. 对数趋势线

对数趋势线适用于数据增长率随时间减缓的情况。以下是一个示例:

import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit

# 生成示例数据
np.random.seed(42)
x = np.linspace(1, 10, 50)
y = 5 * np.log(x) + 2 + np.random.normal(0, 0.5, 50)

# 定义对数函数
def log_func(x, a, b):
    return a * np.log(x) + b

# 拟合对数函数
popt, _ = curve_fit(log_func, x, y)

# 绘制散点图和趋势线
plt.figure(figsize=(10, 6))
plt.scatter(x, y, color='blue', alpha=0.6, label='Data points')
plt.plot(x, log_func(x, *popt), color='red', label='Logarithmic trend line')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Scatter Plot with Logarithmic Trend Line (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

这个例子类似于指数趋势线的例子,但我们使用了对数函数而不是指数函数。我们定义了一个对数函数log_func,然后使用curve_fit()来拟合数据。

6. 移动平均趋势线

移动平均趋势线可以帮助平滑数据并显示整体趋势,特别是在处理有噪声的数据时。以下是一个简单的移动平均趋势线示例:

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

# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 10, 100)
y = 2 * x + 1 + np.random.normal(0, 2, 100)

# 计算移动平均
window_size = 10
y_ma = pd.Series(y).rolling(window=window_size).mean()

# 绘制散点图和趋势线
plt.figure(figsize=(10, 6))
plt.scatter(x, y, color='blue', alpha=0.6, label='Data points')
plt.plot(x, y_ma, color='red', label=f'Moving average (window={window_size})')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Scatter Plot with Moving Average Trend Line (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

在这个例子中,我们使用了Pandas库的rolling()函数来计算移动平均。我们设置了一个窗口大小为10的移动平均,但你可以根据需要调整这个值。

7. 局部加权回归散点平滑(LOWESS)

LOWESS是一种非参数回归方法,它可以很好地捕捉数据中的非线性趋势。以下是使用LOWESS的示例:

import matplotlib.pyplot as plt
import numpy as np
from statsmodels.nonparametric.smoothers_lowess import lowess

# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 10, 100)
y = 2 * np.sin(x) + np.random.normal(0, 0.5, 100)

# 计算LOWESS
lowess_result = lowess(y, x, frac=0.6)

# 绘制散点图和趋势线
plt.figure(figsize=(10, 6))
plt.scatter(x, y, color='blue', alpha=0.6, label='Data points')
plt.plot(lowess_result[:, 0], lowess_result[:, 1], color='red', label='LOWESS trend line')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Scatter Plot with LOWESS Trend Line (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

在这个例子中,我们使用了statsmodels库中的lowess函数来计算LOWESS趋势线。frac参数控制了平滑的程度,你可以根据需要调整这个值。

8. 多条趋势线的比较

有时,我们可能想要比较不同类型的趋势线,以确定哪一种最适合我们的数据。以下是一个同时显示线性、多项式和LOWESS趋势线的示例:

import matplotlib.pyplot as plt
import numpy as np
from scipy import stats
from statsmodels.nonparametric.smoothers_lowess import lowess

# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 10, 100)
y = 2 * x**2 - 5 * x + 3 + np.random.normal(0, 10, 100)

# 线性回归
slope, intercept, r_value, _, _ = stats.linregress(x, y)
linear_trend = slope * x + intercept

# 多项式回归
coeffs = np.polyfit(x, y, 2)
poly_trend = np.poly1d(coeffs)(x)

# LOWESS
lowess_result = lowess(y, x, frac=0.6)

# 绘制散点图和趋势线
plt.figure(figsize=(12, 7))
plt.scatter(x, y, color='blue', alpha=0.6, label='Data points')
plt.plot(x, linear_trend, color='red', label=f'Linear (R² = {r_value**2:.2f})')
plt.plot(x, poly_trend, color='green', label='Polynomial (degree 2)')
plt.plot(lowess_result[:, 0], lowess_result[:, 1], color='purple', label='LOWESS')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Scatter Plot with Multiple Trend Lines (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

这个例子结合了前面几个例子中的技术,在同一个图上绘制了线性、多项式和LOWESS趋势线。这样的比较可以帮助我们更好地理解数据的结构和选择最合适的趋势线类型。

9. 自定义趋势线样式

Matplotlib提供了丰富的选项来自定义趋势线的外观。以下是一个展示如何自定义线条样式、颜色和标记的示例:

import matplotlib.pyplot as plt
import numpy as np
from scipy import stats

# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 10, 50)
y = 2 * x + 1 + np.random.normal(0, 1, 50)

# 计算线性回归
slope, intercept, r_value, _, _ = stats.linregress(x, y)
line = slope * x + intercept

# 绘制散点图和趋势线
plt.figure(figsize=(10, 6))
plt.scatter(x, y, color='blue', alpha=0.6, label='Data points')
plt.plot(x, line, color='red', linestyle='--', linewidth=2, 
         marker='o', markersize=5, markerfacecolor='yellow', markeredgecolor='red',
         label=f'Trend line (R² = {r_value**2:.2f})')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Scatter Plot with Customized Trend Line (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle=':', alpha=0.7)
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

在这个例子中,我们使用了以下参数来自定义趋势线:
linestyle='--': 设置线条样式为虚线
linewidth=2: 设置线条宽度
marker='o': 添加圆形标记
markersize=5: 设置标记大小
markerfacecolor='yellow': 设置标记填充颜色
markeredgecolor='red': 设置标记边缘颜色

这些参数可以根据需要进行调整,以创建视觉上更吸引人的趋势线。

10. 置信区间和预测区间

在绘制趋势线时,添加置信区间和预测区间可以提供更多关于模型不确定性的信息。以下是一个包含这些区间的线性回归示例:

import matplotlib.pyplot as plt
import numpy as np
from scipy import stats

# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 10, 50)
y = 2 * x + 1 + np.random.normal(0, 1, 50)

# 计算线性回归
slope, intercept, r_value, _, std_err = stats.linregress(x, y)
line = slope * x + intercept

# 计算置信区间和预测区间
def predict(x, slope, intercept):
    return slope * x + intercept

def confidence_interval(x, y, prediction, confidence=0.95):
    n = len(x)
    m = 2  # slope and intercept
    dof = n - m
    t = stats.t.ppf((1 + confidence) / 2, dof)
    residual = y - prediction
    std_error = np.sqrt(np.sum(residual**2) / dof)

    x_mean = np.mean(x)
    x_std = np.sqrt(np.sum((x - x_mean)**2))

    se = std_error * np.sqrt(1/n + (x - x_mean)**2 / x_std**2)
    ci = t * se
    pi = t * std_error * np.sqrt(1 + 1/n + (x - x_mean)**2 / x_std**2)

    return ci, pi

prediction = predict(x, slope, intercept)
ci, pi = confidence_interval(x, y, prediction)

# 绘制散点图、趋势线和区间
plt.figure(figsize=(12, 7))
plt.scatter(x, y, color='blue', alpha=0.6, label='Data points')
plt.plot(x, line, color='red', label=f'Trend line (R² = {r_value**2:.2f})')
plt.fill_between(x, prediction - ci, prediction + ci, color='gray', alpha=0.2, label='95% Confidence Interval')
plt.fill_between(x, prediction - pi, prediction + pi, color='lightgray', alpha=0.2, label='95% Prediction Interval')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Scatter Plot with Trend Line, Confidence and Prediction Intervals (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

在这个例子中,我们定义了函数来计算置信区间和预测区间。置信区间表示对真实回归线的估计的不确定性,而预测区间表示对新观测值的预测的不确定性。我们使用plt.fill_between()函数来绘制这些区间。

11. 分组数据的趋势线

有时,我们可能需要为不同类别的数据绘制单独的趋势线。以下是一个示例:

import matplotlib.pyplot as plt
import numpy as np
from scipy import stats

# 生成示例数据
np.random.seed(42)
x1 = np.linspace(0, 10, 50)
y1 = 2 * x1 + 1 + np.random.normal(0, 1, 50)
x2 = np.linspace(0, 10, 50)
y2 = 1.5 * x2 + 2 + np.random.normal(0, 1, 50)

# 计算线性回归
slope1, intercept1, r_value1, _, _ = stats.linregress(x1, y1)
slope2, intercept2, r_value2, _, _ = stats.linregress(x2, y2)
line1 = slope1 * x1 + intercept1
line2 = slope2 * x2 + intercept2

# 绘制散点图和趋势线
plt.figure(figsize=(12, 7))
plt.scatter(x1, y1, color='blue', alpha=0.6, label='Group 1')
plt.scatter(x2, y2, color='green', alpha=0.6, label='Group 2')
plt.plot(x1, line1, color='blue', linestyle='--', label=f'Group 1 trend (R² = {r_value1**2:.2f})')
plt.plot(x2, line2, color='green', linestyle='--', label=f'Group 2 trend (R² = {r_value2**2:.2f})')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Scatter Plot with Group-specific Trend Lines (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

这个例子展示了如何为两个不同的数据组绘制单独的趋势线。这种方法在比较不同组或类别的趋势时非常有用。

12. 带有误差条的趋势线

在某些情况下,我们可能想要在趋势线上显示误差条。以下是一个示例:

import matplotlib.pyplot as plt
import numpy as np
from scipy import stats

# 生成示例数据
np.random.seed(42)
x = np.linspace(0, 10, 10)
y = 2 * x + 1 + np.random.normal(0, 1, 10)
yerr = np.random.uniform(0.5, 1.5, 10)

# 计算加权线性回归
weights = 1 / yerr**2
slope, intercept, r_value, _, _ = stats.linregress(x, y, w=weights)
line = slope * x + intercept

# 绘制散点图、误差条和趋势线
plt.figure(figsize=(12, 7))
plt.errorbar(x, y, yerr=yerr, fmt='o', color='blue', alpha=0.6, label='Data points with errors')
plt.plot(x, line, color='red', label=f'Weighted trend line (R² = {r_value**2:.2f})')
plt.xlabel('X-axis (how2matplotlib.com)')
plt.ylabel('Y-axis (how2matplotlib.com)')
plt.title('Scatter Plot with Error Bars and Weighted Trend Line (how2matplotlib.com)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

在这个例子中,我们使用plt.errorbar()函数来绘制带有误差条的散点图。我们还使用了加权线性回归,其中权重与误差的平方成反比,这意味着误差较小的点在拟合过程中具有更大的影响。

13. 3D散点图的趋势面

虽然我们主要讨论了2D散点图,但Matplotlib也支持3D散点图和趋势面。以下是一个简单的示例:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D

# 生成示例数据
np.random.seed(42)
x = np.random.rand(100)
y = np.random.rand(100)
z = 2*x + 3*y + np.random.normal(0, 0.2, 100)

# 创建网格
xi = np.linspace(0, 1, 100)
yi = np.linspace(0, 1, 100)
X, Y = np.meshgrid(xi, yi)

# 计算趋势面
A = np.c_[np.ones(len(x)), x, y]
C, _, _, _ = np.linalg.lstsq(A, z, rcond=None)
Z = C[0] + C[1]*X + C[2]*Y

# 绘制3D散点图和趋势面
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, z, c='blue', alpha=0.6, label='Data points')
ax.plot_surface(X, Y, Z, alpha=0.5, cmap='viridis')
ax.set_xlabel('X-axis (how2matplotlib.com)')
ax.set_ylabel('Y-axis (how2matplotlib.com)')
ax.set_zlabel('Z-axis (how2matplotlib.com)')
ax.set_title('3D Scatter Plot with Trend Surface (how2matplotlib.com)')
plt.legend()
plt.show()

Output:

Matplotlib绘制散点图趋势线:全面指南与实例

这个例子展示了如何创建3D散点图并添加趋势面。我们使用np.linalg.lstsq()函数来计算最小二乘解,然后使用plot_surface()方法来绘制趋势面。

结论

本文详细介绍了如何使用Matplotlib绘制散点图趋势线,涵盖了从基本的线性趋势线到更复杂的非线性趋势线,以及如何自定义趋势线的外观和添加置信区间等高级主题。通过这些技术,你可以更好地理解和展示数据中的模式和关系。

记住,选择合适的趋势线类型取决于你的数据特性和分析目的。线性趋势线适用于简单的线性关系,而多项式或非参数方法(如LOWESS)可能更适合复杂的非线性关系。始终要批判性地评估趋势线的适用性,并考虑使用多种方法来验证你的结论。

最后,Matplotlib的灵活性意味着你可以进一步自定义这些图表以满足特定需求。通过组合不同的技术和方法,你可以创建既信息丰富又视觉吸引人的数据可视化。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程