引言:经济学图形化的重要性
在经济学分析中,图形是连接抽象理论与直观理解的桥梁。特别是需求分析,我们经常需要对比两种截然不同的经济现象:
需求的变化(Change in Demand)
:由非价格因素(如收入、偏好、替代品价格)引起的整条曲线的平移。
需求量的变化(Change in Quantity Demanded)
:由商品自身价格变动引起的沿着同一条曲线的点的移动。
虽然概念清晰,但如何用代码精确、美观地展示这种区别,往往需要细致的绘图技巧。本文将基于你提供的代码框架,进行深度的扩展和优化,不仅展示代码实现,更深入剖析每一个绘图步骤背后的逻辑,并提供更高级的定制化方案。
第一部分:基础代码详解与逐行剖析
我们将代码分为三个主要阶段:
环境配置
、
数据准备
、
绘图与标注
。
1. 环境配置与字体处理
在绘制包含中文的图表时,字体设置是第一步,也是最容易报错的一步。
import matplotlib.pyplot as plt
import numpy as np
# 设置中文字体
plt.rcParams[‘font.sans-serif’] = [‘SimHei’] # 指定黑体作为默认字体
plt.rcParams[‘axes.unicode_minus’] = False # 解决负号显示为方块的问题
plt.rcParams
: 这是 Matplotlib 的全局配置字典。如果不设置这一行,图表中的中文会显示为乱码(豆腐块)。
字体选择策略
:
Windows
: 通常使用
‘SimHei’
(黑体) 或
‘Microsoft YaHei’
(微软雅黑)。
MacOS
: 通常使用
‘Arial Unicode MS’
或
‘PingFang SC’
。
Linux
: 可能需要安装中文字体包,常用
‘WenQuanYi Micro Hei’
。
unicode_minus
: 这是一个小技巧,确保坐标轴上的负号(-)能正常显示,而不是变成奇怪的符号。
2. 数据准备:构建数学模型
需求曲线通常被建模为线性函数。为了演示,我们使用最简单的线性需求函数:
\(Q = a – bP\)
。
# 创建画布
fig, ax = plt.subplots(figsize=(10, 6))
# 数据准备
price = np.linspace(10, 90, 100) # 生成 10 到 90 之间的 100 个价格点
# 需求量计算
# D1: Q = 100 – P (截距为100,斜率为-1)
q1 = 100 – price
# D2: Q = 120 – P (截距为120,斜率为-1,代表需求增加)
q2 = 120 – price
np.linspace
: 生成平滑曲线的关键。如果只用几个离散点,画出来的线是折线段,不够美观。
斜率的意义
: 在这个模型中,两条曲线的斜率都是 -1(即价格每下降1元,需求量增加1单位)。这很重要,因为
曲线的移动(D1到D2)必须保持斜率不变
,仅仅是截距的变化。
3. 绘图与核心逻辑:区分“移动”与“平移”
这是代码中最关键的部分,我们需要通过视觉元素(颜色、线型、箭头、文字)来区分两种经济学概念。
A. 绘制曲线 (The Lines)
# 1. 绘制两种需求曲线
ax.plot(price, q1, label=’原始需求曲线 D1′, color=’blue’, linewidth=2)
ax.plot(price, q2, label=’需求增加后的曲线 D2′, color=’green’, linewidth=2, linestyle=’–‘)
视觉对比
: 实线(Solid)代表现状,虚线(Dashed)代表变化后。这种对比让读者一眼就能看出这是两条不同的曲线。
B. 标注“需求的变化” (曲线平移)
这对应经济学中的
非价格因素变动
(如收入增加、消费者偏好增强)。
# 2. 标注曲线的移动 (需求的变化)
# 逻辑:价格不变 (P=50),但需求量从 50 增加到 70
ax.annotate(‘需求增加\n(非价格因素导致)’,
xy=(50, 70), # 箭头终点 (D2上的点)
xytext=(30, 85), # 文本起点
arrowprops=dict(facecolor=’black’, shrink=0.05), # 黑色箭头
fontsize=10, ha=’center’)
xy
vs
xytext
: 这里构建了一个从文本指向数据点的箭头。
经济学含义
: 箭头是
水平
的(虽然有弯曲,但本质是横向跨越),强调在同一个价格水平下,数量发生了变化。这是整条曲线向右平移的视觉化表达。
C. 标注“需求量的变化” (沿曲线移动)
这对应经济学中的
价格效应
。
# 3. 标注沿着曲线的移动 (需求量的变化)
# 逻辑:在 D1 上,价格从 P=70 降到 P=30,导致 Q 从 30 增加到 70
ax.annotate(‘价格下降\n(沿着D1移动)’,
xy=(30, 70), # 箭头终点 (D1上的点D)
xytext=(15, 80), # 文本起点
arrowprops=dict(facecolor=’red’, shrink=0.05, alpha=0.6), # 红色箭头
fontsize=10, ha=’center’)
颜色区分
: 使用红色箭头,与黑色的“曲线移动”区分开。
路径
: 箭头在 D1 线上滑动,直观展示了价格下降导致数量上升的过程。
D. 标记关键点 (Scatter & Text)
为了让坐标更具体,我们标记出四个关键点:A, B, C, D。
# 4. 标记关键点
points_x = [50, 50, 70, 30]
points_y = [50, 70, 30, 70]
colors = [‘blue’, ‘green’, ‘blue’, ‘blue’]
ax.scatter(points_x, points_y, color=colors, zorder=5) # zorder确保点在线上方
ax.text(51, 48, ‘A’, fontsize=12, color=’blue’)
ax.text(51, 68, ‘B’, fontsize=12, color=’green’)
ax.text(71, 28, ‘C’, fontsize=12, color=’blue’)
ax.text(31, 68, ‘D’, fontsize=12, color=’blue’)
第二部分:图像解读与经济学分析
生成的图像不仅仅是一张图,它讲述了一个完整的故事。以下是基于上述代码生成的图像的详细解读:
1. 基础形态:需求定律
图像展示了两条向右下方倾斜的曲线(D1 和 D2)。这验证了
需求定律
:在其他条件不变的情况下,价格越高,需求量越少;价格越低,需求量越多。
2. 区分“变化”与“变动”的核心逻辑
沿着需求曲线的移动 (Movement along the curve)
图示表现
: 在
D1
蓝色实线上,从
点 C (P=70, Q=30)
移动到
点 D (P=30, Q=70)
。
原因
: 仅仅是商品自身的价格下降了。
术语
: 这叫“需求量的变化”。
需求曲线的移动 (Shift of the curve)
图示表现
: 从
点 A (P=50, Q=50)
移动到
点 B (P=50, Q=70)
。
原因
: 价格没变(都是50),但发生了非价格因素的变化(例如:消费者收入增加,或者替代品变贵了)。
术语
: 这叫“需求的变化”。注意,点 A 和点 B 不在同一条曲线上,这证明了曲线本身发生了位移。
第三部分:进阶绘图技巧与代码优化
为了让图表更具学术出版质量,我们可以对代码进行以下优化:添加网格、优化箭头样式、以及增加阴影区域来强调经济学概念。
进阶代码示例
import matplotlib.pyplot as plt
import numpy as np
# 1. 设置风格 (使用 seaborn-v0_8-whitegrid 风格更现代)
plt.style.use(‘seaborn-v0_8-whitegrid’)
plt.rcParams[‘font.sans-serif’] = [‘SimHei’]
plt.rcParams[‘axes.unicode_minus’] = False
# 2. 数据准备
fig, ax = plt.subplots(figsize=(12, 7))
# 价格范围
price = np.linspace(10, 90, 100)
# 需求函数
q1 = 100 – price
q2 = 120 – price
# 3. 绘制曲线
# D1: 原始需求
ax.plot(price, q1, label=’原始需求 D1′, color=’#1f77b4′, linewidth=2.5, alpha=0.9)
# D2: 需求增加
ax.plot(price, q2, label=’需求增加 D2′, color=’#2ca02c’, linewidth=2.5, linestyle=’–‘, alpha=0.9)
# 4. 高级标注:使用多段箭头和背景色块
# — 强调“沿着曲线移动” (价格效应) —
# 在 D1 上画一个弯曲的箭头,表示滑动
ax.annotate(”,
xy=(30, 70), xytext=(70, 30),
arrowprops=dict(arrowstyle=’->’, color=’red’, lw=2, mutation_scale=20))
ax.text(50, 45, ‘价格下降导致\n需求量增加’, color=’red’, ha=’center’, fontsize=11, fontweight=’bold’)
# — 强调“曲线移动” (需求变化) —
# 画一个水平的双箭头表示平移
ax.annotate(”,
xy=(50, 70), xytext=(50, 50),
arrowprops=dict(arrowstyle=’<->‘, color=’black’, lw=2))
ax.text(52, 60, ‘非价格因素\n导致需求变动’, color=’black’, va=’center’, fontsize=11, fontweight=’bold’)
# 5. 标记关键点并添加坐标注释
points = {
‘A’: (50, 50, ‘blue’),
‘B’: (50, 70, ‘green’),
‘C’: (70, 30, ‘blue’),
‘D’: (30, 70, ‘blue’)
}
for name, (x, y, c) in points.items():
ax.scatter(x, y, color=c, s=80, zorder=5, edgecolors=’white’, linewidth=1.5)
ax.text(x + 1.5, y – 2, f'{name}({x},{y})’, fontsize=10, color=c, fontweight=’bold’)
# 6. 图表美化
ax.set_title(‘需求定律深度解析:价格效应 vs 收入/偏好效应’, fontsize=18, pad=20, fontweight=’bold’)
ax.set_xlabel(‘价格 (Price)’, fontsize=14)
ax.set_ylabel(‘需求量 (Quantity)’, fontsize=14)
ax.set_xlim(0, 100)
ax.set_ylim(0, 120)
# 设置刻度字体大小
ax.tick_params(axis=’both’, which=’major’, labelsize=12)
# 添加图例
ax.legend(loc=’upper right’, fontsize=12, frameon=True, shadow=True)
# 添加水平和垂直参考线 (辅助阅读)
ax.axhline(y=0, color=’black’, linewidth=1)
ax.axvline(x=0, color=’black’, linewidth=1)
# 显示图像
plt.tight_layout()
plt.show()
代码优化点解析:
plt.style.use
: 使用了
seaborn-v0_8-whitegrid
网格风格,这比默认的 Matplotlib 样式更符合现代数据可视化的审美,便于读取数值。
颜色代码
: 使用了十六进制颜色码(如
#1f77b4
),这比简单的 ‘blue’/‘green’ 能提供更柔和、专业的视觉效果。
箭头的物理意义
:
在进阶版中,我们使用了
<->
双箭头来表示
曲线的平移
(从 D1 到 D2),这比单箭头更能体现“整条线移动”的概念。
使用了
->
单箭头配合弯曲路径来表示
沿着曲线的移动
,路径更贴合曲线本身。
点的样式
:
scatter
增加了
edgecolors=’white’
,让数据点在复杂的背景线条中更加突出。
信息密度
: 在坐标文本中直接显示了数值(如
A(50,50)
),这使得读者无需在脑海中估算坐标轴,大大降低了阅读门槛。
总结
绘制经济学图表不仅仅是画线,更是一种
逻辑的可视化
。
区分概念
:永远记住,
颜色和线型
(实线 vs 虚线)用来区分不同的市场状态(D1 vs D2);
箭头的位置和方向
用来区分变化的原因(价格变动 vs 非价格变动)。
代码核心
:利用
numpy
生成平滑数据,利用
matplotlib
的
plot
画线,利用
annotate
讲故事。
通过上述代码和分析,你可以生成既符合经济学原理,又具备出版级美观度的高质量图表。