活动公告

系统通知
05-18 21:22
系统通知
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,资源失效请在帖子内回复要求补档,会尽快处理!
10-23 09:31

全面掌握matplotlib线条宽度设置技巧从基础参数到高级应用提升数据可视化专业度

SunJu_FaceMall

3万

主题

2860

科技点

3万

积分

白金月票

碾压王

积分
32872

塔罗立华奏

<font color=白金月票" /> 发表于 2025-9-11 00:40:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
引言

Matplotlib是Python中最流行的数据可视化库之一,它提供了丰富的绘图功能,使用户能够创建各种静态、动态和交互式图表。在数据可视化中,线条宽度是一个看似简单却极为重要的参数,它直接影响图表的可读性、美观度和信息传达效果。合理设置线条宽度可以使数据趋势更加明显,关键信息更加突出,从而提升整个可视化的专业度和表现力。本文将全面介绍matplotlib中线条宽度设置的技巧,从基础参数到高级应用,帮助读者掌握这一关键技能,提升数据可视化的专业水准。

基础知识:linewidth参数的基本用法

在matplotlib中,线条宽度主要通过linewidth参数(或其缩写lw)来控制。这个参数接受浮点数值,表示线条的宽度(以点为单位)。默认情况下,matplotlib中的线条宽度为1.0。

基本语法
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y = np.sin(x)
  6. # 创建图表并设置线条宽度
  7. plt.figure(figsize=(10, 6))
  8. plt.plot(x, y, linewidth=2.5)  # 或使用 plt.plot(x, y, lw=2.5)
  9. plt.title('基本线条宽度设置示例')
  10. plt.xlabel('X轴')
  11. plt.ylabel('Y轴')
  12. plt.grid(True)
  13. plt.show()
复制代码

线条宽度的数值范围

理论上,linewidth可以接受任何正浮点数,但实际应用中,我们通常使用以下范围:

• 0.1 - 1.0:细线,适用于密集数据或背景参考线
• 1.0 - 2.0:标准线宽,适用于大多数常规图表
• 2.0 - 4.0:粗线,适用于需要强调的数据系列
• 4.0以上:特粗线,适用于特殊强调或某些特定图表类型

不同绘图函数中的线条宽度设置

matplotlib中不同的绘图函数可能有不同的参数名称来控制线条宽度,但大多支持linewidth或lw参数:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y = np.sin(x)
  6. # 创建子图
  7. fig, axes = plt.subplots(2, 2, figsize=(12, 10))
  8. # plot函数
  9. axes[0, 0].plot(x, y, linewidth=3, color='blue')
  10. axes[0, 0].set_title('plot函数 - linewidth=3')
  11. # step函数
  12. axes[0, 1].step(x, y, linewidth=2.5, color='green')
  13. axes[0, 1].set_title('step函数 - linewidth=2.5')
  14. # stem函数
  15. markerline, stemlines, baseline = axes[1, 0].stem(x, y, use_line_collection=True)
  16. plt.setp(stemlines, linewidth=1.5)  # 设置茎线宽度
  17. plt.setp(markerline, markersize=5)  # 设置标记大小
  18. axes[1, 0].set_title('stem函数 - 茎线linewidth=1.5')
  19. # errorbar函数
  20. y_err = 0.1 * np.abs(y)
  21. axes[1, 1].errorbar(x[::10], y[::10], yerr=y_err[::10], linewidth=2,
  22.                     capsize=5, capthick=1.5, color='red')
  23. axes[1, 1].set_title('errorbar函数 - linewidth=2')
  24. plt.tight_layout()
  25. plt.show()
复制代码

常用线条宽度设置:不同场景下的推荐值

在不同的数据可视化场景中,选择合适的线条宽度对于有效传达信息至关重要。以下是几种常见场景及其推荐的线条宽度设置。

时间序列图

时间序列图通常需要清晰展示数据随时间的变化趋势,推荐使用中等宽度的线条:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import pandas as pd
  4. # 创建时间序列数据
  5. dates = pd.date_range('20230101', periods=100)
  6. values = np.cumsum(np.random.randn(100) * 0.5)
  7. # 创建图表
  8. plt.figure(figsize=(12, 6))
  9. plt.plot(dates, values, linewidth=2.0, color='royalblue')
  10. plt.title('时间序列数据 - linewidth=2.0', fontsize=14)
  11. plt.xlabel('日期', fontsize=12)
  12. plt.ylabel('数值', fontsize=12)
  13. plt.grid(True, linestyle='--', alpha=0.6)
  14. plt.tight_layout()
  15. plt.show()
复制代码

多系列对比图

当需要在同一图表中展示多个数据系列时,通过不同的线条宽度可以增强区分度:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y1 = np.sin(x)
  6. y2 = np.cos(x)
  7. y3 = np.sin(x) * np.cos(x)
  8. # 创建图表
  9. plt.figure(figsize=(12, 6))
  10. plt.plot(x, y1, linewidth=2.5, label='sin(x)', color='blue')
  11. plt.plot(x, y2, linewidth=1.8, label='cos(x)', color='red')
  12. plt.plot(x, y3, linewidth=3.0, label='sin(x)*cos(x)', color='green')
  13. plt.title('多系列对比 - 不同线条宽度', fontsize=14)
  14. plt.xlabel('X轴', fontsize=12)
  15. plt.ylabel('Y轴', fontsize=12)
  16. plt.legend(fontsize=12)
  17. plt.grid(True, linestyle='--', alpha=0.6)
  18. plt.tight_layout()
  19. plt.show()
复制代码

参考线和网格线

参考线和网格线通常应该较细,以免干扰主要数据的展示:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y = np.sin(x) * np.exp(-x/5)
  6. # 创建图表
  7. plt.figure(figsize=(12, 6))
  8. plt.plot(x, y, linewidth=2.5, color='royalblue', label='数据')
  9. # 添加参考线
  10. plt.axhline(y=0, color='black', linestyle='-', linewidth=0.8, alpha=0.7)
  11. plt.axvline(x=np.pi, color='red', linestyle='--', linewidth=1.0, alpha=0.7, label='x=π')
  12. # 设置网格线
  13. plt.grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  14. plt.title('参考线和网格线设置', fontsize=14)
  15. plt.xlabel('X轴', fontsize=12)
  16. plt.ylabel('Y轴', fontsize=12)
  17. plt.legend(fontsize=12)
  18. plt.tight_layout()
  19. plt.show()
复制代码

强调特定数据点或区间

