You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Matplotlib分色填充两组非函数线性图的上下区域

Solution for Filling Between Non-Functional Curves with Different Colors

Great question! The key challenge here is that your datasets aren't functional (x-values aren't monotonic or one-to-one), which makes plt.fill_between seem off-limits at first. But we can work around this by first converting your discrete points into continuous, monotonic curves using interpolation. Here's a step-by-step solution:

Step 1: Prepare and Sort Your Data

First, we need to sort both datasets by their x-values—this is required for interpolation tools to work correctly, as they expect monotonic input.

Step 2: Interpolate to Create Continuous Curves

We'll generate a dense set of x-values spanning the full range of both datasets, then interpolate y-values for each curve. This gives us the monotonic x array needed for plt.fill_between.

Full Code Implementation

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d

# Your original point sets
a = [(1, 3), (3, 1), (7, 4), (6, 2), (13, 5)]
b = [(0, 0), (3, 3), (6, 1), (10, 4), (8, 2), (12, 1)]

# Convert to numpy arrays and sort by x-value
a_arr = np.array(a)
a_sorted = a_arr[a_arr[:, 0].argsort()]
a_x, a_y = a_sorted[:, 0], a_sorted[:, 1]

b_arr = np.array(b)
b_sorted = b_arr[b_arr[:, 0].argsort()]
b_x, b_y = b_sorted[:, 0], b_sorted[:, 1]

# Define the full x range we need to cover
x_min = min(a_x.min(), b_x.min())
x_max = max(a_x.max(), b_x.max())

# Generate dense x points for interpolation (1000 points ensures smoothness)
x_interp = np.linspace(x_min, x_max, 1000)

# Create interpolation functions (linear interpolation works well here; use 'cubic' for smoother curves if needed)
interp_a = interp1d(a_x, a_y, kind='linear', fill_value="extrapolate")
interp_b = interp1d(b_x, b_y, kind='linear', fill_value="extrapolate")

# Get interpolated y values
y_a_interp = interp_a(x_interp)
y_b_interp = interp_b(x_interp)

# Plot original points and interpolated curves
plt.scatter(a_x, a_y, label='Set a', color='darkblue')
plt.scatter(b_x, b_y, label='Set b', color='darkred')
plt.plot(x_interp, y_a_interp, color='darkblue', alpha=0.7)
plt.plot(x_interp, y_b_interp, color='darkred', alpha=0.7)

# Fill between curves with different colors based on which is above
plt.fill_between(
    x_interp, y_a_interp, y_b_interp,
    where=(y_a_interp > y_b_interp),
    color='limegreen', alpha=0.3,
    label='a above b'
)
plt.fill_between(
    x_interp, y_a_interp, y_b_interp,
    where=(y_b_interp > y_a_interp),
    color='orange', alpha=0.3,
    label='b above a'
)

# Add labels and legend
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Fill Between Non-Functional Curves')
plt.legend()
plt.show()

How This Works

  • Sorting: By sorting each dataset's points by x-value, we ensure the interpolation function can correctly map x to y without ambiguity.
  • Interpolation: Generating dense x points creates a monotonic x array that plt.fill_between requires. The fill_value="extrapolate" ensures we cover the full range of both datasets, even where one set has no points.
  • Conditional Filling: The where parameter in plt.fill_between lets us target only the regions where one curve sits above the other, applying different colors accordingly.

Alternative (More Complex) Approach: Polygon Intersection

If you need to avoid interpolation and work strictly with the original discrete points, you can calculate the intersection points between the two polygonal lines, split the curves into segments at these intersections, then fill each segment based on which curve is on top. This requires more advanced geometry logic (e.g., using the shapely library to handle polygon intersections), but it's useful for cases where interpolation isn't acceptable.

内容的提问来源于stack exchange,提问作者yonzmeer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:18:34