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, which doesn't need external files. First I extract all the different sources in the first column and store them in a gnuplot variable:
filename = 'data.log'
from=system('tail -n +2 '.filename. '| cut -f 1 -d " " | sort | uniq')
For the filtering during plotting I use awk
and define a gnuplot function
select_source(w) = sprintf('< awk ''{if ($1 == "%s") print }'' %s', w, filename)
Now you can iterate over all source stored in from
. The complete gnuplot script is as follows:
filename = 'data.log'
from=system('tail -n +2 '.filename. '| cut -f 1 -d " " | sort | uniq')
select_source(w) = sprintf('< awk ''{if ($1 == "%s") print }'' %s', w, filename)
set style data linespoints
set multiplot layout 1,2
set title 'Packets'
plot for [f in from] select_source(f) using 2:3 title f
set title 'Jitter'
plot for [f in from] select_source(f) using 2:4 title f
unset multiplot
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With