← 返回Book 2目录
第08章

线图

Line Plots · 连续数据的可视化

从基础到艺术创作,掌握线图的12种技法

📈 章节概览

线图是展示连续数据变化趋势的最佳工具。本章系统讲解线图的12种高级技法, 包括颗粒度控制、阶跃图、火柴梗图、参考线、面具、交点标注、极值标记、 色谱着色、分段渲染、网格绘制,以及用线条创作生成艺术。

📊
基础技法
颗粒度、阶跃、火柴梗
🎯
增强标注
参考线、交点、极值
🎨
视觉编码
面具、色谱、分段渲染
✨
生成艺术
网格、三角形、创意线条

8.1 平面线图颗粒度

控制采样密度,理解Nyquist-Shannon采样定理

📊 线图颗粒度实验室(Line Granularity Lab)

通过调整采样点数,理解颗粒度对曲线平滑度的影响

0.03.16.39.412.650 个采样点

🧪 探索建议

  • • 拖动滑块改变采样点数,观察曲线变化
  • • 点数太少→曲线失真;点数太多→计算冗余
  • • 切换函数类型,体验不同函数的采样需求
  • • 开启"显示点"查看实际采样位置
✅
颗粒度评分: 100/100
当前: 50点 × sin函数
✅ 采样点数适中,曲线平滑
50
粗糙(5)平滑(200)
线条粗细2px

⚡ 性能考量

当前数据点: 50
计算复杂度: O(n)
渲染元素: 1

📚 采样理论(Sampling Theory)

Nyquist-Shannon 采样定理
要完整还原信号,采样率必须至少是信号最高频率的2倍。 对于正弦波 sin(x),理论上每周期至少需要2个点,但实际需要更多以保证平滑。
采样点数建议
  • • 简单函数(如sin、cos):30-50点
  • • 中等复杂度:50-100点
  • • 快速变化/尖锐:100-200点
  • • 平滑艺术曲线:200+点
欠采样问题
采样点太少会导致锯齿状曲线、失真、 甚至混叠(Aliasing)——高频信号被错误地表示为低频。
过采样权衡
采样点过多虽然曲线更平滑,但会:
  • • 增加计算时间
  • • 占用更多内存
  • • 文件体积变大
需要在视觉质量和性能间平衡。
🎯 学习目标:通过动手调整采样点数,建立"采样率→曲线质量"的直觉。 理解采样定理的实际意义,学会为不同函数选择合适的颗粒度。
📚 Python绘图代码(基于Ch08原文)
# ===== 示例1:线图颗粒度对比 =====
import matplotlib.pyplot as plt
import numpy as np

# 低颗粒度:9个点
x_low = np.linspace(0, 4*np.pi, 9)
y_low = np.sin(x_low)

fig, ax = plt.subplots(figsize=(5, 3))
plt.plot(x_low, y_low, '.--', ms=10, color='#0088FF')
ax.set_xlim((0, 4*np.pi))
ax.set_ylim((-1.2, 1.2))
ax.set_xlabel('x')
ax.set_ylabel('f(x)')
plt.show()

# 合理颗粒度:101个点
x_fine = np.linspace(0, 4*np.pi, 101)
y_fine = np.sin(x_fine)

fig, ax = plt.subplots(figsize=(5, 3))
plt.plot(x_fine, y_fine, color='#0088FF')  # 平滑曲线
ax.set_xlim((0, 4*np.pi))
ax.set_ylim((-1.2, 1.2))
ax.set_xlabel('x')
ax.set_ylabel('f(x)')
plt.show()


# ===== 示例2:阶跃图(step函数) =====
x_coarse = np.linspace(0, 4*np.pi, 25)
y_coarse = np.sin(x_coarse)

x_reference = np.linspace(0, 4*np.pi, 101)
y_reference = np.sin(x_reference)

fig, ax = plt.subplots(figsize=(5, 3))
plt.plot(x_reference, y_reference, '--', color='#888888')  # 参考线
plt.step(x_coarse, y_coarse, '.-', ms=10, color='#0088FF')  # 阶跃
# where参数:'pre'(向前填充), 'mid'(中间), 'post'(向后填充)

ax.set_xlabel('x')
ax.set_ylabel('f(x)')
plt.show()


# ===== 示例3:火柴梗图(stem函数) =====
# 绘制等差数列
n_array = np.arange(1, 21)
a_n = 1 + (n_array - 1) * 2  # 首项1,公差2

fig, ax = plt.subplots(figsize=(5, 3))
plt.stem(n_array, a_n)
ax.set_xlabel('$n$')
ax.set_ylabel('n-th term, $a_n$')
plt.show()