当需要强调图表中的特定数据点或区间时,可以使用较粗的线条:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y = np.sin(x)
  6. # 创建图表
  7. plt.figure(figsize=(12, 6))
  8. # 绘制完整数据,使用标准线宽
  9. plt.plot(x, y, linewidth=1.5, color='lightgray', label='完整数据')
  10. # 强调特定区间
  11. mask = (x >= 3) & (x <= 7)
  12. plt.plot(x[mask], y[mask], linewidth=4.0, color='red', label='强调区间')
  13. # 标记特殊点
  14. special_x = [np.pi/2, 3*np.pi/2]
  15. special_y = [np.sin(np.pi/2), np.sin(3*np.pi/2)]
  16. plt.scatter(special_x, special_y, s=100, color='blue', zorder=5, label='特殊点')
  17. plt.title('强调特定数据点和区间', fontsize=14)
  18. plt.xlabel('X轴', fontsize=12)
  19. plt.ylabel('Y轴', fontsize=12)
  20. plt.legend(fontsize=12)
  21. plt.grid(True, linestyle='--', alpha=0.6)
  22. plt.tight_layout()
  23. plt.show()
复制代码

高级应用:结合其他参数的线条宽度设置

线条宽度设置可以与其他参数结合使用,创造出更加丰富和专业的可视化效果。本节将介绍一些高级应用技巧。

结合颜色映射(colormap)设置线条宽度

可以根据数据值或其他变量动态调整线条宽度,创建更加信息丰富的可视化:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from matplotlib.collections import LineCollection
  4. # 创建数据
  5. x = np.linspace(0, 10, 500)
  6. y = np.sin(x) * np.exp(-x/10)
  7. # 创建点对
  8. points = np.array([x, y]).T.reshape(-1, 1, 2)
  9. segments = np.concatenate([points[:-1], points[1:]], axis=1)
  10. # 创建基于y值的线条宽度
  11. linewidths = 1 + 3 * np.abs(y[:-1])  # 宽度范围从1到4
  12. # 创建基于x值的颜色
  13. from matplotlib.colors import LinearSegmentedColormap
  14. colors = plt.cm.viridis(x[:-1] / x.max())
  15. # 创建LineCollection对象
  16. lc = LineCollection(segments, linewidths=linewidths, colors=colors)
  17. fig, ax = plt.subplots(figsize=(12, 6))
  18. ax.add_collection(lc)
  19. # 设置图表范围和标题
  20. ax.set_xlim(x.min(), x.max())
  21. ax.set_ylim(y.min() - 0.1, y.max() + 0.1)
  22. ax.set_title('结合颜色映射的动态线条宽度', fontsize=14)
  23. ax.set_xlabel('X轴', fontsize=12)
  24. ax.set_ylabel('Y轴', fontsize=12)
  25. # 添加颜色条
  26. sm = plt.cm.ScalarMappable(cmap=plt.cm.viridis, norm=plt.Normalize(0, 10))
  27. sm.set_array([])
  28. cbar = plt.colorbar(sm, ax=ax)
  29. cbar.set_label('X值', fontsize=12)
  30. plt.grid(True, linestyle='--', alpha=0.6)
  31. plt.tight_layout()
  32. plt.show()
复制代码

结合线型和标记样式

线条宽度与线型、标记样式的结合可以创造出更加多样化的视觉效果:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 30)
  5. y1 = np.sin(x)
  6. y2 = np.cos(x)
  7. y3 = np.sin(x) * np.cos(x)
  8. # 创建图表
  9. plt.figure(figsize=(12, 6))
  10. # 不同的线型、宽度和标记组合
  11. plt.plot(x, y1, linewidth=2.0, linestyle='-', marker='o',
  12.          markersize=6, markerfacecolor='white', markeredgewidth=1.5,
  13.          color='blue', label='实线+圆形标记')
  14. plt.plot(x, y2, linewidth=1.5, linestyle='--', marker='s',
  15.          markersize=7, markerfacecolor='white', markeredgewidth=1.2,
  16.          color='red', label='虚线+方形标记')
  17. plt.plot(x, y3, linewidth=2.5, linestyle=':', marker='^',
  18.          markersize=8, markerfacecolor='white', markeredgewidth=1.8,
  19.          color='green', label='点线+三角形标记')
  20. plt.title('结合线型和标记的线条宽度设置', fontsize=14)
  21. plt.xlabel('X轴', fontsize=12)
  22. plt.ylabel('Y轴', fontsize=12)
  23. plt.legend(fontsize=12)
  24. plt.grid(True, linestyle='--', alpha=0.6)
  25. plt.tight_layout()
  26. plt.show()
复制代码

结合透明度(alpha)设置

透明度与线条宽度的结合可以创建层次感,特别适用于展示重叠数据:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. np.random.seed(42)
  5. n_series = 5
  6. x = np.linspace(0, 10, 100)
  7. data = np.array([np.sin(x) + np.random.normal(0, 0.2, len(x)) for _ in range(n_series)])
  8. # 创建图表
  9. plt.figure(figsize=(12, 6))
  10. # 绘制多条线,逐渐增加线宽和透明度
  11. for i, y in enumerate(data):
  12.     alpha = 0.3 + 0.15 * i  # 透明度从0.3到0.9
  13.     linewidth = 1.0 + 0.5 * i  # 线宽从1.0到3.0
  14.     plt.plot(x, y, linewidth=linewidth, alpha=alpha,
  15.              color=plt.cm.viridis(i / n_series),
  16.              label=f'系列 {i+1}')
  17. # 计算并绘制平均值
  18. mean_values = np.mean(data, axis=0)
  19. plt.plot(x, mean_values, linewidth=3.5, color='red',
  20.          linestyle='--', label='平均值')
  21. plt.title('结合透明度的线条宽度设置', fontsize=14)
  22. plt.xlabel('X轴', fontsize=12)
  23. plt.ylabel('Y轴', fontsize=12)
  24. plt.legend(fontsize=12)
  25. plt.grid(True, linestyle='--', alpha=0.6)
  26. plt.tight_layout()
  27. plt.show()
复制代码

结合填充区域

线条宽度与填充区域的结合可以强调数据范围和趋势:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y1 = np.sin(x)
  6. y2 = np.sin(x) * 0.8
  7. y3 = np.sin(x) * 1.2
  8. # 创建图表
  9. plt.figure(figsize=(12, 6))
  10. # 填充区域
  11. plt.fill_between(x, y2, y3, color='lightblue', alpha=0.3, label='数据范围')
  12. # 主数据线
  13. plt.plot(x, y1, linewidth=3.0, color='blue', label='主数据线')
  14. # 边界线
  15. plt.plot(x, y2, linewidth=1.5, color='darkblue', linestyle='--', alpha=0.7, label='下边界')
  16. plt.plot(x, y3, linewidth=1.5, color='darkblue', linestyle='--', alpha=0.7, label='上边界')
  17. plt.title('结合填充区域的线条宽度设置', fontsize=14)
  18. plt.xlabel('X轴', fontsize=12)
  19. plt.ylabel('Y轴', fontsize=12)
  20. plt.legend(fontsize=12)
  21. plt.grid(True, linestyle='--', alpha=0.6)
  22. plt.tight_layout()
  23. plt.show()
