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

如何按最后一个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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:44:52