如何绘制pd.cut生成的分箱时间数据?解决绘图溢出错误
问题描述
我有如下格式的时间序列数据:
LFrame Date_Time DoW run_time az el distance pass_ID SV_ID Direction PFD_Jy 0 3114360965 2023-03-29 17:25:20 Wednesday 62720.0 349.254117 12.199639 2.171043e+06 2023_03_29_154 154 SB 8.505332 1 3114360977 2023-03-29 17:25:21 Wednesday 62721.0 349.216316 12.294878 2.164688e+06 2023_03_29_154 154 SB 1085.548185 2 3114360988 2023-03-29 17:25:22 Wednesday 62722.0 349.178240 12.390492 2.158335e+06 2023_03_29_154 154 SB 515.828602 3 3114360999 2023-03-29 17:25:23 Wednesday 62723.0 349.139888 12.486484 2.151987e+06 2023_03_29_154 154 SB 344.120530 4 3114361010 2023-03-29 17:25:24 Wednesday 62724.0 349.101256 12.582857 2.145641e+06 2023_03_29_154 154 SB 37.207705
因为数据采样间隔为1秒,绘图过于密集,我用以下代码对时间列分箱并分组取均值:
binned = SV_pfd_data.groupby(pd.cut(SV_pfd_data.Date_Time, SV_pfd_data.shape[0]//5), as_index=True).mean() # ~1 min bins binned = binned.reset_index()
得到的分箱数据如下:
Date_Time LFrame run_time az el distance SV_ID PFD_Jy 0 (2023-03-29 17:25:19.408999936, 2023-03-29 17:... 3.114361e+09 62722.5 349.158693 12.438994 2.155165e+06 154.0 448.731927 1 (2023-03-29 17:25:25.008474624, 2023-03-29 17:... 3.114361e+09 62728.0 348.943580 12.972617 2.120295e+06 154.0 213.259464 2 (2023-03-29 17:25:30.016949248, 2023-03-29 17:... 3.114361e+09 62733.0 348.740192 13.468287 2.088688e+06 154.0 556.595627 3 (2023-03-29 17:25:35.025423616, 2023-03-29 17:... 3.114361e+09 62738.0 348.529055 13.974280 2.057173e+06 154.0 872.418091
注意:分箱后的时间精度高于微秒,暂不清楚原因
随后我使用以下matplotlib代码绘图时触发错误:
timeOnly = matdates.DateFormatter('%H:%M:%S') fig, ax = plt.subplots(figsize=(10,5)) ax.plot_date(binned.Date_Time, binned.PFD_Jy, label=r"$\nu$=1611.1") ax.set_ylabel("PFD [Jy]") ax.set_xlabel("Date-time") ax.set_xticklabels(SV_pfd_data.Date_Time, rotation = 65, fontsize=10) ax.xaxis.set_major_formatter(timeOnly)
错误信息:
OverflowError: int too big to convert
请问如何解决该问题,成功绘制分箱后的时间数据?
解决方法
出现错误的核心原因:pd.cut对时间列分箱后生成的是区间类型(Interval),matplotlib的plot_date无法直接处理该类型;同时你误用了原数据的时间来设置分箱后图表的刻度标签,进一步引发问题。
步骤1:将分箱时间转换为可识别的时间戳
方案A:用pd.Grouper直接按时间间隔分箱(推荐)
这种方式更直观,直接指定分箱时长,避免生成区间类型:
# 按5秒间隔分箱取均值,可根据需求调整freq参数(如'1min'代表1分钟) binned = SV_pfd_data.groupby(pd.Grouper(key='Date_Time', freq='5s')).mean().reset_index()
方案B:提取现有区间的中点作为时间戳
如果坚持使用原pd.cut逻辑,需将区间列转换为时间戳:
# 提取每个时间区间的中点,转为pandas时间戳 binned['Date_Time'] = binned['Date_Time'].apply(lambda x: x.mid) # 确保列类型为datetime64 binned['Date_Time'] = pd.to_datetime(binned['Date_Time'])
步骤2:修正绘图代码的刻度设置
原代码中ax.set_xticklabels(SV_pfd_data.Date_Time)是错误的,应让matplotlib自动生成刻度后再格式化:
import matplotlib.dates as matdates import matplotlib.pyplot as plt timeOnly = matdates.DateFormatter('%H:%M:%S') fig, ax = plt.subplots(figsize=(10,5)) # 此时Date_Time为时间戳类型,plot_date可正常处理 ax.plot_date(binned['Date_Time'], binned['PFD_Jy'], label=r"$\nu$=1611.1", linestyle='-') ax.set_ylabel("PFD [Jy]") ax.set_xlabel("Date-time") # 自动生成刻度后格式化显示 ax.xaxis.set_major_formatter(timeOnly) # 旋转刻度标签避免重叠 plt.xticks(rotation=65, fontsize=10) ax.legend() plt.tight_layout() plt.show()
补充:解决分箱时间精度过高问题
pd.cut会根据原数据时间精度自动调整区间精度,若需控制精度,可在分箱前转换时间列精度:
# 将时间列精度调整为毫秒 SV_pfd_data['Date_Time'] = SV_pfd_data['Date_Time'].dt.round('ms')
内容的提问来源于stack exchange,提问作者earnric
相关产品推荐
相关产品推荐

