如何在欠采样曲线上为用户指定X区间的线段着色?
问题:欠采样曲线指定X区间线段着色
我想了解是否可以为欠采样曲线上用户指定X区间的线段着色。例如,用户希望为x=11到x=14区间的线段着色(预期效果为该区间线段呈现不同颜色)。我尝试使用df.loc[..]查找邻近点,但仅能选中x=10到x=15的线段。请问如何解决该问题?是否需要在两点间插值添加额外点?具体如何实现?该方案需支持如x=11到x=19这类跨多段的区间。
代码示例:
from bokeh.plotting import figure, output_file, show import pandas as pd p = figure(width=600, height=600, tools="pan,reset,save") data = {'x': [1, 2, 3, 6, 10, 15, 20, 22], 'y': [2, 3, 6, 8, 18, 24, 50, 77]} df = pd.DataFrame(data) p.line(df.x, df.y) show(p)
解决方案
要精准着色指定X区间的线段,必须在区间的起始和结束边界处进行线性插值,将原曲线拆分为未着色段和目标着色段分别绘制。以下是具体实现步骤:
1. 核心思路
通过插值计算出用户指定区间边界(如x=11、x=14)对应的y值,把原曲线拆成三部分:
- 区间之前的原始线段
- 区间内的高亮线段
- 区间之后的原始线段
该逻辑同样适用于跨多个原始数据段的区间(如x=11到x=19)。
2. 完整代码实现
from bokeh.plotting import figure, show import pandas as pd def get_interpolated_point(x_target, df): # 找到目标x前后的两个原始点 prev_point = df[df['x'] < x_target].iloc[-1] next_point = df[df['x'] > x_target].iloc[0] # 线性插值计算对应y值 slope = (next_point['y'] - prev_point['y']) / (next_point['x'] - prev_point['x']) y_target = prev_point['y'] + slope * (x_target - prev_point['x']) return pd.Series({'x': x_target, 'y': y_target}) # 初始化绘图对象 p = figure(width=600, height=600, tools="pan,reset,save") # 原始数据 raw_data = {'x': [1, 2, 3, 6, 10, 15, 20, 22], 'y': [2, 3, 6, 8, 18, 24, 50, 77]} df = pd.DataFrame(raw_data) # 用户指定的高亮区间 x_start = 11 x_end = 14 # 计算区间边界的插值点 start_point = get_interpolated_point(x_start, df) end_point = get_interpolated_point(x_end, df) # 1. 绘制区间前的线段:从起点到x_start插值点 before_data = df[df['x'] <= start_point['x']] before_data = pd.concat([before_data, pd.DataFrame([start_point])]) p.line(before_data['x'], before_data['y'], line_width=2, color='black') # 2. 绘制高亮区间的线段 highlight_data = pd.DataFrame([start_point, end_point]) p.line(highlight_data['x'], highlight_data['y'], line_width=2, color='red') # 3. 绘制区间后的线段:从x_end插值点到终点 after_data = df[df['x'] >= end_point['x']] after_data = pd.concat([pd.DataFrame([end_point]), after_data]) p.line(after_data['x'], after_data['y'], line_width=2, color='black') show(p)
3. 扩展到跨多段区间
如果需要着色x=11到x=19的区间,仅需修改x_start=11和x_end=19即可:
- 代码会自动基于原始数据的10&15点插值x=11的y值,基于15&20点插值x=19的y值
- 最终绘制出11到19区间的红色高亮线段,其余部分保持黑色
内容的提问来源于stack exchange,提问作者zape
相关产品推荐
相关产品推荐

