求助:使用Matplotlib绘制日期为X、时间为Y的三元变量图时遇类型错误
解决Matplotlib绘制三元变量图的时间类型错误问题
我尝试用Matplotlib基于如下结构的Pandas数据框绘制三元变量图(第三列数值用绿到红表示从低到高):
Date Time Value 2023-11-01 11:22:34 59.0 2023-11-01 11:25:26 65.0 ...但始终无法成功绘图,报错提示时间值必须为浮点数等类型错误。我的数据处理代码如下:
import pandas as pd import datetime x = pandas.read_xml('/Users/steven/Downloads/apple_health_export/export.xml', xpath='//Record', attrs_only=True,parse_dates=["creationDate","startDate","endDate"]) x.value=pandas.to_numeric(x.value,errors='coerce') x = x[x.value.notnull()] data = x[x.type == 'HKQuantityTypeIdentifierHeartRate'] data['Date']=[datetime.datetime.date(d) for d in data['endDate']] data['Time']=[datetime.datetime.time(d) for d in data['endDate']]
问题原因
报错核心是Matplotlib无法直接识别datetime.time类型的坐标轴数据,它要求坐标轴输入为数值类型(比如浮点数、整数)。你提取的Time列是时间对象,不符合绘图要求。
解决方案
把时间转换成一天内的秒数/小时数(数值类型),日期转换成可映射的数值索引,再用散点图实现三元变量可视化(颜色对应心率值)。
完整可运行代码
import pandas as pd import matplotlib.pyplot as plt # 读取并预处理数据 x = pd.read_xml( '/Users/steven/Downloads/apple_health_export/export.xml', xpath='//Record', attrs_only=True, parse_dates=["creationDate","startDate","endDate"] ) x['value'] = pd.to_numeric(x['value'], errors='coerce') x = x[x['value'].notnull()] data = x[x['type'] == 'HKQuantityTypeIdentifierHeartRate'] # 转换日期和时间为绘图可用格式 # 用Pandas内置方法提取日期,比列表推导式更高效规范 data['Date'] = data['endDate'].dt.date # 将时间转为一天中的秒数(数值类型) data['Time_seconds'] = data['endDate'].dt.hour * 3600 + data['endDate'].dt.minute * 60 + data['endDate'].dt.second # 把日期映射为数值索引(方便y轴显示日期标签) date_list = data['Date'].unique() date_to_num = {date: idx for idx, date in enumerate(date_list)} data['Date_num'] = data['Date'].map(date_to_num) # 绘制三元变量散点图 plt.figure(figsize=(12, 6)) # c指定颜色对应value,cmap用反转的黄绿红配色(绿=低心率,红=高心率) scatter = plt.scatter( data['Time_seconds'], data['Date_num'], c=data['value'], cmap='RdYlGn_r', alpha=0.7 ) # 设置坐标轴 plt.yticks(ticks=range(len(date_list)), labels=date_list) plt.xlabel('一天中的秒数') plt.ylabel('日期') plt.title('心率随日期和时间的变化') # 添加颜色条说明 plt.colorbar(scatter, label='心率值') plt.tight_layout() plt.show()
关键优化点
- 用
dt属性替代手动循环提取日期时间,避免链式赋值警告,代码更简洁 Time_seconds把时间转为数值,解决Matplotlib的类型要求Date_num将日期映射为连续数值,既满足绘图要求,又能通过yticks显示原始日期标签RdYlGn_r配色正好实现“低数值绿、高数值红”的需求
内容的提问来源于stack exchange,提问作者Steven Buehler
相关产品推荐
相关产品推荐