复制代码

动态调整线条宽度:基于数据值的动态宽度

在某些情况下,我们可能需要根据数据值动态调整线条宽度,以突出显示数据的重要特征或变化。本节将介绍几种实现动态线条宽度的方法。

基于数据值的变化调整宽度
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from matplotlib.collections import LineCollection
  4. # 创建数据
  5. x = np.linspace(0, 10, 500)
  6. y = np.sin(x) * np.exp(-x/10)
  7. # 创建线段
  8. points = np.array([x, y]).T.reshape(-1, 1, 2)
  9. segments = np.concatenate([points[:-1], points[1:]], axis=1)
  10. # 基于y值的变化率计算线条宽度
  11. dy = np.abs(np.diff(y))
  12. # 归一化到0.5-4的范围
  13. linewidths = 0.5 + 3.5 * (dy - dy.min()) / (dy.max() - dy.min())
  14. # 创建LineCollection
  15. lc = LineCollection(segments, linewidths=linewidths, color='blue')
  16. fig, ax = plt.subplots(figsize=(12, 6))
  17. ax.add_collection(lc)
  18. # 设置图表范围和标题
  19. ax.set_xlim(x.min(), x.max())
  20. ax.set_ylim(y.min() - 0.1, y.max() + 0.1)
  21. ax.set_title('基于数据值变化率的动态线条宽度', fontsize=14)
  22. ax.set_xlabel('X轴', fontsize=12)
  23. ax.set_ylabel('Y轴', fontsize=12)
  24. # 添加颜色条表示线条宽度
  25. sm = plt.cm.ScalarMappable(cmap=plt.cm.Blues, norm=plt.Normalize(dy.min(), dy.max()))
  26. sm.set_array([])
  27. cbar = plt.colorbar(sm, ax=ax)
  28. cbar.set_label('变化率', fontsize=12)
  29. plt.grid(True, linestyle='--', alpha=0.6)
  30. plt.tight_layout()
  31. plt.show()
复制代码

基于数据重要性调整宽度
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from matplotlib.collections import LineCollection
  4. # 创建数据
  5. np.random.seed(42)
  6. x = np.linspace(0, 10, 200)
  7. # 创建一个基础信号
  8. base_signal = np.sin(x)
  9. # 添加一些随机噪声
  10. noise = np.random.normal(0, 0.1, len(x))
  11. # 创建重要性指标(这里用信号强度的绝对值)
  12. importance = np.abs(base_signal)
  13. # 最终信号
  14. y = base_signal + noise
  15. # 创建线段
  16. points = np.array([x, y]).T.reshape(-1, 1, 2)
  17. segments = np.concatenate([points[:-1], points[1:]], axis=1)
  18. # 基于重要性计算线条宽度
  19. # 重要性高的地方线条更粗
  20. linewidths = 0.8 + 3.2 * (importance[:-1] - importance.min()) / (importance.max() - importance.min())
  21. # 创建颜色映射,重要性高的地方颜色更暖
  22. colors = plt.cm.coolwarm(importance[:-1] / importance.max())
  23. # 创建LineCollection
  24. lc = LineCollection(segments, linewidths=linewidths, colors=colors)
  25. fig, ax = plt.subplots(figsize=(12, 6))
  26. ax.add_collection(lc)
  27. # 设置图表范围和标题
  28. ax.set_xlim(x.min(), x.max())
  29. ax.set_ylim(y.min() - 0.2, y.max() + 0.2)
  30. ax.set_title('基于数据重要性的动态线条宽度和颜色', fontsize=14)
  31. ax.set_xlabel('X轴', fontsize=12)
  32. ax.set_ylabel('Y轴', fontsize=12)
  33. # 添加颜色条表示重要性
  34. sm = plt.cm.ScalarMappable(cmap=plt.cm.coolwarm, norm=plt.Normalize(importance.min(), importance.max()))
  35. sm.set_array([])
  36. cbar = plt.colorbar(sm, ax=ax)
  37. cbar.set_label('重要性', fontsize=12)
  38. plt.grid(True, linestyle='--', alpha=0.6)
  39. plt.tight_layout()
  40. plt.show()
复制代码

基于数据密度调整宽度
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from scipy.stats import gaussian_kde
  4. from matplotlib.collections import LineCollection
  5. # 创建数据
  6. np.random.seed(42)
  7. # 生成一些随机点,但某些区域密度更高
  8. x = np.concatenate([
  9.     np.random.normal(2, 0.5, 100),
  10.     np.random.normal(5, 0.8, 200),
  11.     np.random.normal(8, 0.3, 80)
  12. ])
  13. y = np.concatenate([
  14.     np.random.normal(1, 0.3, 100),
  15.     np.random.normal(2, 0.5, 200),
  16.     np.random.normal(0.5, 0.2, 80)
  17. ])
  18. # 计算点的密度
  19. xy = np.vstack([x, y])
  20. kde = gaussian_kde(xy)
  21. density = kde(xy)
  22. # 按x值排序
  23. sort_idx = np.argsort(x)
  24. x_sorted = x[sort_idx]
  25. y_sorted = y[sort_idx]
  26. density_sorted = density[sort_idx]
  27. # 创建线段
  28. points = np.array([x_sorted, y_sorted]).T.reshape(-1, 1, 2)
  29. segments = np.concatenate([points[:-1], points[1:]], axis=1)
  30. # 基于密度计算线条宽度
  31. # 密度高的地方线条更粗
  32. linewidths = 0.5 + 4.5 * (density_sorted[:-1] - density_sorted.min()) / (density_sorted.max() - density_sorted.min())
  33. # 创建颜色映射
  34. colors = plt.cm.plasma(density_sorted[:-1] / density_sorted.max())
  35. # 创建LineCollection
  36. lc = LineCollection(segments, linewidths=linewidths, colors=colors)
  37. fig, ax = plt.subplots(figsize=(12, 6))
  38. ax.add_collection(lc)
  39. # 设置图表范围和标题
  40. ax.set_xlim(x.min() - 0.5, x.max() + 0.5)
  41. ax.set_ylim(y.min() - 0.5, y.max() + 0.5)
  42. ax.set_title('基于数据密度的动态线条宽度和颜色', fontsize=14)
  43. ax.set_xlabel('X轴', fontsize=12)
  44. ax.set_ylabel('Y轴', fontsize=12)
  45. # 添加颜色条表示密度
  46. sm = plt.cm.ScalarMappable(cmap=plt.cm.plasma, norm=plt.Normalize(density_sorted.min(), density_sorted.max()))
  47. sm.set_array([])
  48. cbar = plt.colorbar(sm, ax=ax)
  49. cbar.set_label('数据密度', fontsize=12)
  50. plt.grid(True, linestyle='--', alpha=0.6)
  51. plt.tight_layout()
  52. plt.show()
