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

使用Matplotlib绘制数据库中电压与时间数据时遇TypeError问题求助

嘿,我帮你分析了代码和错误回溯,问题一目了然:matplotlib 没法直接把 datetime.timedelta 类型的数据当作坐标轴数值来用,它在尝试把时间数据转成浮点数的时候直接报错了,因为timedelta不是可直接转换的数字类型。

错误修复代码

我们只需要把从数据库取出的时间数据转换成matplotlib能识别的数值格式(比如总秒数),同时补上你缺失的图表显示代码,就能解决问题:

import matplotlib.pyplot as plt
import numpy as np
import mysql.connector
import datetime  # 别忘了导入datetime模块

my_connect = mysql.connector.connect(host="localhost", user="Kennedy", passwd="Kennerdol05071994", database="ecg_db", auth_plugin="mysql_native_password")
mycursor = my_connect.cursor()

def fetch_voltage():
    pat_id = 1
    # 用参数化查询更安全,避免SQL注入风险
    query = "SELECT voltage, time FROM ecg_data_tbl where patient_id = %s"
    mycursor.execute(query, (pat_id,))
    result = mycursor.fetchall()
    
    voltage_data = []
    time_in_seconds = []
    for volts, tim in result:
        voltage_data.append(volts)
        # 将timedelta转换为总秒数的浮点数,让matplotlib能处理
        if isinstance(tim, datetime.timedelta):
            time_sec = tim.total_seconds()
            time_in_seconds.append(time_sec)
    
    # 转成numpy数组(其实matplotlib也支持直接用列表)
    voltage_data = np.array(voltage_data)
    time_in_seconds = np.array(time_in_seconds)
    
    # 绘图并做基础美化
    plt.figure(figsize=(10, 6))
    plt.plot(time_in_seconds, voltage_data, label='ECG Voltage')
    plt.xlabel('Time (Seconds)')
    plt.ylabel('Voltage')
    plt.title(f'ECG Data for Patient ID {pat_id}')
    plt.legend()
    plt.grid(True)
    plt.show()  # 这一步你之前漏了!没有它图表不会显示

fetch_voltage()

# 最后记得关闭数据库连接,避免资源浪费
mycursor.close()
my_connect.close()

关键修复点

  • 将timedelta类型的时间通过total_seconds()转换成浮点型秒数,适配matplotlib的绘图要求
  • 添加了plt.show(),这是你之前代码里的核心缺失项——没有它图表根本不会显示出来
  • 改用参数化查询,这是数据库操作的最佳实践,能避免SQL注入风险
  • 补充了数据库连接关闭代码,避免长期占用资源

更优实现方案

1. 数据库端直接转换时间

如果你的数据库支持时间转数值的函数(比如MySQL的TIME_TO_SEC()),可以直接在SQL查询里完成转换,减少Python端的代码量:

SELECT voltage, TIME_TO_SEC(time) as time_sec FROM ecg_data_tbl where patient_id = %s

这样取出的time_sec直接是数值类型,Python端可以直接拿来绘图。

2. 用Pandas简化全流程

Pandas对数据库读取、时间处理和可视化的支持非常友好,能大幅简化代码:

import pandas as pd
import matplotlib.pyplot as plt
import mysql.connector

my_connect = mysql.connector.connect(host="localhost", user="Kennedy", passwd="Kennerdol05071994", database="ecg_db", auth_plugin="mysql_native_password")

# 直接用Pandas读取数据库查询结果
df = pd.read_sql("SELECT voltage, time FROM ecg_data_tbl where patient_id = 1", my_connect)
# 转换时间为秒数
df['time_sec'] = df['time'].apply(lambda x: x.total_seconds())
# 一键绘图并美化
df.plot(x='time_sec', y='voltage', figsize=(10,6), title='ECG Data', grid=True, legend='Voltage')
plt.show()

my_connect.close()

Pandas还能自动处理缺失值、数据排序等问题,后续如果要做数据清洗或分析也更方便。

3. 保留时间可读性的坐标轴格式化

如果你希望x轴显示具体的时间格式(比如HH:MM:SS)而不是单纯的秒数,可以用matplotlib的日期格式化工具:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import mysql.connector
import datetime

my_connect = mysql.connector.connect(host="localhost", user="Kennedy", passwd="Kennerdol05071994", database="ecg_db", auth_plugin="mysql_native_password")
mycursor = my_connect.cursor()

def fetch_voltage():
    pat_id = 1
    query = "SELECT voltage, time FROM ecg_data_tbl where patient_id = %s"
    mycursor.execute(query, (pat_id,))
    result = mycursor.fetchall()
    
    voltage_data = []
    time_data = []
    for volts, tim in result:
        voltage_data.append(volts)
        time_data.append(tim)
    
    plt.figure(figsize=(10,6))
    plt.plot(time_data, voltage_data)
    # 把x轴格式化为可读的时间格式
    plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))
    plt.gcf().autofmt_xdate()  # 自动旋转标签,避免重叠
    plt.xlabel('Time')
    plt.ylabel('Voltage')
    plt.title(f'ECG Data for Patient ID {pat_id}')
    plt.grid(True)
    plt.show()

fetch_voltage()
mycursor.close()
my_connect.close()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 23:02:38