折线斜率变化对fill_betweenx填充区域的影响及优化问询
解决方案
核心思路
问题本质是当x_orig - c和x_orig + c两条曲线交叉时,fill_betweenx仅填充同一y值下两条曲线的左右区间,而我们需要的是对每个y值取两条曲线的最小x为左边界、最大x为右边界,这样无论曲线是否交叉,都能填充两曲线覆盖的全部横向区域。同时利用这些边界值可判断散点是否在填充区域内,实现屏蔽效果。
代码实现
import matplotlib.pyplot as plt import numpy as np from scipy.interpolate import interp1d # 示例原始曲线数据 y_orig = np.linspace(0, 10, 100) x_orig = np.sin(y_orig) * 3 + y_orig / 2 # 构造带正负斜率的交叉曲线 c = 1.5 # 偏移量 # 计算两条偏移曲线 x_left = x_orig - c x_right = x_orig + c # 生成填充边界:对每个y值取两条曲线的极值 fill_left = np.minimum(x_left, x_right) fill_right = np.maximum(x_left, x_right) # 绘制填充区域与曲线 plt.figure(figsize=(8, 6)) plt.fill_betweenx(y_orig, fill_left, fill_right, color='lightblue', alpha=0.5) plt.plot(x_orig, y_orig, 'k-', label='Original Curve') plt.plot(x_left, y_orig, 'r--', label='Left Offset') plt.plot(x_right, y_orig, 'b--', label='Right Offset') # 生成并筛选散点(屏蔽填充区域内的点) np.random.seed(42) scatter_x = np.random.uniform(-2, 12, 50) scatter_y = np.random.uniform(0, 10, 50) # 插值得到散点对应y值的填充边界 left_interp = interp1d(y_orig, fill_left, bounds_error=False, fill_value='extrapolate') right_interp = interp1d(y_orig, fill_right, bounds_error=False, fill_value='extrapolate') scatter_left = left_interp(scatter_y) scatter_right = right_interp(scatter_y) # 筛选区域外的散点 mask = (scatter_x < scatter_left) | (scatter_x > scatter_right) plt.scatter(scatter_x[mask], scatter_y[mask], color='darkred', s=30, label='Filtered Scatter') plt.xlabel('X') plt.ylabel('Y') plt.legend() plt.grid(True) plt.show()
关键说明
- 填充逻辑简化:用
np.minimum和np.maximum直接对每个y对应的x值取极值,无需自定义复杂的交叉判断逻辑,完美解决交叉处无填充的问题。 - 散点屏蔽实现:通过
interp1d将填充边界的y-x映射扩展到散点的y值范围,快速判断散点是否在填充区间内,筛选逻辑简洁高效。
内容的提问来源于stack exchange,提问作者Isaiah Santistevan
相关产品推荐
相关产品推荐