复制代码

不同图表类型的线条宽度设置

不同类型的图表对线条宽度有不同的要求和最佳实践。本节将介绍几种常见图表类型的线条宽度设置技巧。

折线图(Line Plot)

折线图是最常用的图表类型之一,适合展示连续数据的变化趋势:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y1 = np.sin(x)
  6. y2 = np.cos(x)
  7. y3 = np.sin(x) * np.cos(x)
  8. # 创建图表
  9. plt.figure(figsize=(12, 6))
  10. # 主数据线使用中等宽度
  11. plt.plot(x, y1, linewidth=2.5, color='blue', label='sin(x)')
  12. # 次要数据线使用稍细的宽度
  13. plt.plot(x, y2, linewidth=1.8, color='red', label='cos(x)')
  14. # 计算值使用较粗的宽度以强调
  15. plt.plot(x, y3, linewidth=3.0, color='green', label='sin(x)*cos(x)')
  16. # 添加参考线,使用细线
  17. plt.axhline(y=0, color='black', linestyle='--', linewidth=0.8, alpha=0.5)
  18. plt.title('折线图的线条宽度设置', fontsize=14)
  19. plt.xlabel('X轴', fontsize=12)
  20. plt.ylabel('Y轴', fontsize=12)
  21. plt.legend(fontsize=12)
  22. plt.grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  23. plt.tight_layout()
  24. plt.show()
复制代码

面积图(Area Plot)

面积图适合展示数据随时间的变化以及各部分占总体的比例:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y1 = np.sin(x) + 1
  6. y2 = np.cos(x) + 1
  7. y3 = np.sin(x) * np.cos(x) + 1
  8. # 创建图表
  9. plt.figure(figsize=(12, 6))
  10. # 填充区域
  11. plt.fill_between(x, 0, y1, color='blue', alpha=0.3, label='区域1')
  12. plt.fill_between(x, y1, y1+y2, color='green', alpha=0.3, label='区域2')
  13. plt.fill_between(x, y1+y2, y1+y2+y3, color='red', alpha=0.3, label='区域3')
  14. # 边界线使用中等宽度
  15. plt.plot(x, y1, linewidth=2.0, color='darkblue')
  16. plt.plot(x, y1+y2, linewidth=2.0, color='darkgreen')
  17. plt.plot(x, y1+y2+y3, linewidth=2.0, color='darkred')
  18. plt.title('面积图的线条宽度设置', fontsize=14)
  19. plt.xlabel('X轴', fontsize=12)
  20. plt.ylabel('Y轴', fontsize=12)
  21. plt.legend(fontsize=12)
  22. plt.grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  23. plt.tight_layout()
  24. plt.show()
复制代码

散点图与连线(Scatter Plot with Lines)

散点图与连线的结合适合展示数据点的分布和趋势:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. np.random.seed(42)
  5. x = np.linspace(0, 10, 30)
  6. y = np.sin(x) + np.random.normal(0, 0.2, len(x))
  7. # 创建图表
  8. plt.figure(figsize=(12, 6))
  9. # 连线使用中等宽度
  10. plt.plot(x, y, linewidth=1.8, color='gray', alpha=0.7, label='趋势线')
  11. # 数据点使用不同的标记大小和边框宽度
  12. plt.scatter(x, y, s=80, color='blue', alpha=0.8,
  13.             edgecolors='darkblue', linewidths=1.5, label='数据点')
  14. # 突出显示特定点
  15. special_idx = [5, 15, 25]
  16. plt.scatter(x[special_idx], y[special_idx], s=120, color='red',
  17.             edgecolors='darkred', linewidths=2.0, zorder=5, label='特殊点')
  18. plt.title('散点图与连线的线条宽度设置', fontsize=14)
  19. plt.xlabel('X轴', fontsize=12)
  20. plt.ylabel('Y轴', fontsize=12)
  21. plt.legend(fontsize=12)
  22. plt.grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  23. plt.tight_layout()
  24. plt.show()
复制代码

箱线图(Box Plot)

箱线图适合展示数据的分布情况,包括中位数、四分位数和异常值:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. np.random.seed(42)
  5. data = [np.random.normal(0, std, 100) for std in range(1, 4)]
  6. # 创建图表
  7. plt.figure(figsize=(10, 6))
  8. # 设置箱线图的各个部分的线条宽度
  9. boxprops = dict(linewidth=2.0, color='black')
  10. whiskerprops = dict(linewidth=1.5, color='black')
  11. capprops = dict(linewidth=1.5, color='black')
  12. medianprops = dict(linewidth=2.5, color='red')
  13. flierprops = dict(marker='o', markerfacecolor='green', markersize=8,
  14.                  markeredgecolor='darkgreen', markeredgewidth=1.0)
  15. # 绘制箱线图
  16. bp = plt.boxplot(data, patch_artist=True, boxprops=boxprops,
  17.                 whiskerprops=whiskerprops, capprops=capprops,
  18.                 medianprops=medianprops, flierprops=flierprops)
  19. # 设置箱体颜色
  20. colors = ['lightblue', 'lightgreen', 'lightpink']
  21. for patch, color in zip(bp['boxes'], colors):
  22.     patch.set_facecolor(color)
  23.     patch.set_alpha(0.7)
  24. plt.title('箱线图的线条宽度设置', fontsize=14)
  25. plt.xlabel('数据组', fontsize=12)
  26. plt.ylabel('数值', fontsize=12)
  27. plt.xticks([1, 2, 3], ['组1', '组2', '组3'])
  28. plt.grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  29. plt.tight_layout()
  30. plt.show()
复制代码

热力图(Heatmap)

热力图适合展示矩阵数据,虽然不直接使用线条,但边框线条的设置也很重要:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. np.random.seed(42)
  5. data = np.random.rand(10, 10)
  6. # 创建图表
  7. plt.figure(figsize=(10, 8))
  8. # 绘制热力图,设置单元格边框线宽
  9. im = plt.imshow(data, cmap='viridis')
  10. # 添加网格线,设置线宽
  11. plt.grid(True, which='both', color='white', linewidth=0.8)
  12. # 添加颜色条
  13. cbar = plt.colorbar(im)
  14. cbar.set_label('数值', fontsize=12)
  15. # 设置标题和标签
  16. plt.title('热力图的边框线条宽度设置', fontsize=14)
  17. plt.xlabel('X轴', fontsize=12)
  18. plt.ylabel('Y轴', fontsize=12)
  19. plt.tight_layout()
  20. plt.show()
复制代码

雷达图(Radar Chart)

