如何使用Bokeh绘制含英里与米组合格式的坐标轴?
用Bokeh处理混合单位距离数据的最佳实现方案
嘿,这个场景我之前帮同事解决过,核心思路是先把混合单位的字符串转换成统一数值,再自定义X轴刻度显示原格式,这样既满足Bokeh对数值型X轴的要求,又能保留直观的距离标签。下面是具体步骤:
1. 解析距离字符串,转换为统一数值单位
Bokeh的X轴需要数值型数据才能正确排序、缩放,所以第一步必须把“X英里Y米”这种格式转成单一单位(比如全部转成米,或者千米)。这里用正则表达式来提取数值,再做单位转换:
import re def parse_distance(dist_str): # 匹配英里(支持小数)和米的数值 mile_pattern = re.compile(r'(\d+\.?\d*)英里') meter_pattern = re.compile(r'(\d+)米') mile_val = float(mile_pattern.search(dist_str).group(1)) if mile_pattern.search(dist_str) else 0 meter_val = int(meter_pattern.search(dist_str).group(1)) if meter_pattern.search(dist_str) else 0 # 1英里≈1609.34米,转换为总米数 total_meters = mile_val * 1609.34 + meter_val return total_meters
测试一下:
print(parse_distance("7.5英里100米")) # 输出≈12170.05米
2. 准备绘图数据
把原始距离列表转换成数值列表,同时保留原字符串作为后续的刻度标签:
# 你的原始距离数据 raw_distances = ["7.5英里100米", "7.5英里200米", "8英里100米"] # 转换为数值型X轴数据 x_numeric = [parse_distance(d) for d in raw_distances] # 示例Y轴数据,替换成你的实际数据 y_data = [12.3, 15.7, 14.1]
3. 用Bokeh绘图,自定义X轴刻度
关键是让X轴的数值位置对应原始的距离字符串标签,这样图表既逻辑正确又直观:
from bokeh.plotting import figure, show from bokeh.models import FixedTicker, ColumnDataSource # 创建数据源,把数值、标签、Y数据绑定 source = ColumnDataSource(data=dict( x=x_numeric, y=y_data, distance_labels=raw_distances )) # 初始化绘图对象,设置X轴范围(可选,让图表更美观) p = figure( x_axis_label="距离", y_axis_label="测量值", x_range=(min(x_numeric)-600, max(x_numeric)+600), # 给两端留点空白 plot_width=800, plot_height=400 ) # 绘制你的数据(这里用散点图,换成line/vbar等都可以) p.circle(x='x', y='y', source=source, size=12, color='darkorange', alpha=0.8) # 自定义X轴:用数值作为刻度位置,替换成原始距离标签 p.xaxis.ticker = FixedTicker(ticks=x_numeric) p.xaxis.major_label_overrides = dict(zip(x_numeric, raw_distances)) # (可选)添加数据标签,让每个点的距离更清晰 from bokeh.models import LabelSet labels = LabelSet( x='x', y='y', text='distance_labels', source=source, x_offset=10, y_offset=10, text_font_size='10pt', text_color='navy' ) p.add_layout(labels) # 显示图表 show(p)
额外注意事项
- 如果你的数据量很大,不需要每个点都显示刻度标签,可以筛选关键数值作为
ticks,避免标签重叠; - 单位转换的精度可以根据需求调整(比如1英里=1609.344米,更精确的数值);
- 如果需要对距离排序,直接基于
x_numeric排序即可,再同步调整raw_distances和y_data的顺序。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

