Bokeh Y轴时间显示异常:微秒转分钟及图表无线条解决方案
解决Bokeh Y轴时间(VARCHAR类型)显示问题的步骤
这个问题我之前也碰到过,核心卡点在于Bokeh的时间轴只认标准的datetime类型(或对应的毫秒级时间戳),而你从MySQL读出来的varchar字符串,Bokeh根本识别不出这是时间数据——自然不会应用格式化规则,甚至连线条都画不出来。下面给你一步步拆解解决方案:
1. 先把VARCHAR时间字符串转成Python datetime对象
不管用pandas还是原生MySQL驱动读数据,第一步必须完成字符串到datetime的转换。假设你数据库里的时间格式是"YYYY-MM-DD HH:MM:SS"(比如"2024-05-20 14:30:00"),用pandas的话可以这么写:
import pandas as pd from sqlalchemy import create_engine # 连接MySQL并读取数据 engine = create_engine('mysql+pymysql://user:password@host/db_name') df = pd.read_sql("SELECT time_col, value_col FROM your_table", engine) # 把varchar类型的时间转成datetime对象 df['datetime_time'] = pd.to_datetime(df['time_col'], format="%Y-%m-%d %H:%M:%S")
如果不用pandas,用mysql-connector原生驱动的话,就用Python标准库的datetime.strptime逐个转换:
import datetime import mysql.connector conn = mysql.connector.connect(user='user', password='password', host='host', database='db_name') cursor = conn.cursor() cursor.execute("SELECT time_col, value_col FROM your_table") raw_data = cursor.fetchall() # 转换时间字符串为datetime对象 processed_data = [] for time_str, value in raw_data: dt = datetime.datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S") processed_data.append( (dt, value) )
注意:一定要严格匹配你数据库里时间字符串的实际格式!比如如果是
"MM/DD/YYYY HH:MM",就把format改成"%m/%d/%Y %H:%M",否则转换会报错。
2. 转成Bokeh兼容的毫秒级时间戳
Bokeh内部处理时间时,用的是从1970-01-01 UTC开始的毫秒级时间戳(整数类型),所以需要把datetime对象转成这个格式:
用pandas的话:
# pandas的datetime是纳秒级,除以1e6得到毫秒级时间戳 df['bokeh_time'] = df['datetime_time'].astype('int64') // 10**6
原生Python的话:
import time processed_data_bokeh = [] for dt, value in processed_data: # 转成毫秒级时间戳 timestamp_ms = int(time.mktime(dt.timetuple()) * 1000) processed_data_bokeh.append( (timestamp_ms, value) )
3. 配置Bokeh图表的Y轴
现在可以绘图了,关键要指定Y轴为datetime类型,并设置DatetimeTickFormatter:
from bokeh.plotting import figure, show from bokeh.models import DatetimeTickFormatter p = figure( y_axis_type="datetime", # 重中之重:指定Y轴为时间类型 title="时间数据Y轴示例", x_axis_label="X轴标签", y_axis_label="时间(分钟格式)" ) # 绘制线条,用转换后的bokeh_time作为Y值 p.line(x=df.index, y=df['bokeh_time'], line_width=2) # 配置Y轴的时间格式,按需调整显示规则 p.yaxis.formatter = DatetimeTickFormatter( minutes=["%M:%S", "%H:%M"], # 轴范围是分钟级时的显示格式 hours=["%H:%M", "%Y-%m-%d"], # 轴范围是小时级时的显示格式 days=["%Y-%m-%d"] # 更大时间范围时的显示格式 ) show(p)
常见问题排查
- 如果线条不显示:检查转换后的
bokeh_time是否有有效值,比如有没有NaN或者异常大/小的数值;同时确认x和y的数据长度一致。 - 如果格式化还是不生效:务必确认已经设置了
y_axis_type="datetime"——没有这行的话,Bokeh会把Y轴当成普通数值轴,DatetimeTickFormatter完全不会起作用。 - 如果时间显示有偏移:注意时区问题,MySQL里的时间如果是本地时区,转换时可能需要调整为UTC,或者在
DatetimeTickFormatter里指定timezone参数。
内容的提问来源于stack exchange,提问作者Meh
相关产品推荐
相关产品推荐