雷达图适合展示多变量数据,线条宽度的设置可以增强可读性:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. categories = ['速度', '力量', '技巧', '耐力', '智力']
  5. N = len(categories)
  6. # 创建两个数据系列
  7. values1 = np.array([0.8, 0.6, 0.9, 0.7, 0.85])
  8. values2 = np.array([0.6, 0.8, 0.7, 0.9, 0.75])
  9. # 计算角度
  10. angles = np.linspace(0, 2 * np.pi, N, endpoint=False).tolist()
  11. # 闭合图形
  12. values1 = np.concatenate((values1, [values1[0]]))
  13. values2 = np.concatenate((values2, [values2[0]]))
  14. angles += angles[:1]
  15. # 创建图表
  16. fig, ax = plt.subplots(figsize=(10, 8), subplot_kw=dict(polar=True))
  17. # 绘制数据线,使用不同的线宽
  18. ax.plot(angles, values1, linewidth=2.5, color='blue', label='选手A')
  19. ax.fill(angles, values1, color='blue', alpha=0.25)
  20. ax.plot(angles, values2, linewidth=2.0, color='red', label='选手B')
  21. ax.fill(angles, values2, color='red', alpha=0.25)
  22. # 设置网格线,使用细线
  23. ax.grid(True, linewidth=0.5, color='gray', linestyle='--')
  24. # 设置标签
  25. ax.set_xticks(angles[:-1])
  26. ax.set_xticklabels(categories, fontsize=12)
  27. ax.set_title('雷达图的线条宽度设置', fontsize=14, y=1.1)
  28. ax.legend(loc='upper right', bbox_to_anchor=(1.2, 1.1), fontsize=12)
  29. plt.tight_layout()
  30. plt.show()
复制代码

最佳实践和技巧

在设置matplotlib线条宽度时,有一些最佳实践和技巧可以帮助我们创建更加专业和有效的数据可视化。本节将介绍这些实用技巧。

一致性原则

在整个可视化项目或报告中保持线条宽度的一致性非常重要,这有助于建立统一的视觉风格:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 定义全局线条宽度设置
  4. LINEWIDTHS = {
  5.     'thin': 0.8,      # 用于网格线、参考线等
  6.     'regular': 1.8,   # 用于常规数据线
  7.     'thick': 2.8,     # 用于强调的数据线
  8.     'emphasis': 4.0   # 用于特别强调的元素
  9. }
  10. # 创建数据
  11. x = np.linspace(0, 10, 100)
  12. y1 = np.sin(x)
  13. y2 = np.cos(x)
  14. # 创建子图
  15. fig, axes = plt.subplots(1, 2, figsize=(15, 6))
  16. # 第一个子图
  17. axes[0].plot(x, y1, linewidth=LINEWIDTHS['regular'], color='blue', label='sin(x)')
  18. axes[0].plot(x, y2, linewidth=LINEWIDTHS['regular'], color='red', label='cos(x)')
  19. axes[0].axhline(y=0, color='black', linestyle='--', linewidth=LINEWIDTHS['thin'], alpha=0.5)
  20. axes[0].set_title('图表1', fontsize=14)
  21. axes[0].legend()
  22. axes[0].grid(True, linestyle=':', linewidth=LINEWIDTHS['thin'], alpha=0.5)
  23. # 第二个子图
  24. axes[1].plot(x, y1 * y2, linewidth=LINEWIDTHS['thick'], color='green', label='sin(x)*cos(x)')
  25. axes[1].axhline(y=0, color='black', linestyle='--', linewidth=LINEWIDTHS['thin'], alpha=0.5)
  26. axes[1].set_title('图表2', fontsize=14)
  27. axes[1].legend()
  28. axes[1].grid(True, linestyle=':', linewidth=LINEWIDTHS['thin'], alpha=0.5)
  29. plt.tight_layout()
  30. plt.show()
复制代码

层次感原则

通过不同的线条宽度创建视觉层次,引导观众的注意力:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y = np.sin(x) * np.exp(-x/10)
  6. # 创建图表
  7. plt.figure(figsize=(12, 6))
  8. # 背景信息 - 最细的线
  9. plt.plot(x, np.sin(x), linewidth=0.8, color='lightgray', alpha=0.7, linestyle='--', label='基础信号')
  10. # 次要信息 - 中等线宽
  11. plt.plot(x, np.exp(-x/10), linewidth=1.5, color='gray', alpha=0.7, label='衰减因子')
  12. # 主要信息 - 最粗的线
  13. plt.plot(x, y, linewidth=3.0, color='blue', label='合成信号')
  14. # 特殊点标记 - 粗线框
  15. special_x = [np.pi/2, 3*np.pi/2]
  16. special_y = [np.sin(np.pi/2) * np.exp(-np.pi/2/10), np.sin(3*np.pi/2) * np.exp(-3*np.pi/2/10)]
  17. plt.scatter(special_x, special_y, s=100, color='red',
  18.             edgecolors='darkred', linewidths=2.0, zorder=5, label='特殊点')
  19. plt.title('层次感原则应用', fontsize=14)
  20. plt.xlabel('X轴', fontsize=12)
  21. plt.ylabel('Y轴', fontsize=12)
  22. plt.legend(fontsize=12)
  23. plt.grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  24. plt.tight_layout()
  25. plt.show()
复制代码

对比度原则

确保线条宽度与背景、其他元素形成足够的对比度,提高可读性:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y1 = np.sin(x)
  6. y2 = np.cos(x)
  7. # 创建图表
  8. fig, axes = plt.subplots(1, 2, figsize=(15, 6))
  9. # 第一个子图 - 低对比度示例
  10. axes[0].plot(x, y1, linewidth=1.0, color='lightblue', label='sin(x)')
  11. axes[0].plot(x, y2, linewidth=1.0, color='lightcoral', label='cos(x)')
  12. axes[0].set_title('低对比度示例', fontsize=14)
  13. axes[0].legend()
  14. axes[0].grid(True, linestyle=':', linewidth=0.5, alpha=0.3)
  15. # 第二个子图 - 高对比度示例
  16. axes[1].plot(x, y1, linewidth=2.5, color='blue', label='sin(x)')
  17. axes[1].plot(x, y2, linewidth=2.5, color='red', label='cos(x)')
  18. axes[1].set_title('高对比度示例', fontsize=14)
  19. axes[1].legend()
  20. axes[1].grid(True, linestyle=':', linewidth=0.8, alpha=0.5)
  21. plt.tight_layout()
  22. plt.show()
复制代码

适应性原则

