且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何根据GNUPlot中列的值绘制单行/多行

更新时间:2022-10-17 15:18:18

这是一个依赖几个标准工具的解决方案,应该可以在任何标准Linux机器上使用,而且大多数基于bash。让我们从您提供的数据文件开始,没有第一行

第1步:将数据拆分为一个文件每场1: awk -f split.awk< data.log ,其中 split.awk

 #!/ usr / bin / awk -f 
#擦除前面的文件
BEGIN {system(rm file _ *。dat); }

#打印特定文件中的每一行
{print $ 0>>(file_$ 1.dat)}
第2步:复制每个生成的数据文件的第一行(因为在gnuplot中使用其中一个字段作为标题会忽略该行当绘制时):

  for f in`ls file _ *。dat`;做
头-n 1 $ f> tmp.dat
cat $ f>> tmp.dat
mv tmp.dat $ f
完成;

第3步:生成一个gnuplot脚本,该脚本包含

  echoplot 绘制不同文件的命令(参见下面的完整脚本)。 \\>>在`ls file _ *。dat`中为plot.plt 
for f;做
使用2:3标题栏标题(1)回显'$ f',并带有线点lw 2,\\>> plot.plt
完成;
echo0 notitle>> plot.plt

FIY,最后的0图仅仅是因为将几个文件绘制到单个绘图,gnuplot在行尾需要一个尾部反斜杠。如果有一个,并且在下面一行没有任何内容,则会生成一个错误。所以我只能找到这个愚蠢的技巧才能使它工作...



第4步:调用生成的gnuplot脚本。



使用您提供的数据,以下脚本最终为:



可能本来可以缩短,但我喜欢保持可读性。

完整脚本:

 #!/ bin / bash 

#1 - 将数据拆分为一个文件每场1
awk -f split.awk< data.log

#2 - 复制第一行(对gnuplot有用)
用于`ls file _ *。dat`中的f;做
头-n 1 $ f> tmp.dat
cat $ f>> tmp.dat
mv tmp.dat $ f
完成;

#3 - 生成gnuplot脚本
echoset terminal pngcairo size 800,500> plot.plt
echoset output'b.png'>> plot.plt
echoset multiplot layout 1,2>> plot.plt

echoset title'Packets'>> plot.plt
echoplot \\>>在`ls file _ *。dat`中为plot.plt
for f;做
使用2:3标题栏标题(1)回显'$ f',并带有线点lw 2,\\>> plot.plt
完成;
echo0 notitle>> plot.plt

echoset title'Jitter'>> plot.plt
echoplot \\>>在`ls file _ *。dat`中为plot.plt
for f;做
使用2:4标题栏标题(1)回应'$ f',并带有线点lw 2,\\>> plot.plt
完成;
echo0 notitle>> plot.plt

echounset multiplot>> plot.plt

#4 - 调用gnuplot脚本
gnuplot plot.plt


I have a little problem using gnuplot. Here is my datafile:

From Time Packets Jitter  
127.0.0.1:53091 1 0 274  
127.0.0.1:53091 2 0 417  
127.0.0.1:53091 3 36 53  
127.0.0.1:53091 4 215 55  
127.0.0.1:53090 4 215 55  
127.0.0.1:53091 5 215 33  
127.0.0.1:53090 6 256 78

(I put that "time" for the test, but it will be replaced by a datetime after it works)

I want to draw two different graphics, with Time column in x axis on both, and Packets column (on a first graphic) & Jitter column (on a second graphic) in y axis. But, as you may have seen, I don't know how many different values from the From column I will have (minimum 1, but I don't know the maximum, the data file will be refresh and some values will be added each x seconds).
So my problem is that I want to make another 'line' each different From values on both graphics.
In fact, having the From value in title of lines (example : "127.0.0.1:53091").
I want to add that if it's possible to change column order.

I tried:

plot 'data.log' using 3:xtic(2) title 'Packets' with lines, \
     'data.log' using 4:xtic(2) title 'Jitter' with lines

But it's on the same graphic (I don't use multiplot yet, I tried to make the multiple lines works before).

Is it possible ? If it is, How can I plot this two graphics in gnuplot ?
If not, we can remove the Jitter graphic, and plot only the Packets column on a single graphic but with the different From values.

Here is a solution relying on several standard tools that should be available on any standard Linux box, and mostly based on bash. Lets starts with the datafile you provide, without the first line.

Step 1: split data into one file per field 1 : awk -f split.awk < data.log, with the following in split.awk:

#!/usr/bin/awk -f
# erase previous files
BEGIN { system("rm file_*.dat"); }

# print each line in a specific file
 { print $0 >>( "file_" $1 ".dat") }

Step 2: duplicate first line of each produced datafile (because using one of the fields as title in gnuplot makes this line ignored when plotting):

for f in `ls file_*.dat`; do 
    head -n 1 $f > tmp.dat
    cat $f >> tmp.dat
    mv tmp.dat $f
done;

Step 3: generate a gnuplot script that holds a plot command that plots the different files (see full script below).

 echo "plot \\" >> plot.plt
 for f in `ls file_*.dat`; do 
     echo "   '$f' using 2:3 title columnheader(1) with linespoints lw 2, \\" >> plot.plt
done;
echo "    0 notitle" >> plot.plt

FIY, the last "0" plot is there only because to plot several files onto a single plot, gnuplot needs a trailing backslash at the end of the line. And if there is one, and nothing to plot at the following line, an error is generated. So I could only find this dumb trick to make it work...

Step 4: call the generated gnuplot script.

With the data you provided, the script below ends up as:

Probably could have been shorter, but I like to keep things readable.

Full script:

#!/bin/bash

# 1 - split data into one file per field 1
awk -f split.awk < data.log

# 2 - duplicate first line (useful for gnuplot)
for f in `ls file_*.dat`; do 
    head -n 1 $f > tmp.dat
    cat $f >> tmp.dat
    mv tmp.dat $f
done;

# 3 - generate gnuplot script
echo "set terminal pngcairo size 800,500" > plot.plt
echo "set output 'b.png'" >> plot.plt
echo "set multiplot layout 1,2" >> plot.plt

echo "set title 'Packets'" >> plot.plt
echo "plot \\" >> plot.plt
for f in `ls file_*.dat`; do 
    echo "   '$f' using 2:3 title columnheader(1) with linespoints lw 2, \\" >> plot.plt
done;
echo "    0 notitle" >> plot.plt

echo "set title 'Jitter'" >> plot.plt
echo "plot \\" >> plot.plt
for f in `ls file_*.dat`; do 
    echo "   '$f' using 2:4 title columnheader(1) with linespoints lw 2, \\" >> plot.plt
done;
echo "    0 notitle" >> plot.plt

echo "unset multiplot" >> plot.plt

# 4 - call gnuplot script
gnuplot plot.plt