Matplotlib绘制两条水平曲线之间的填充多边形
参考:Make filled polygons between two horizontal curves in Python using Matplotlib
Matplotlib是Python中强大的数据可视化库,它提供了丰富的绘图功能。本文将详细介绍如何使用Matplotlib在两条水平曲线之间创建填充多边形。这种技术在数据分析、科学研究和金融领域中广泛应用,可以直观地展示数据范围、误差区间或者时间序列的变化趋势。
1. 基本概念
在开始绘制之前,我们需要了解一些基本概念:
- 水平曲线:指在二维平面上,y值随x值变化的曲线。
- 填充多边形:指在两条曲线之间的区域用颜色填充,形成一个封闭的多边形区域。
- Matplotlib的fill_between()函数:这是实现填充效果的核心函数。
让我们从一个简单的例子开始:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
plt.figure(figsize=(10, 6))
plt.fill_between(x, y1, y2, alpha=0.5, label='how2matplotlib.com')
plt.plot(x, y1, label='sin(x)')
plt.plot(x, y2, label='cos(x)')
plt.legend()
plt.title('Filled Polygon between Sin and Cos Curves')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
Output:
在这个例子中,我们创建了两条曲线(正弦和余弦),然后使用fill_between()
函数填充它们之间的区域。alpha
参数控制填充区域的透明度。
2. 自定义填充样式
Matplotlib提供了多种方式来自定义填充区域的样式:
2.1 颜色设置
我们可以通过color
参数来设置填充区域的颜色:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = 2 * np.sin(x)
y2 = np.sin(x)
plt.figure(figsize=(10, 6))
plt.fill_between(x, y1, y2, color='skyblue', alpha=0.7, label='how2matplotlib.com')
plt.plot(x, y1, 'r-', label='2*sin(x)')
plt.plot(x, y2, 'g-', label='sin(x)')
plt.legend()
plt.title('Custom Color Filled Polygon')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
Output:
在这个例子中,我们使用了’skyblue’作为填充颜色,并设置了0.7的透明度。
2.2 渐变填充
我们还可以创建渐变填充效果:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LinearSegmentedColormap
x = np.linspace(0, 10, 100)
y1 = np.exp(-x/10) * np.cos(x)
y2 = -np.exp(-x/10) * np.cos(x)
colors = ['red', 'white', 'blue']
n_bins = 100
cmap = LinearSegmentedColormap.from_list('how2matplotlib.com', colors, N=n_bins)
plt.figure(figsize=(10, 6))
plt.fill_between(x, y1, y2, cmap=cmap, norm=plt.Normalize(-1, 1))
plt.plot(x, y1, 'k-', label='Upper curve')
plt.plot(x, y2, 'k-', label='Lower curve')
plt.legend()
plt.title('Gradient Filled Polygon')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
Output:
这个例子展示了如何创建一个从红色到蓝色的渐变填充效果。我们使用LinearSegmentedColormap
来定义颜色映射,然后将其应用到fill_between()
函数中。
3. 条件填充
Matplotlib允许我们根据条件来选择性地填充区域:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = 0.5 * np.sin(x)
plt.figure(figsize=(10, 6))
plt.fill_between(x, y1, y2, where=(y1 > y2), color='green', alpha=0.5, label='how2matplotlib.com (y1 > y2)')
plt.fill_between(x, y1, y2, where=(y1 <= y2), color='red', alpha=0.5, label='how2matplotlib.com (y1 <= y2)')
plt.plot(x, y1, 'b-', label='y1')
plt.plot(x, y2, 'y-', label='y2')
plt.legend()
plt.title('Conditional Filled Polygon')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
Output:
在这个例子中,我们根据y1和y2的大小关系,使用不同的颜色填充区域。当y1 > y2时,填充绿色;当y1 <= y2时,填充红色。
4. 多区域填充
我们可以在同一个图表中填充多个区域:
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)
plt.figure(figsize=(10, 6))
plt.fill_between(x, y1, y2, color='lightblue', alpha=0.5, label='how2matplotlib.com (sin-cos)')
plt.fill_between(x, y2, y3, color='lightgreen', alpha=0.5, label='how2matplotlib.com (cos-tan)')
plt.plot(x, y1, 'r-', label='sin(x)')
plt.plot(x, y2, 'g-', label='cos(x)')
plt.plot(x, y3, 'b-', label='tan(x)')
plt.legend()
plt.title('Multiple Filled Polygons')
plt.xlabel('x')
plt.ylabel('y')
plt.ylim(-5, 5)
plt.show()
Output:
这个例子展示了如何在正弦、余弦和正切函数之间填充多个区域。注意我们使用ylim()
函数限制了y轴的范围,以便更好地显示结果。
5. 堆叠区域图
堆叠区域图是一种特殊的填充多边形图,常用于展示累积数据:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.random.rand(100)
y2 = np.random.rand(100)
y3 = np.random.rand(100)
plt.figure(figsize=(10, 6))
plt.fill_between(x, 0, y1, alpha=0.5, label='how2matplotlib.com (Layer 1)')
plt.fill_between(x, y1, y1+y2, alpha=0.5, label='how2matplotlib.com (Layer 2)')
plt.fill_between(x, y1+y2, y1+y2+y3, alpha=0.5, label='how2matplotlib.com (Layer 3)')
plt.title('Stacked Area Chart')
plt.xlabel('x')
plt.ylabel('Cumulative y')
plt.legend()
plt.show()
Output:
这个例子创建了一个三层的堆叠区域图,每一层都用不同的颜色填充,并且累积在前一层之上。
6. 误差区间可视化
填充多边形技术常用于可视化数据的误差区间:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 50)
y = np.sin(x)
error = 0.2 * np.random.rand(len(x))
plt.figure(figsize=(10, 6))
plt.fill_between(x, y-error, y+error, alpha=0.2, label='how2matplotlib.com (Error range)')
plt.plot(x, y, 'r-', label='sin(x)')
plt.legend()
plt.title('Error Range Visualization')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
Output:
这个例子展示了如何使用fill_between()
函数来可视化数据点周围的误差范围。
7. 时间序列数据的可视化
对于时间序列数据,我们可以使用填充多边形来强调某些时间段:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
values = np.cumsum(np.random.randn(len(dates)))
plt.figure(figsize=(12, 6))
plt.fill_between(dates, 0, values, where=(values > 0), color='green', alpha=0.3, label='how2matplotlib.com (Positive)')
plt.fill_between(dates, 0, values, where=(values <= 0), color='red', alpha=0.3, label='how2matplotlib.com (Negative)')
plt.plot(dates, values, 'b-')
plt.title('Time Series Data Visualization')
plt.xlabel('Date')
plt.ylabel('Cumulative Value')
plt.legend()
plt.show()
Output:
这个例子展示了如何使用填充多边形来区分时间序列数据中的正值和负值区域。
8. 3D填充多边形
虽然本文主要讨论2D填充多边形,但Matplotlib也支持3D填充:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z1 = np.sin(np.sqrt(X**2 + Y**2))
Z2 = np.cos(np.sqrt(X**2 + Y**2))
ax.plot_surface(X, Y, Z1, alpha=0.5, cmap='viridis', label='how2matplotlib.com (Surface 1)')
ax.plot_surface(X, Y, Z2, alpha=0.5, cmap='plasma', label='how2matplotlib.com (Surface 2)')
ax.set_title('3D Filled Surfaces')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()
Output:
这个例子展示了如何在3D空间中创建和填充表面。虽然不是严格意义上的”填充多边形”,但它展示了Matplotlib在3D可视化方面的能力。
9. 自定义边界样式
我们可以自定义填充区域的边界样式:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = 0.5 * np.sin(x)
plt.figure(figsize=(10, 6))
plt.fill_between(x, y1, y2, alpha=0.5, edgecolor='red', linewidth=2, linestyle='--', label='how2matplotlib.com')
plt.plot(x, y1, 'b-', label='y1')
plt.plot(x, y2, 'g-', label='y2')
plt.legend()
plt.title('Custom Border Style')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
Output:
在这个例子中,我们为填充区域添加了红色虚线边界。
10. 交互式填充多边形
使用Matplotlib的交互式功能,我们可以创建动态的填充多边形:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Slider
fig, ax = plt.subplots(figsize=(10, 6))
plt.subplots_adjust(bottom=0.25)
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.zeros_like(x)
line, = ax.plot(x, y1, 'r-', label='sin(x)')
fill = ax.fill_between(x, y1, y2, alpha=0.5, label='how2matplotlib.com')
ax.set_title('Interactive Filled Polygon')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend()
axfreq = plt.axes([0.25, 0.1, 0.65, 0.03])
freq_slider = Slider(axfreq, 'Freq', 0.1, 3.0, valinit=1)
def update(val):
freq = freq_slider.val
y1 = np.sin(freq * x)
line.set_ydata(y1)
ax.collections.clear()
ax.fill_between(x, y1, y2, alpha=0.5, label='how2matplotlib.com')
fig.canvas.draw_idle()
freq_slider.on_changed(update)
plt.show()
Output:
这个例子创建了一个交互式图表,用户可以通过滑块来调整正弦函数的频率,填充区域会随之动态更新。
结论
通过本文的详细介绍和丰富的示例,我们深入探讨了如何使用Matplotlib在Python中创建两条水平曲线之间的填充多边形。从基本的填充技术到高级的自定义样式,从2D到3D可视化,再到交互式图表,我们涵盖了广泛的应用场景。
填充多边形技术在数据可视化中扮演着重要角色,它可以有效地展示数据范围、误差区间、时间序列变化等信息。通过合理运用颜色、透明度、边界样式等参数,我们可以创建出既美观又富有信息量的可视化图表。
在实际应用中,填充多边形技术可以用于:
- 金融数据分析:如股票价格波动范围的可视化
- 科学研究:如实验数据的误差范围展示
- 气象学:如温度、降水量等随时间变化的趋势图
- 人口统计:如不同年龄组人口分布的堆叠区域图
- 工程领域:如设备性能参数的允许范围可视化
为了进一步提高填充多边形图的表现力,我们还可以考虑以下几点:
11. 组合多种图表类型
填充多边形可以与其他类型的图表结合使用,以提供更丰富的信息:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = 0.5 * np.sin(x)
plt.figure(figsize=(12, 6))
plt.fill_between(x, y1, y2, alpha=0.3, color='lightblue', label='how2matplotlib.com (Area)')
plt.plot(x, y1, 'r-', label='y1')
plt.plot(x, y2, 'g-', label='y2')
plt.scatter(x[::10], y1[::10], color='red', s=50, label='Data points')
plt.title('Combination of Fill, Line, and Scatter Plots')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()
Output:
这个例子结合了填充区域、线图和散点图,提供了数据的多个维度的信息。
12. 使用不同的插值方法
Matplotlib提供了多种插值方法来连接数据点,这可以影响填充区域的形状:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 10)
y1 = np.sin(x)
y2 = 0.5 * np.sin(x)
plt.figure(figsize=(12, 8))
plt.subplot(2, 2, 1)
plt.fill_between(x, y1, y2, alpha=0.5, interpolate=True, label='how2matplotlib.com')
plt.title('Default (linear interpolation)')
plt.subplot(2, 2, 2)
plt.fill_between(x, y1, y2, alpha=0.5, step='pre', label='how2matplotlib.com')
plt.title('Step (pre)')
plt.subplot(2, 2, 3)
plt.fill_between(x, y1, y2, alpha=0.5, step='post', label='how2matplotlib.com')
plt.title('Step (post)')
plt.subplot(2, 2, 4)
from scipy.interpolate import interp1d
f = interp1d(x, y1, kind='cubic')
g = interp1d(x, y2, kind='cubic')
xnew = np.linspace(0, 10, 100)
plt.fill_between(xnew, f(xnew), g(xnew), alpha=0.5, label='how2matplotlib.com')
plt.title('Cubic interpolation')
plt.tight_layout()
plt.show()
Output:
这个例子展示了不同插值方法对填充区域形状的影响,包括线性插值、阶梯插值和三次样条插值。
13. 添加图例和注释
为了使图表更加信息丰富,我们可以添加图例和注释:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = 0.5 * np.sin(x)
plt.figure(figsize=(10, 6))
plt.fill_between(x, y1, y2, alpha=0.5, color='lightblue', label='how2matplotlib.com (Filled area)')
plt.plot(x, y1, 'r-', label='Upper curve')
plt.plot(x, y2, 'g-', label='Lower curve')
plt.title('Filled Polygon with Annotations')
plt.xlabel('x')
plt.ylabel('y')
plt.annotate('Maximum', xy=(np.pi/2, 1), xytext=(np.pi/2+1, 1.2),
arrowprops=dict(facecolor='black', shrink=0.05))
plt.annotate('Minimum', xy=(3*np.pi/2, -1), xytext=(3*np.pi/2+1, -1.2),
arrowprops=dict(facecolor='black', shrink=0.05))
plt.legend()
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()
Output:
这个例子添加了图例和指向最大值和最小值的注释,使图表更加易于理解。
14. 使用颜色映射
我们可以使用颜色映射来表示额外的数据维度:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = 0.5 * np.sin(x)
z = np.abs(y1 - y2)
plt.figure(figsize=(10, 6))
plt.fill_between(x, y1, y2, alpha=0.5, cmap='viridis', norm=plt.Normalize(0, z.max()))
plt.colorbar(label='Difference')
plt.plot(x, y1, 'r-', label='Upper curve')
plt.plot(x, y2, 'g-', label='Lower curve')
plt.title('Filled Polygon with Color Mapping')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
这个例子使用颜色映射来表示上下曲线之间的差值,添加了一个颜色条来解释颜色的含义。
15. 处理缺失数据
在实际应用中,我们可能会遇到缺失数据的情况。Matplotlib可以优雅地处理这种情况:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = 0.5 * np.sin(x)
# 创建一些缺失数据
mask = np.random.choice([0, 1], size=len(x), p=[0.1, 0.9]).astype(bool)
y1[mask] = np.nan
y2[mask] = np.nan
plt.figure(figsize=(10, 6))
plt.fill_between(x, y1, y2, alpha=0.5, label='how2matplotlib.com')
plt.plot(x, y1, 'r-', label='Upper curve')
plt.plot(x, y2, 'g-', label='Lower curve')
plt.title('Filled Polygon with Missing Data')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
Output:
这个例子展示了如何处理包含缺失数据(NaN值)的情况。Matplotlib会自动跳过这些缺失的数据点。
总结
通过本文的详细探讨,我们全面了解了如何使用Matplotlib在Python中创建两条水平曲线之间的填充多边形。从基本概念到高级技巧,我们涵盖了广泛的应用场景和实现方法。
填充多边形技术在数据可视化中有着重要的应用,它可以有效地展示数据范围、误差区间、时间序列变化等信息。通过灵活运用颜色、透明度、边界样式、插值方法等参数,我们可以创建出既美观又富有信息量的可视化图表。
在实际应用中,填充多边形可以与其他图表类型结合,添加注释和图例,使用颜色映射表示额外的数据维度,甚至处理缺失数据。这些技巧使得填充多边形成为一种强大而灵活的数据可视化工具。
最后,值得注意的是,虽然本文主要关注2D填充多边形,但Matplotlib也支持3D填充,为更复杂的数据可视化需求提供了可能性。
通过掌握这些技巧,数据科学家、研究人员和开发者可以更好地展示他们的数据,传达更丰富的信息,从而做出更informed的决策和洞察。随着数据可视化在各个领域的重要性不断提升,熟练运用填充多边形等技术将成为一项越来越有价值的技能。