根据输出媒介和尺寸调整线条宽度:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y1 = np.sin(x)
  6. y2 = np.cos(x)
  7. # 定义不同尺寸下的线条宽度
  8. def get_linewidths(fig_size):
  9.     base_width = max(1.0, fig_size[0] / 5)
  10.     return {
  11.         'thin': base_width * 0.5,
  12.         'regular': base_width,
  13.         'thick': base_width * 1.5,
  14.         'emphasis': base_width * 2.0
  15.     }
  16. # 创建不同尺寸的图表
  17. fig_sizes = [(8, 6), (12, 6), (16, 8)]
  18. titles = ['小尺寸图表', '中等尺寸图表', '大尺寸图表']
  19. fig, axes = plt.subplots(1, 3, figsize=(20, 6))
  20. for i, (fig_size, title) in enumerate(zip(fig_sizes, titles)):
  21.     # 获取适合当前尺寸的线条宽度
  22.     linewidths = get_linewidths(fig_size)
  23.    
  24.     # 在对应的子图上绘制
  25.     axes[i].plot(x, y1, linewidth=linewidths['regular'], color='blue', label='sin(x)')
  26.     axes[i].plot(x, y2, linewidth=linewidths['regular'], color='red', label='cos(x)')
  27.     axes[i].axhline(y=0, color='black', linestyle='--', linewidth=linewidths['thin'], alpha=0.5)
  28.     axes[i].set_title(title, fontsize=14)
  29.     axes[i].legend()
  30.     axes[i].grid(True, linestyle=':', linewidth=linewidths['thin'], alpha=0.5)
  31. plt.tight_layout()
  32. plt.show()
复制代码

可访问性原则

考虑色盲用户和其他视觉障碍用户,确保线条宽度足够区分不同数据系列:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. # 创建数据
  4. x = np.linspace(0, 10, 100)
  5. y1 = np.sin(x)
  6. y2 = np.cos(x)
  7. y3 = np.sin(x) * np.cos(x)
  8. # 创建图表
  9. fig, axes = plt.subplots(1, 2, figsize=(15, 6))
  10. # 第一个子图 - 仅依赖颜色区分
  11. axes[0].plot(x, y1, linewidth=1.8, color='blue', label='sin(x)')
  12. axes[0].plot(x, y2, linewidth=1.8, color='red', label='cos(x)')
  13. axes[0].plot(x, y3, linewidth=1.8, color='green', label='sin(x)*cos(x)')
  14. axes[0].set_title('仅依赖颜色区分', fontsize=14)
  15. axes[0].legend()
  16. axes[0].grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  17. # 第二个子图 - 结合线条宽度和样式区分
  18. axes[1].plot(x, y1, linewidth=2.5, color='black', linestyle='-', label='sin(x)')
  19. axes[1].plot(x, y2, linewidth=1.8, color='black', linestyle='--', label='cos(x)')
  20. axes[1].plot(x, y3, linewidth=3.0, color='black', linestyle=':', label='sin(x)*cos(x)')
  21. axes[1].set_title('结合线条宽度和样式区分', fontsize=14)
  22. axes[1].legend()
  23. axes[1].grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  24. plt.tight_layout()
  25. plt.show()
复制代码

案例分析:真实数据可视化中的线条宽度应用

为了更好地理解线条宽度在实际数据可视化中的应用,本节将通过几个真实案例进行分析,展示如何通过合理的线条宽度设置提升数据可视化的专业度和有效性。

案例一:股票价格分析

在金融数据可视化中,合理的线条宽度设置可以帮助投资者更清晰地识别价格趋势和关键点:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import pandas as pd
  4. from datetime import datetime, timedelta
  5. # 创建模拟股票数据
  6. np.random.seed(42)
  7. start_date = datetime(2022, 1, 1)
  8. dates = [start_date + timedelta(days=i) for i in range(365)]
  9. prices = 100 + np.cumsum(np.random.randn(365) * 0.5)
  10. volumes = 1000000 + np.random.randint(-500000, 500000, 365)
  11. # 创建DataFrame
  12. df = pd.DataFrame({'Date': dates, 'Price': prices, 'Volume': volumes})
  13. # 计算20日和50日移动平均线
  14. df['MA20'] = df['Price'].rolling(window=20).mean()
  15. df['MA50'] = df['Price'].rolling(window=50).mean()
  16. # 创建图表
  17. fig, axes = plt.subplots(2, 1, figsize=(14, 10), gridspec_kw={'height_ratios': [3, 1]})
  18. # 价格和移动平均线
  19. axes[0].plot(df['Date'], df['Price'], linewidth=1.8, color='black', label='股票价格')
  20. axes[0].plot(df['Date'], df['MA20'], linewidth=2.0, color='blue', label='20日移动平均')
  21. axes[0].plot(df['Date'], df['MA50'], linewidth=2.5, color='red', label='50日移动平均')
  22. # 标记重要点(例如:移动平均线交叉点)
  23. golden_cross = []
  24. death_cross = []
  25. for i in range(50, len(df)):
  26.     if df['MA20'].iloc[i-1] < df['MA50'].iloc[i-1] and df['MA20'].iloc[i] > df['MA50'].iloc[i]:
  27.         golden_cross.append(i)
  28.     elif df['MA20'].iloc[i-1] > df['MA50'].iloc[i-1] and df['MA20'].iloc[i] < df['MA50'].iloc[i]:
  29.         death_cross.append(i)
  30. if golden_cross:
  31.     axes[0].scatter(df['Date'].iloc[golden_cross], df['Price'].iloc[golden_cross],
  32.                    s=100, color='gold', edgecolors='orange', linewidths=2.0,
  33.                    zorder=5, label='金叉')
  34. if death_cross:
  35.     axes[0].scatter(df['Date'].iloc[death_cross], df['Price'].iloc[death_cross],
  36.                    s=100, color='darkred', edgecolors='black', linewidths=2.0,
  37.                    zorder=5, label='死叉')
  38. axes[0].set_title('股票价格分析', fontsize=16)
  39. axes[0].set_ylabel('价格', fontsize=12)
  40. axes[0].legend(fontsize=12)
  41. axes[0].grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  42. # 成交量
  43. axes[1].bar(df['Date'], df['Volume'], width=1, color='gray', alpha=0.6)
  44. axes[1].set_title('成交量', fontsize=14)
  45. axes[1].set_ylabel('成交量', fontsize=12)
  46. axes[1].grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  47. plt.tight_layout()
  48. plt.show()
复制代码

案例二:气候变化趋势分析

