如何在 gnuplot 中对数据块进行排序?

How to sort a datablock in gnuplot?

要按列对 文件 进行排序,Linux 用户拥有实用程序 sort。 Windows 用户必须安装,例如CoreUtilsGnuWin 获得相同(或相似)的功能。

因此,首先按 column1 然后按 column2 对文件进行排序,然后绘制文件的最少代码如下所示:

plot '<sort -k 1,2 "myFile.dat"' u 1:2

但是现在,我有一个数据块$Data:

$Data <<EOD
1    6
4    8
3    7
2    5
1    4
2    3
EOD

到目前为止,我尝试过的所有命令都以错误消息告终:

plot '<sort -k 1,2' $Data u 1:2

#--> Bad data on line 1 of file <sort -k 1,2

plot '<sort -k 1,2  $Data' u 1:2
plot '<sort -k 1,2 <$Data' u 1:2 

#--> warning: Skipping data file with no valid points
#--> x range is invalid

plot '<sort -k 1,2 '<$Data u 1:2

#--> Column number or datablock line expected

我不想先将数据块写入文件,然后再从文件中读取。我目前不知道如何将 $Data 的内容重定向到 sort 的标准输入。 Windows 和 Linux 有什么解决方案吗?

更新:

使用@Ethan 建议的代码时,我得到以下结果。请注意我预期的 2 52 3 行(Ethan 也有)。

# Curve 0 of 1, 6 points
# Curve title: "$Data_1 using 1:2:1"
# x y type
 1  4  i
 1  6  i
 2  5  i
 2  3  i
 3  7  i
 4  8  i

知道这是为什么吗?我是 运行 Win10 上的 gnuplot 5.4.1。

将 $Data 发送到排序实用程序的标准输入的语法是 set print "| sort"; print $Data。但这不会做你想要的。相反,让我们在 gnuplot 中执行双重排序。

$Data <<EOD
1    6
4    8
3    7
2    5
1    4
2    3
EOD

set table $Data_1
plot $Data using 1:2:2 smooth zsort with points
set table $Data_2
plot $Data_1 using 1:2:1 smooth zsort with points
unset table
print $Data_2

# Curve 0 of 1, 6 points
# Curve title: "$Data_1 using 1:2:1"
# x y type
 1  4  i
 1  6  i
 2  3  i
 2  5  i
 3  7  i
 4  8  i

如果没有解决方法,就不会是 gnuplot。嗯,有点麻烦,但它似乎工作。 显然,smooth zsort 分别对每个子块进行排序。因此,在第一次排序之后,只要第一列中的值发生变化,您就“简单地”需要将数据拆分为子块。

  1. 按第一列排序
  2. 在第一列中的值更改之前插入一个空行
  3. 按第二列排序
  4. 将其绘制成 table 以再次删除空行

代码:(编辑:使用图形表示更容易说明 zsort 的不良行为(仅在 Windows 下))

### sorting datablock, "bug": Windows zsort does not preserve order
reset session

# create some random test data 
set print $Data
    do for [i=1:100] {
        print sprintf("%g %g", int(rand(0)*10), int(rand(0)*10))
    }
set print

# order not preserving (only under Windows)
set table $Data1
    plot $Data  u 1:2:2 smooth zsort
set table $Data2
    plot $Data1  u 1:2:1 smooth zsort
unset table

# order preserving (even under Windows, but cumbersome)
set table $Data3
    plot $Data  u 1:2:1 smooth zsort
unset table
set print $Data4
    do for [i=1:|$Data3|] {
        print $Data3[i]
        if (i<|$Data3|) { if (word($Data3[i],1) ne word($Data3[i+1],1)) { print "" } }
    }
set print
set table $Data5
    plot $Data4 u 1:2:2 smooth zsort
set table $Data6
    plot $Data5 u 1:2 w table
unset table

set key out
set rmargin 20
set multiplot layout 3,1
    plot $Data  w lp pt 7 lc "black"     ti "Random"
    plot $Data2 w lp pt 7 lc "red"       ti "zsort"
    plot $Data6 w lp pt 7 lc "web-green" ti "Workaround"
unset multiplot
### end of code

结果:

我要备份并建议您重新考虑您最初对使用临时文件的限制。最直接的解决方案是:

   set print "| sort -k 1,2 > sorted.dat"
   print $Data
   unset print
   plot 'sorted.dat'

如果您解释了为什么您不想使用临时文件,也许这个问题的答案与排序问题无关。 如果问题是临时文件的 name,那么可能是这样的:

  tempfile = system("mktemp")
  set print "| sort -k 1,2 > ".tempfile
  print $Data
  unset print
  plot tempfile with points