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

使用Bokeh绘制CSV数据多线图求助(Python 2.7环境)

解决Bokeh multi_line绘制CSV数据的问题

嘿,我来帮你搞定这个Bokeh multi_line绘图的问题!结合你的Python 2.7.14和Bokeh 0.12.13环境,我整理了一套可行的方案,还会帮你排查可能踩的坑:

完整可运行代码示例

首先,我们用pandas来处理CSV数据(Python2.7也能正常使用pandas),代码如下:

import pandas as pd
from bokeh.plotting import figure, show, output_file
from bokeh.models import ColumnDataSource

# 1. 读取并预处理CSV数据
# 注意Python2.7的编码问题,若CSV含中文可换成encoding='gbk'
df = pd.read_csv('data.csv', encoding='utf-8')
# 将time列转为datetime类型,Bokeh才能正确渲染时间轴
df['time'] = pd.to_datetime(df['time'])

# 2. 按Id分组整理multi_line需要的数据格式
grouped = df.groupby('Id')

# multi_line要求xs和ys是「列表的列表」,每个子列表对应一条线的x/y数据
xs = []
ys = []
line_labels = []

for id_, group in grouped:
    # 添加当前Id的上行字节曲线数据
    xs.append(group['time'].tolist())
    ys.append(group['upbyte'].tolist())
    line_labels.append("ID {} - 上行字节".format(id_))
    # 添加当前Id的下行字节曲线数据
    xs.append(group['time'].tolist())
    ys.append(group['downbyte'].tolist())
    line_labels.append("ID {} - 下行字节".format(id_))

# 3. 创建数据源并绘制图表
source = ColumnDataSource(data=dict(
    xs=xs,
    ys=ys,
    labels=line_labels
))

# 初始化绘图对象,指定x轴为时间类型
p = figure(x_axis_type="datetime", 
           title="各ID上下行字节流量趋势", 
           x_axis_label='时间', 
           y_axis_label='字节数')

# 调用multi_line绘制所有曲线
p.multi_line(xs='xs', ys='ys', source=source, legend='labels', line_width=2)

# 输出到HTML文件并在浏览器打开
output_file('byte_traffic.html')
show(p)

关键注意事项(你之前失败可能踩的坑)

  • 时间格式必须正确:如果time列是字符串类型,Bokeh无法识别为时间轴,必须用pd.to_datetime()转成datetime对象
  • multi_line的数据格式要求:xs和ys必须是列表嵌套列表,每个子列表对应一条独立曲线的x/y数据,不能直接传单列数据
  • Python2.7字符串格式化:别用Python3.6+的f-string,必须用.format()方法来拼接字符串
  • 编码问题:如果读取CSV时出现乱码,调整encoding参数(比如gbk、utf-8-sig)

不用pandas的替代方案(纯csv模块)

如果你不想用pandas,也可以用Python内置的csv模块处理数据:

import csv
from datetime import datetime
from bokeh.plotting import figure, show, output_file

# 读取CSV并按Id分组
data = {}
with open('data.csv', 'rb') as f:
    reader = csv.DictReader(f)
    for row in reader:
        id_ = row['Id']
        # 手动将时间字符串转为datetime对象,替换成你的实际时间格式
        time_ = datetime.strptime(row['time'], "%Y-%m-%d %H:%M:%S")
        upbyte = float(row['upbyte'])
        downbyte = float(row['downbyte'])
        
        if id_ not in data:
            data[id_] = {'times': [], 'upbytes': [], 'downbytes': []}
        data[id_]['times'].append(time_)
        data[id_]['upbytes'].append(upbyte)
        data[id_]['downbytes'].append(downbyte)

# 整理multi_line需要的xs/ys数据
xs = []
ys = []
line_labels = []
for id_ in data:
    xs.append(data[id_]['times'])
    ys.append(data[id_]['upbytes'])
    line_labels.append("ID {} - 上行字节".format(id_))
    xs.append(data[id_]['times'])
    ys.append(data[id_]['downbytes'])
    line_labels.append("ID {} - 下行字节".format(id_))

# 绘图部分和之前一致
p = figure(x_axis_type="datetime", title="各ID上下行字节流量趋势", x_axis_label='时间', y_axis_label='字节数')
p.multi_line(xs=xs, ys=ys, legend=line_labels, line_width=2)
output_file('byte_traffic.html')
show(p)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:40:06