在环境数据可视化中,线条宽度的设置可以突出长期趋势和短期波动:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import pandas as pd
  4. from datetime import datetime, timedelta
  5. # 创建模拟温度数据
  6. np.random.seed(42)
  7. start_date = datetime(1980, 1, 1)
  8. dates = [start_date + timedelta(days=i*30) for i in range(480)]  # 40年的月度数据
  9. # 创建基础温度趋势(模拟全球变暖)
  10. base_temp = 14 + 0.02 * np.arange(len(dates))  # 每年增加约0.24度
  11. # 添加季节性变化
  12. seasonal = 3 * np.sin(2 * np.pi * np.arange(len(dates)) / 12)
  13. # 添加随机波动
  14. random_fluctuation = np.random.normal(0, 0.5, len(dates))
  15. # 合成最终温度数据
  16. temperatures = base_temp + seasonal + random_fluctuation
  17. # 创建DataFrame
  18. df = pd.DataFrame({'Date': dates, 'Temperature': temperatures})
  19. # 计算年度平均温度
  20. df['Year'] = df['Date'].dt.year
  21. yearly_avg = df.groupby('Year')['Temperature'].mean().reset_index()
  22. # 创建图表
  23. fig, axes = plt.subplots(2, 1, figsize=(14, 10), gridspec_kw={'height_ratios': [2, 1]})
  24. # 月度温度数据
  25. axes[0].plot(df['Date'], df['Temperature'], linewidth=0.8, color='lightblue', alpha=0.7, label='月度温度')
  26. # 5年移动平均
  27. df['5yr_MA'] = df['Temperature'].rolling(window=60).mean()
  28. axes[0].plot(df['Date'], df['5yr_MA'], linewidth=2.5, color='red', label='5年移动平均')
  29. # 年度平均温度
  30. yearly_dates = pd.to_datetime(yearly_avg['Year'], format='%Y')
  31. axes[1].bar(yearly_dates, yearly_avg['Temperature'] - 14, width=365, color='coral', alpha=0.7)
  32. axes[1].axhline(y=0, color='black', linestyle='-', linewidth=1.0)
  33. # 添加趋势线
  34. z = np.polyfit(range(len(yearly_avg)), yearly_avg['Temperature'] - 14, 1)
  35. p = np.poly1d(z)
  36. axes[1].plot(yearly_dates, p(range(len(yearly_avg))), linewidth=2.0, color='darkred', linestyle='--', label='温度异常趋势')
  37. axes[0].set_title('全球温度变化趋势分析', fontsize=16)
  38. axes[0].set_ylabel('温度 (°C)', fontsize=12)
  39. axes[0].legend(fontsize=12)
  40. axes[0].grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  41. axes[1].set_title('年度温度异常(相对于1980年平均值)', fontsize=14)
  42. axes[1].set_ylabel('温度异常 (°C)', fontsize=12)
  43. axes[1].legend(fontsize=12)
  44. axes[1].grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  45. plt.tight_layout()
  46. plt.show()
复制代码

案例三:多变量性能比较

在比较多个变量或实体的性能时,通过线条宽度的设置可以增强可读性和专业感:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. import pandas as pd
  4. # 创建模拟性能数据
  5. np.random.seed(42)
  6. years = np.arange(2010, 2023)
  7. categories = ['产品A', '产品B', '产品C', '产品D']
  8. # 为每个产品创建性能数据
  9. performance_data = {}
  10. for i, category in enumerate(categories):
  11.     # 创建基础趋势
  12.     base_trend = 50 + 10 * i + 5 * (years - 2010) / 10
  13.    
  14.     # 添加随机波动
  15.     fluctuation = np.random.normal(0, 3, len(years))
  16.    
  17.     # 合成最终数据
  18.     performance_data[category] = base_trend + fluctuation
  19. # 创建DataFrame
  20. df = pd.DataFrame(performance_data)
  21. df['Year'] = years
  22. # 创建图表
  23. plt.figure(figsize=(14, 8))
  24. # 绘制各产品性能线,使用不同的线宽
  25. for i, category in enumerate(categories):
  26.     # 主要产品使用较粗的线
  27.     if category == '产品A':
  28.         plt.plot(df['Year'], df[category], linewidth=3.0, color='blue',
  29.                 label=category, marker='o', markersize=6)
  30.     # 次要产品使用中等线宽
  31.     elif category == '产品B':
  32.         plt.plot(df['Year'], df[category], linewidth=2.5, color='red',
  33.                 label=category, marker='s', markersize=5)
  34.     # 其他产品使用较细的线
  35.     else:
  36.         plt.plot(df['Year'], df[category], linewidth=1.8,
  37.                 color=plt.cm.tab10(i), label=category, marker='^', markersize=4)
  38. # 添加市场平均线
  39. market_avg = df[categories].mean(axis=1)
  40. plt.plot(df['Year'], market_avg, linewidth=2.0, color='black',
  41.         linestyle='--', label='市场平均')
  42. # 添加目标线
  43. target = 70
  44. plt.axhline(y=target, color='green', linestyle=':', linewidth=2.0,
  45.            alpha=0.7, label='目标')
  46. # 标记重要事件
  47. important_years = [2015, 2019, 2021]
  48. for year in important_years:
  49.     plt.axvline(x=year, color='gray', linestyle='-', linewidth=0.8, alpha=0.5)
  50.     plt.text(year, plt.ylim()[1] * 0.95, f'事件\n{year}',
  51.             ha='center', va='top', fontsize=9)
  52. plt.title('产品性能比较分析', fontsize=16)
  53. plt.xlabel('年份', fontsize=12)
  54. plt.ylabel('性能指标', fontsize=12)
  55. plt.legend(fontsize=12)
  56. plt.grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  57. # 添加数据来源注释
  58. plt.annotate('数据来源:公司内部数据', xy=(0.98, 0.02), xycoords='axes fraction',
  59.             ha='right', va='bottom', fontsize=9, alpha=0.7)
  60. plt.tight_layout()
  61. plt.show()
复制代码

案例四:科学实验数据可视化