# 绘制二项分布PMF
from scipy.stats import binom
k_array = np.arange(0, 21)
pmf = binom.pmf(k_array, n=20, p=0.4)

plt.stem(k_array, pmf)
plt.xlabel('$x$')
plt.ylabel('PMF, $f_X(x)$')
plt.show()


# 💡 关键学习点:
# 1. linspace()控制采样点数:点数越多,曲线越平滑
# 2. plot()样式:'.-'点+虚线,'.--'点+虚线,纯线条
# 3. step()绘制阶跃图:where参数控制填充方向
# 4. stem()绘制火柴梗图:适合离散数据(数列、PMF)

8.2 阶跃函数:plt.step() 绘制离散值

理解三种阶跃模式的差异

• 在中点转折
0123450123456XY(0, 1)(1, 3)(2, 2)(3, 5)(4, 4)(5, 6)
Python代码:
import matplotlib.pyplot as plt
import numpy as np

x = np.array([0, 1, 2, 3, 4, 5])
y = np.array([1, 3, 2, 5, 4, 6])

# where参数控制阶跃方式
plt.step(x, y, where='mid', linewidth=2, color='blue')
plt.scatter(x, y, c='red', s=50, zorder=5)
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Step Function (where="mid")')
plt.grid(alpha=0.3)
plt.show()
💡 阶跃函数的应用:
• pre:数字信号处理中常用,值在下一个采样点前保持
• mid:直方图绘制,在区间中点转换
• post:控制系统中,输出在输入改变后立即响应
• 适合展示离散时间序列、数字信号、分段常数函数

8.3 火柴梗图:plt.stem() 展示离散数据

突出显示每个数据点的幅度

051015200123456x: 0 y: 3.00x: 1 y: 4.44x: 2 y: 5.52x: 3 y: 5.99x: 4 y: 5.73x: 5 y: 4.80x: 6 y: 3.42x: 7 y: 1.95x: 8 y: 0.73x: 9 y: 0.07x: 10 y: 0.12x: 11 y: 0.88x: 12 y: 2.16x: 13 y: 3.65x: 14 y: 4.97x: 15 y: 5.81x: 16 y: 5.97x: 17 y: 5.40x: 18 y: 4.24x: 19 y: 2.77x: 20 y: 1.37Sample IndexAmplitude
Python代码:
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 21)
y = np.sin(x * 0.5) * 3 + 3

# 绘制火柴梗图
plt.stem(x, y, 
         linefmt='purple',    # 茎的样式
         markerfmt='o',       # 标记样式
         basefmt='orange')  # 基线样式

plt.xlabel('Sample Index')
plt.ylabel('Amplitude')
plt.title('Stem Plot - Sine Wave')
plt.grid(alpha=0.3)
plt.show()
💡 火柴梗图的应用:
• 数字信号:展示离散时间信号的幅度
• 频谱分析:显示频率成分的强度
• 脉冲响应:系统对脉冲输入的响应
• 采样数据:突出每个采样点的值
• 相比普通线图,更强调数据的离散性

8.4 参考线:axhline / axvline 标记关键值

添加水平和垂直参考线辅助分析

06
010
024681001234563.05.0
Python代码:
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y = 2 + 2*np.sin(x*0.8) + np.cos(x*0.3)

# 绘制曲线
plt.plot(x, y, 'b-', linewidth=2.5, label='f(x)')

# 添加水平参考线
plt.axhline(y=3.0, color='hotpink', 
            linestyle='--', linewidth=2, label='y=3.0')

# 添加垂直参考线
plt.axvline(x=5.0, color='crimson', 
            linestyle='--', linewidth=2, label='x=5.0')

plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.grid(alpha=0.3)
plt.show()
💡 参考线的应用:
• 阈值标记:标出警戒线、目标值、平均值
• 区间划分:将数据分为不同区域
• 关键时刻:标记重要时间点或事件
• 比较基准:提供对比的参考标准
• 拖动滑块调整参考线位置,观察与曲线的关系

8.5 使用面具mask:选择性显示数据

根据条件筛选和突出显示特定数据段

15
显示 y > 3.0 的数据段
02468100123456
总数据点
101
符合条件的点
74
数据段数
2
Python代码:
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)
y = 3 + 2*np.sin(x*0.6)*np.cos(x*0.2)

# 创建mask
mask = y > 3.0

# 绘制完整曲线(灰色)
plt.plot(x, y, 'lightgray', linewidth=1.5, label='All data')

# 仅绘制满足条件的部分(红色高亮)
plt.plot(x[mask], y[mask], 'r-', linewidth=3, label='Masked data')

# 添加阈值线或区间
plt.axhline(3.0, color='red', linestyle='--', linewidth=2)

plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.show()
💡 Mask的应用:
• 异常检测:突出显示超出正常范围的数据
• 条件筛选:仅展示符合特定条件的数据段
• 数据清洗:过滤噪声或无效数据
• 区间分析:关注特定值域内的变化
• NumPy mask是强大的数组操作工具

8.6 交点标注:找出两条曲线的交叉位置

计算并标注曲线交点,辅助数据分析

-12
找到 3 个交点
02468100123456(0.98,3.42)(3.44,2.76)(8.69,3.24)f(x)g(x)交点
交点坐标:
P1: (0.983, 3.415)
P2: (3.436, 2.764)
P3: (8.691, 3.241)
Python代码:
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)
y1 = 2 + 2*np.sin(x*0.8)
y2 = 3 + 0.50*np.cos(x*0.6)

# 绘制两条曲线
plt.plot(x, y1, 'b-', linewidth=2.5, label='f(x)')
plt.plot(x, y2, 'g-', linewidth=2.5, label='g(x)')

# 找交点(符号变化法)
idx = np.where(np.diff(np.sign(y1 - y2)))[0]

# 标注交点
for i in idx:
    # 线性插值
    x_cross = x[i] + (x[i+1]-x[i])*(0-(y1[i]-y2[i]))/((y1[i+1]-y2[i+1])-(y1[i]-y2[i]))
    y_cross = np.interp(x_cross, x, y1)
    
    plt.plot(x_cross, y_cross, 'ro', markersize=8)
    plt.annotate(f'({x_cross:.2f}, {y_cross:.2f})', 
                xy=(x_cross, y_cross),
                xytext=(10, 10), textcoords='offset points')

plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.grid(alpha=0.3)
plt.show()
💡 交点分析的应用:
• 经济学:供需平衡点、盈亏平衡点
• 物理学:运动轨迹交叉、波的干涉
• 工程学:系统响应的临界点
• 金融学:均线交叉信号(金叉/死叉)
• 拖动滑块改变曲线形状,观察交点如何移动

8.11-8.12 生成艺术:用线条创作几何艺术

观察算法驱动的艺术创作过程,理解参数化设计

✨ 生成艺术动画器(Generative Art Animator)

观察线条逐步生成几何艺术的动态过程

步骤: 0 / 20
🔺 三角形
速度1x
线条数量20

🎨 观察要点

  • • 注意每条线的生成位置和角度
  • • 观察颜色如何随步骤变化(色相渐变)
  • • 暂停后可以仔细查看中间状态
  • • 不同模式展示不同的数学规律

🎭 艺术模式

📊 生成统计

已绘制线条0
完成度0%
当前颜色

📐 数学原理

等边三角形:三个顶点相隔120°, 通过旋转角度θ和递增半径r创造螺旋效果。

🎨 生成艺术技巧

  • • 色彩渐变:使用HSL色相循环
  • • 几何规律:基于数学公式
  • • 分层叠加:透明度0.8产生混色
  • • 对称美感:中心对称设计

📚 生成艺术(Generative Art)

🎲
算法驱动
通过代码和数学公式自动生成艺术作品,而非手工绘制
🔄
随机性与确定性
结合数学规律和随机元素,每次运行产生独特作品
✨
参数化设计
调整参数即可创造无限变化的视觉效果
🎯 应用领域
• NFT数字艺术作品
• 数据可视化美化
• 建筑设计参数化
• 品牌视觉识别系统
• 游戏程序化生成
• 交互装置艺术
📚 Python绘图代码(基于Ch08原文)
# ===== 示例4:参考线(axhline/axvline) =====
import matplotlib.pyplot as plt
import numpy as np

x_array = np.linspace(0, 4*np.pi, 101)
y_array = np.sin(x_array)

fig, ax = plt.subplots(figsize=(5, 3))
plt.plot(x_array, y_array, color='#0088FF')

# 水平参考线
plt.axhline(y=1, color='r', ls='--')
plt.axhline(y=0, color='r', ls='--')
plt.axhline(y=-1, color='r', ls='--')

# 竖直参考线
plt.axvline(x=np.pi, color='r', ls='--')
plt.axvline(x=2*np.pi, color='r', ls='--')
plt.axvline(x=3*np.pi, color='r', ls='--')

ax.set_xlabel('x')
ax.set_ylabel('f(x)')
plt.show()


# ===== 示例5:填充区域(fill_between) =====
# 填充曲线下方区域
fig, ax = plt.subplots(figsize=(5, 3))
plt.plot(x_array, y_array, color='#0088FF', linewidth=2)
plt.fill_between(x_array, y_array, 0, 
                 where=(y_array > 0), 
                 color='#0088FF', 
                 alpha=0.3)

