gnuplot中的循环结构?

94

有没有办法在gnuplot中迭代地从多个文件中检索数据并将它们绘制在同一张图上。假设我有像data1.txt,data2.txt......data1000.txt这样的文件;每个文件都有相同数量的列。现在我可以写类似于-

plot "data1.txt" using 1:2 title "Flow 1", \
     "data2.txt" using 1:2 title "Flow 2", \
      .
      .
      .
     "data1000.txt"  using 1:2 title "Flow 6"

但是这将非常不方便。我在想是否有一种方法可以循环遍历gnuplot中的plot部分。


下面的答案中有一个非常舒适的bash函数。 - Hastur
6个回答

110

当然有(在gnuplot 4.4+版本中):

plot for [i=1:1000] 'data'.i.'.txt' using 1:2 title 'Flow '.i
变量i可以被解释为变量或字符串,因此您可以执行类似以下的操作:
plot for [i=1:1000] 'data'.i.'.txt' using 1:($2+i) title 'Flow '.i

如果您想让每行之间有偏移,请使用以下方法。

在gnuplot命令行中键入help iteration获取更多信息。

还要注意@DarioP的答案,其中介绍了do for语法;这将为您提供更接近传统for循环的东西。


感谢您的解决方案“plot for [i=1:1000] 'data'.i.'.txt' using 1:2 title 'Flow '.i”,它对我很有帮助。我在Windows上使用C++和gnuplot 5.2。 - MasoodRehman
但我有另一个问题,我正在编写一个程序,通过fream从硬盘上写入K个文件。K是一个全局变量,因此我想使用gnuplot在我的图表上绘制K个文件。我尝试了for [i = 1:K],但它会出现未定义变量的错误。我尝试了在gnuplot外部使用for循环,但也不起作用。 - MasoodRehman
我在C++中为gnuplot编写了一个函数,它可以处理for[i = 1:5],但是当我使用for[i = 1:K]时,它会出现错误... - MasoodRehman
@MasoodUrRehman 你似乎在尝试在 gnuplot 脚本中使用 C++ 代码中的变量;确保在发送命令到 gnuplot 时打印变量 K 的值。Gnuplot 会说“未定义的变量”,因为C++ 知道 K 是什么,但 gnuplot 不知道。 如果你还卡住了,可以将你的问题作为单独的 C++ 问题发布。 - andyras

95

同时,也要看一下自gnuplot 4.6版本以来非常强大的do { ... }命令:

do for [t=0:50] {
  outfile = sprintf('animation/bessel%03.0f.png',t)
  set output outfile
  splot u*sin(v),u*cos(v),bessel(u,t/50.0) w pm3d ls 1
}

http://www.gnuplotting.org/gnuplot-4-6-do/


1
我能否也使用迭代器t来引用例如文件名或颜色的数组中的索引? - tommy.carstensen
1
我从未尝试过,但我认为这没有任何问题。最终的另一种可能性是直接在方括号中指定数组的项(颜色、名称或其他),如help do所示。 - DarioP
1
我在这里https://dev59.com/OWMl5IYBdhLWcg3wOEvG提出了一个新问题,因为我不确定如何实现。 - tommy.carstensen

11

我有一个名为all.p的脚本。

set ...
...
list=system('ls -1B *.dat')
plot for [file in list] file w l u 1:2 t file

这里的最后两行是文字描述,不是启发式的。然后我运行了【未提供上下文无法确定具体翻译】。
$ gnuplot -p all.p

*.dat 更改为您拥有的文件类型,或添加文件类型。

下一步:在 ~ / .bashrc 中添加此行

alias p='gnuplot -p ~/./all.p'

将您的文件all.p放在您的主目录中,然后就可以使用“p”和“enter”键绘制任何目录中的所有文件。

编辑我更改了命令,因为它没有起作用。之前它包含list(i)=word(system(ls -1B *.dat),i)


对我来说,你的代码不起作用。我不得不写list=system(ls -1B *.dat) - Jaxan
嗯,好的。我在Linux上使用的是4.6版本。 - Jonatan Öström
1
所以我再试了一次,就像你说的那样,它不起作用。我必须在系统调用中使用单引号才能使你的命令起作用: list=system('ls -1B *.dat') - Jonatan Öström
"它对我不起作用。为什么?" - samira
@samira 我不知道。 - Jonatan Öström

10

如果您需要在图表中绘制离散列,请使用以下内容

do for [indx in "2 3 7 8"] {
  column = indx + 0
  plot ifile using 1:column ;  
}

3
这里提供的唯一示例展示了如何循环遍历非连续的数字。 - rehctawrats

2

我希望能够使用通配符来绘制经常放置在不同目录中的多个文件,同时从任何目录工作。我找到的解决方案是在~/.bashrc中创建以下函数:

plo () {
local arg="w l"
local str="set term wxt size 900,500 title 'wild plotting'
set format y '%g'
set logs
plot"
while [ $# -gt 0 ]
        do str="$str '$1' $arg,"
        shift
done
echo "$str" | gnuplot -persist
}

并使用它,例如像plo *.dat ../../dir2/*.out这样的方式,绘制当前目录中的所有.dat文件和一个名为dir2且位于上一级别的目录中的所有.out文件。


你可以添加 plo() { [[ $# -eq 0 ]] && echo "Usage plo file1 file2 ..." || { .... } } 来避免在没有文件的情况下调用 gnuplot - Hastur

1
这里是替代命令:


gnuplot -p -e 'plot for [file in system("find . -name \\*.txt -depth 1")] file using 1:2 title file with lines'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接