在科学研究中,精确的数据可视化对结果展示至关重要,线条宽度的设置需要兼顾精确性和美观性:
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from scipy import stats
  4. # 创建模拟实验数据
  5. np.random.seed(42)
  6. x = np.linspace(0, 10, 50)
  7. # 理论模型
  8. def theoretical_model(x, a, b, c):
  9.     return a * np.exp(-b * x) * np.sin(c * x)
  10. # 真实参数
  11. true_params = [5.0, 0.2, 2.0]
  12. y_true = theoretical_model(x, *true_params)
  13. # 添加测量误差
  14. measurement_error = 0.2
  15. y_measured = y_true + np.random.normal(0, measurement_error, len(x))
  16. # 拟合模型
  17. params, covariance = stats.curve_fit(theoretical_model, x, y_measured, p0=[4, 0.3, 1.5])
  18. y_fit = theoretical_model(x, *params)
  19. # 计算置信区间
  20. residuals = y_measured - y_fit
  21. std_err = np.sqrt(np.diag(covariance))
  22. n_bootstraps = 100
  23. bootstrapped_params = []
  24. for _ in range(n_bootstraps):
  25.     # 创建重采样数据集
  26.     indices = np.random.randint(0, len(x), len(x))
  27.     x_bs = x[indices]
  28.     y_bs = y_measured[indices]
  29.    
  30.     # 拟合模型
  31.     try:
  32.         params_bs, _ = stats.curve_fit(theoretical_model, x_bs, y_bs, p0=params)
  33.         bootstrapped_params.append(params_bs)
  34.     except:
  35.         pass
  36. bootstrapped_params = np.array(bootstrapped_params)
  37. lower_bound = np.array([theoretical_model(x, *p) for p in
  38.                        [params - 1.96 * std_err] * len(x)])
  39. upper_bound = np.array([theoretical_model(x, *p) for p in
  40.                        [params + 1.96 * std_err] * len(x)])
  41. # 创建图表
  42. plt.figure(figsize=(12, 8))
  43. # 测量数据点
  44. plt.scatter(x, y_measured, s=40, color='blue', alpha=0.7,
  45.            edgecolors='darkblue', linewidths=1.0, label='测量数据', zorder=5)
  46. # 真实模型(理论值)
  47. plt.plot(x, y_true, linewidth=2.5, color='green', linestyle='--',
  48.         alpha=0.7, label='真实模型')
  49. # 拟合模型
  50. plt.plot(x, y_fit, linewidth=3.0, color='red', label='拟合模型')
  51. # 置信区间
  52. plt.fill_between(x, lower_bound, upper_bound, color='red', alpha=0.2,
  53.                label='95% 置信区间')
  54. # 误差条(选择性显示一些点)
  55. error_indices = np.arange(0, len(x), 5)
  56. plt.errorbar(x[error_indices], y_measured[error_indices],
  57.             yerr=measurement_error, fmt='none', ecolor='gray',
  58.             elinewidth=1.0, capsize=3, capthick=1.0, alpha=0.7)
  59. # 添加拟合参数文本
  60. param_text = f'拟合参数:\na = {params[0]:.2f} ± {std_err[0]:.2f}\n' \
  61.             f'b = {params[1]:.2f} ± {std_err[1]:.2f}\n' \
  62.             f'c = {params[2]:.2f} ± {std_err[2]:.2f}'
  63. plt.annotate(param_text, xy=(0.98, 0.98), xycoords='axes fraction',
  64.             ha='right', va='top', fontsize=10,
  65.             bbox=dict(boxstyle='round,pad=0.5', fc='white', alpha=0.8))
  66. plt.title('科学实验数据分析', fontsize=16)
  67. plt.xlabel('自变量 X', fontsize=12)
  68. plt.ylabel('因变量 Y', fontsize=12)
  69. plt.legend(fontsize=12)
  70. plt.grid(True, linestyle=':', linewidth=0.5, alpha=0.5)
  71. # 添加R²值
  72. ss_res = np.sum((y_measured - y_fit) ** 2)
  73. ss_tot = np.sum((y_measured - np.mean(y_measured)) ** 2)
  74. r_squared = 1 - (ss_res / ss_tot)
  75. plt.text(0.02, 0.02, f'R² = {r_squared:.4f}', transform=plt.gca().transAxes,
  76.         fontsize=10, bbox=dict(boxstyle='round,pad=0.3', fc='white', alpha=0.8))
  77. plt.tight_layout()
  78. plt.show()
复制代码

总结

线条宽度是matplotlib中一个看似简单却极为重要的参数,它直接影响着数据可视化的效果和专业度。通过本文的详细介绍,我们从基础参数设置到高级应用技巧,全面探讨了matplotlib线条宽度的各种用法。

关键要点回顾

1. 基础知识:linewidth参数(或缩写lw)是控制线条宽度的核心参数,接受浮点数值,默认为1.0。
2. 场景应用:不同类型的图表和数据场景需要不同的线条宽度设置。例如,时间序列图适合使用中等宽度线条,参考线和网格线应使用较细的线条,而需要强调的数据则应使用较粗的线条。
3. 高级技巧:线条宽度可以与其他参数如颜色、透明度、线型等结合使用,创造出更加丰富和专业的可视化效果。特别是通过LineCollection对象,可以实现基于数据值的动态线条宽度设置。
4. 最佳实践:在设置线条宽度时,应遵循一致性原则、层次感原则、对比度原则、适应性原则和可访问性原则,以确保可视化既美观又有效。
5. 案例分析:通过股票价格分析、气候变化趋势、多变量性能比较和科学实验数据可视化等真实案例,我们展示了线条宽度在实际应用中的重要性和灵活性。

基础知识:linewidth参数(或缩写lw)是控制线条宽度的核心参数,接受浮点数值,默认为1.0。

场景应用:不同类型的图表和数据场景需要不同的线条宽度设置。例如,时间序列图适合使用中等宽度线条,参考线和网格线应使用较细的线条,而需要强调的数据则应使用较粗的线条。

高级技巧:线条宽度可以与其他参数如颜色、透明度、线型等结合使用,创造出更加丰富和专业的可视化效果。特别是通过LineCollection对象,可以实现基于数据值的动态线条宽度设置。

最佳实践:在设置线条宽度时,应遵循一致性原则、层次感原则、对比度原则、适应性原则和可访问性原则,以确保可视化既美观又有效。

案例分析:通过股票价格分析、气候变化趋势、多变量性能比较和科学实验数据可视化等真实案例,我们展示了线条宽度在实际应用中的重要性和灵活性。

实用建议

1. 建立风格指南:对于长期项目或团队协作,建议建立统一的线条宽度风格指南,确保可视化的一致性。
2. 考虑输出媒介:根据可视化最终的输出媒介(屏幕显示、打印、网页等)调整线条宽度,确保最佳效果。
3. 注重可访问性:不仅仅依赖颜色区分不同数据系列,结合线条宽度和样式,使色盲用户和其他视觉障碍用户也能正确理解可视化内容。
4. 适度使用:避免过度使用不同线条宽度,以免造成视觉混乱。通常在一个图表中,线条宽度的变化应控制在3-4个层次内。
5. 反复试验:最佳的线条宽度设置往往需要根据具体数据和可视化目标进行反复试验和调整。

建立风格指南:对于长期项目或团队协作,建议建立统一的线条宽度风格指南,确保可视化的一致性。

考虑输出媒介:根据可视化最终的输出媒介(屏幕显示、打印、网页等)调整线条宽度,确保最佳效果。

注重可访问性:不仅仅依赖颜色区分不同数据系列,结合线条宽度和样式,使色盲用户和其他视觉障碍用户也能正确理解可视化内容。

适度使用:避免过度使用不同线条宽度,以免造成视觉混乱。通常在一个图表中,线条宽度的变化应控制在3-4个层次内。

反复试验:最佳的线条宽度设置往往需要根据具体数据和可视化目标进行反复试验和调整。

通过掌握matplotlib线条宽度的设置技巧,你可以显著提升数据可视化的专业度和表现力,使数据故事更加生动有力。希望本文能为你的数据可视化之旅提供有价值的指导和启发。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则