ax.set_xlabel('x')
ax.set_ylabel('f(x)')
plt.show()


# ===== 示例6:多条曲线填充 =====
y1 = np.sin(x_array)
y2 = np.sin(2*x_array) * 0.5

fig, ax = plt.subplots(figsize=(5, 3))
plt.plot(x_array, y1, color='#0088FF', label='sin(x)')
plt.plot(x_array, y2, color='#FF6B00', label='0.5·sin(2x)')

# 填充两曲线之间区域
plt.fill_between(x_array, y1, y2, 
                 where=(y1 >= y2),
                 color='#0088FF', 
                 alpha=0.2)
plt.fill_between(x_array, y1, y2, 
                 where=(y1 < y2),
                 color='#FF6B00', 
                 alpha=0.2)

plt.legend()
plt.show()


# ===== 示例7:指定范围的参考线(hlines/vlines) =====
fig, ax = plt.subplots(figsize=(5, 3))
plt.plot(x_array, y_array, color='#0088FF')

# 指定范围的水平线
ax.hlines(y=1, xmin=np.pi/2-1, xmax=np.pi/2+1, 
         linewidth=2, color='r', ls='--')
ax.hlines(y=-1, xmin=3*np.pi/2-1, xmax=3*np.pi/2+1, 
         linewidth=2, color='r', ls='--')

# 指定范围的竖直线
ax.vlines(x=np.pi, ymin=-0.5, ymax=0.5, 
         linewidth=2, color='g', ls=':')

plt.show()


# 💡 关键学习点:
# 1. axhline()/axvline():绘制贯穿全图的参考线
# 2. hlines()/vlines():绘制指定范围的参考线
# 3. fill_between():填充曲线下方或两曲线之间区域
# 4. where参数:条件填充,只填充满足条件的部分

📚 章节总结

基础线图技法

  • ✓ 颗粒度控制:调整采样点数
  • ✓ 阶跃图:离散值的连续展示
  • ✓ 火柴梗图:突出每个数据点
  • ✓ 参考线:标记关键值

高级标注技法

  • ✓ 面具选择:条件筛选数据
  • ✓ 交点标注:曲线交叉点
  • ✓ 极值标记:最大/最小值
  • ✓ 色谱编码:多曲线区分

艺术创作

  • ✓ 分段渲染:不同区间不同样式
  • ✓ 网格绘制:规则图案
  • ✓ 几何艺术:三角形生成
  • ✓ 生成艺术:创意线条作品

💡 核心洞察: 线图不仅是数据可视化工具,更是艺术创作媒介。通过12种技法的组合运用, 可以创造出既科学严谨又视觉震撼的作品。从函数可视化到生成艺术, 线图展现了数学与美学的完美结合。

💻关键函数速查表

基础绘图

plt.plot(x, y, linewidth, linestyle, color)
plt.step(x, y, where='pre'|'post'|'mid')
plt.stem(x, y, linefmt, markerfmt, basefmt)

标注增强

plt.axhline(y, color, linestyle, linewidth)
plt.axvline(x, color, linestyle, linewidth)
plt.annotate(text, xy, xytext, arrowprops)

高级技法

mask = (condition)
y[mask] = value
cmap = plt.get_cmap('viridis')
colors = cmap(np.linspace(0, 1, n))

📂Python代码文件

本章内容对应以下Jupyter Notebook代码文件:

BK_2_Ch08_01.ipynb小节 8.1
BK_2_Ch08_02.ipynb小节 8.2
BK_2_Ch08_03.ipynb小节 8.3
BK_2_Ch08_04.ipynb小节 8.4
BK_2_Ch08_05.ipynb小节 8.5
BK_2_Ch08_06.ipynb小节 8.6
BK_2_Ch08_07.ipynb小节 8.7
BK_2_Ch08_08.ipynb小节 8.8
BK_2_Ch08_09.ipynb小节 8.9
BK_2_Ch08_10.ipynb小节 8.10
BK_2_Ch08_11.ipynb小节 8.11
BK_2_Ch08_12.ipynb小节 8.12
📁 代码位置:books/Book2_Beauty-of-Data-Visualization/Book2_Ch08_Python_Codes/

🎯线图应用场景

📈
时间序列
股票价格、气温变化、网站流量等随时间变化的数据
📐
函数可视化
数学函数、物理曲线、工程模拟结果的图形展示
🔬
科学实验
实验测量数据、传感器读数、信号处理结果
💹
趋势分析
市场趋势、用户增长、性能指标的变化趋势
🎨
生成艺术
算法艺术、几何图案、参数化设计作品
🔄
比较分析
多条曲线对比、AB测试结果、模型性能比较