如何用GNUPlot 4.6.2正确绘制HMMSS特殊时间格式图表?
解决GNUPlot 4.6.2处理无冒号HMMSS时间轴的问题
问题根因
你用无冒号的HMMSS格式(比如081500)作为X轴数据时,GNUPlot 4.6.2会把它当成整数解析,导致时间间隔逻辑完全错乱——比如083000到090000的整数差是7000,但实际是30分钟(1800秒),和其他时段的比例对不上,自然刻度位置和显示全乱了。
修复方案
1. 把整数HMMSS转成实际时间秒数
先把每个X轴的整数值拆解为时、分、秒,计算成当天的总秒数,这样X轴的数值就和实际时间间隔成正比了。
假设你的CSV格式是时间,设备1丢包率,设备2丢包率,...,示例数据:
081500,2,0 083000,5,1 090000,0,3
绘图时用using语句完成转换:
set datafile separator ',' # 整数转当天秒数:时*3600 + 分*60 + 秒 plot 'data.csv' using ($1/10000*3600 + int(($1%10000)/100)*60 + $1%100):2 with linespoints title '设备1', \ '' using ($1/10000*3600 + int(($1%10000)/100)*60 + $1%100):3 with linespoints title '设备2'
2. 自定义X轴刻度,避免大间隔
两种方式按需选择:
方式一:手动指定固定刻度
如果你的监控时间点是固定的(比如每15分钟一次),直接用set xtics硬编码刻度:
# X轴范围设为全天0-24点(0到86400秒) set xrange [0:86400] # 刻度位置(秒数)对应标签(HH:MM) set xtics ( \ "08:00" 28800, \ "08:15" 29700, \ "08:30" 30600, \ "09:00" 32400, \ "09:15" 33300 \ )
方式二:从数据自动提取所有时间点
如果时间点不固定,用stats命令配合循环提取所有时间点生成刻度:
set datafile separator ',' # 统计数据总行数 stats 'data.csv' nooutput # 定义数组存储刻度位置和标签 positions = array(int(STATS_records)) labels = array(int(STATS_records)) # 循环读取每行时间,转换后存入数组 do for [i=0:int(STATS_records)-1] { set table '' plot 'data.csv' every ::i::i using ($1/10000*3600 + int(($1%10000)/100)*60 + $1%100) with table unset table positions[i+1] = GPVAL_DATA_Y # 转成HH:MM:SS格式的标签 hour = int($1/10000) minute = int(($1%10000)/100) second = $1%100 labels[i+1] = sprintf("%02d:%02d:%02d", hour, minute, second) } # 应用自定义刻度 set xtics ( for [i=1:int(STATS_records)] labels[i] positions[i] )
3. 优化显示效果
加上X轴标题,旋转刻度避免重叠:
set xlabel "时间" set xtics rotate by 45 right
完整示例脚本
整合所有步骤的完整脚本:
set terminal pngcairo size 1200,600 set output 'packet_loss_trend.png' set datafile separator ',' set xrange [0:86400] set xlabel "时间" set xtics rotate by 45 right # 手动指定刻度(根据你的实际时间点调整) set xtics ( \ "08:15" 29700, \ "08:30" 30600, \ "09:00" 32400, \ "09:15" 33300, \ "09:30" 34200 \ ) # 转换时间并绘制丢包趋势图 plot 'packet_loss.csv' using ($1/10000*3600 + int(($1%10000)/100)*60 + $1%100):2 with linespoints lw 2 title '设备A', \ '' using ($1/10000*3600 + int(($1%10000)/100)*60 + $1%100):3 with linespoints lw 2 title '设备B'
额外提示
- 如果你的CSV里时间是字符串类型(不是整数),把
$1换成stringcolumn(1),用strptime转换:strptime("%H%M%S", stringcolumn(1)),再减去当天0点的时间戳得到秒数:strptime("%H%M%S", s) - strptime("%Y-%m-%d", strftime("%Y-%m-%d")) - GNUPlot 4.6.2的数组功能默认启用,如果遇到错误,直接换手动指定刻度的方式更稳妥。
内容的提问来源于stack exchange,提问作者CyberdocWI
相关产品推荐
相关产品推荐

