如何按最后一个y值排序gnuplot图例(key)条目?
问题:Gnuplot内按曲线最后Y值排序图例条目
我用Gnuplot生成了温度数据图表,现在想优化图例(key)的条目顺序,避免图例到曲线的连线交叉。原本打算在Gnuplot外预处理数据,想知道Gnuplot内部有没有简便方法,要求按每条曲线最后一个Y值排序图例。
当前生成的温度数据图表:[多曲线温度图表,图例与曲线的连线存在交叉]
数据格式示例
每行第一列为日期,第二列为时间,后续列是不同监测点的温度值:
2023-10-28 14:17:01 59.125 34.875 43.500 25.375 26.125 45.312 44.687 26.125 57.750 2023-10-28 14:18:01 59.125 34.937 43.875 25.375 26.125 45.437 44.750 26.187 57.750 2023-10-28 14:19:01 59.250 35.000 43.937 25.375 26.125 45.437 44.812 26.187 57.875 2023-10-28 14:20:01 59.187 35.062 43.562 25.375 26.125 45.562 44.812 26.250 57.750 2023-10-28 14:21:01 59.125 35.125 43.625 25.375 26.125 45.562 44.875 26.312 57.812
当前Gnuplot脚本关键片段
# 提取各列最后一行的值 stats 'temp.txt' using (last1=$1,last2=$2,last3=$3,last4=$4,last5=$5,last6=$6,last7=$7,last8=$8,last9=$9,last10=$10) nooutput # 设置图表尺寸 set size 0.8,1 # 添加从曲线到图例的连线 set arrow from graph 1,first last4 to screen 0.8, first 70 nohead # 设置图例位置在外部左侧,反转顺序 set key outside Left reverse # 绘制曲线,手动指定图例位置 plot \ "temp.txt" using 1:4 with lines title sprintf("太阳能供水, %.1f°", last4) at screen 0.84, first 70, \ "temp.txt" using 1:3 with lines title sprintf("生活热水, %.1f°", last3) at screen 0.84, first 65, \
Gnuplot内部实现方案
不需要外部预处理,用Gnuplot的数组+系统排序命令就能实现按最后Y值排序图例,避免连线交叉:
步骤1:定义数据结构并提取各曲线最后值
# 定义数组存储每个曲线的信息:最后Y值、数据列索引 array curve_data[8] # 对应8个温度列(第3到第10列) # 对应各列的监测点名称,顺序要和数据列一致 array point_names[8] = ["生活热水", "太阳能供水", "监测点3", "监测点4", "监测点5", "监测点6", "监测点7", "监测点8"] # 遍历所有温度列,提取最后一行的值 do for [col=3:10] { stats 'temp.txt' using col nooutput idx = col - 2 # 转换为数组索引(1-8) # 存储格式:"最后Y值 数据列索引" curve_data[idx] = sprintf("%.3f %d", STATS_max, col) }
步骤2:对曲线按最后Y值排序
利用系统sort命令实现排序(这是Gnuplot内最简便的排序方式):
# 将数组内容转为换行分隔的字符串,调用sort按数值降序排列 sorted_str = system("echo '" . join(curve_data, "\n") . "' | sort -nr") # 将排序后的字符串拆回数组 set print "_sorted_temp.tmp" print sorted_str set print stats "_sorted_temp.tmp" using 0 nooutput array sorted_curve[STATS_records] do for [i=1:STATS_records] { sorted_curve[i] = word(sorted_str, i*2 - 1) . " " . word(sorted_str, i*2) }
步骤3:动态生成绘图命令
循环排序后的数组,自动绘制曲线、图例和连线,保证顺序对应:
set size 0.8,1 # 设置图例在外部左侧顶部 set key outside Left top # 图例起始位置和间隔(屏幕坐标) legend_start_y = 0.9 legend_gap = 0.05 # 动态生成plot和arrow plot for [i=1:|sorted_curve|] \ 'temp.txt' using 1:word(sorted_curve[i],2) with lines \ title sprintf("%s, %.1f°", point_names[word(sorted_curve[i],2)-2], real(word(sorted_curve[i],1))) \ at screen 0.84, first legend_start_y - (i-1)*legend_gap, \ arrow from graph 1,first real(word(sorted_curve[i],1)) to screen 0.8, first legend_start_y - (i-1)*legend_gap nohead
方案说明
- 依赖系统
sort命令,是Gnuplot内实现排序最简洁的方式;若完全不想依赖外部命令,可自行实现冒泡排序,但代码会繁琐很多 point_names数组必须和数据列顺序一一对应,需根据实际需求修改- 调整
legend_start_y和legend_gap可适配不同图表尺寸 - 排序方向:
sort -nr是降序,改成sort -n就是升序,可根据需求调整
内容的提问来源于stack exchange,提问作者grueni
相关产品推荐
相关产品推荐

