Plotting with Gnuplot - gnuplot

I have this input data, I want to plot with gnuplot.
01-02-18 456
01-05-18 438
01-06-18 451
01-09-18 458
How call gnuplot?

As far as I understand your expected output is:
date(mm-dd-yy) time(in s since midnight)
If I am correct you can use:
paste <(awk '{print $1}' dump.run) <(awk '{print $3}' dump.run | awk -F ':' '{print 3600*$1+60*$2+$3}')
Output:
02-02-18 448.932
02-03-18 445.523
02-04-18 443.869
02-05-18 446.106

I think that there is no need for any perl/awk preprocessing in this case. Gnuplot can handle inputs like this natively, you just have to specify the correct timefmt:
$DATA <<EOD
01-02-18 456
01-05-18 438
01-06-18 451
01-09-18 458
EOD
set xdata time
set timefmt '%d-%m-%y'
set format x '%d-%m-%y'
plot $DATA u 1:2 w lp

This is a job for perl (I think;)
perl -pe 's/^([0-9-]+)\s+(\d+)\s+(\d+):(\d+):(\d+)\.(\d+)/sprintf("%s %d.%d", $1, $2*86400+$3*3600+$4*60+$5, $6)/e;' <dump.run
02-02-18 448.932
02-03-18 445.523
02-04-18 443.869
02-05-18 446.106
Or
perl -pe 's/
^([0-9-]+)\s+(\d+)\s+(\d+):(\d+):(\d+)\.(\d+)
/
sprintf("%s %d.%d", $1, $2*86400+$3*3600+$4*60+$5, $6)
/ex;' <dump.run
With a x modifier in perl regex, to be able to split them.
02-02-18 448.932
02-03-18 445.523
02-04-18 443.869
02-05-18 446.106

If you have awk and gnuplot, you can use this script:
awk '{print $1,substr($3,1,2)*3600+substr($3,4,2)*60+substr($3,7)}' file | gnuplot -e 'set xdata time; set timefmt "%m-%d-%y"; plot "/dev/stdin" using 1:2 with lines'
The awk script converts the third column of the input file into seconds.
The resulting data (day, number of seconds) is passed to gnuplot for displaying. The X axis is set as a date with the parameters xdata, and the format is set with timefmt.

Related

grep a value from a file then use it as a folder name to locate a file and plot

Sorry for the confusing title. I couldn't find a better title to describe the issue. I am using gnuplot to plot some files. The files that I am trying to plot are locate in a folder titled process. Inside the process folder is another folder named 100; the structure is as below;
"plot" is the file I recall using gnuplot.
The file plot has the following line;
file='file.dat'
time = "cat file | grep 'time' | cut -d' ' -f2 | tr -d ';' | awk 'NR==1{print $1}'"
plot \
"process/".time."/speed.txt" using 1:3 with line lt 2 lc 6 title ""
So, the goal is to look for the word time in the file.dat and cut its value, which in this case is 100, and use it as a folder name where I am trying to plot the speed.txt file. However, what I have doesn't seem to work when I execute gnuplot. Anyone can help please?
Thank you very much!
First of all, to run a shell command from gnuplot and get its standard output as text, use the system function.
filter_command = "cat ..."
time = system( filter_command )
Secondly, the command string "cat ..." which you have defined will not work properly if you just pass it to system. You intend for the string file in the cat file to be expanded as cat file.dat from gnuplot's file variable.
To do that, we need one more step. There are two ways to do that.
Concatnating strings using . operator
file='file.dat'
filter_command = "cat " . file . " | grep 'time' | cut -d' ' -f2 | tr -d ';' | awk 'NR==1{print $1}'"
Using sprintf function
file='file.dat'
filter_template = "cat %s | grep 'time' | cut -d' ' -f2 | tr -d ';' | awk 'NR==1{print $1}'"
filter_command = sprintf(filter_template, file)
Script
The final script looks like this.
file='file.dat'
filter_template = "cat %s | grep 'time' | cut -d' ' -f2 | tr -d ';' | awk 'NR==1{print $1}'"
filter_command = sprintf(filter_template, file)
time = system( filter_command )
plot "process/".time."/speed.txt" using 1:3 with line lt 2 lc 6 title ""
Although gnuplot is not made for parsing files, you nevertheless can do it, sometimes with strange workarounds.
There is certainly a way to do it with the tools you mentioned: cat, grep, cut, tr and awk. However, not everybody is using Linux and has these tools at hand. Hence, if possible and although it's not optimal, I personally prefer to have "gnuplot-only" solutions which are platform-independent.
So, what the code below basically does is to "plot" the file file.dat into a dummy table line by line and everytime checking if the current line contains the string time:. If yes, write the rest of the line into the variabe myValue.
Get more information on the commands: help strstrt, help strlen, help strcol, help ternary, help datafile separator.
File: file.dat
### file.dat
This is a data file
which contains something
but also a line with
time:100
And many more things...
Maybe also some data...?
1 1.1
2 2.2
3 3.3
4 4.4
# end of file
Code:
### extract key&value from a file and use it in path
reset session
myFile = 'file.dat'
myKey = 'time:'
myValue = ''
myPath(s) = sprintf('process/%s/speed.txt',s)
getValue(line) = strstrt(line,myKey) > 0 ? myValue = line[strstrt(line,myKey)+strlen(myKey):] : myValue
# extract the value for key
set datafile separator "\n"
set table $Dummy
plot myFile u (getValue(strcol(1))) w table
unset table
set datafile separator whitespace
print myValue
print myPath(myValue)
# Your plot command would then look, e.g. like this:
plot myPath(myValue) using 1:3 with line lt 2 lc 6 title ""
### end of code
Result:
100
process/100/speed.txt

Gnuplot no variable "pause"

With the following gnuplot script
set logscale y
set title "Residuals"
set ylabel 'Residual'
set xlabel 'Iteration'
plot "< cat log | grep 'solving for p' | cut -d ' ' -f9 | tr -d ','" title 'p' with lines,\
pause 1
and this version
$ gnuplot --version
gnuplot 4.6 patchlevel 2
I get the following error:
"residuals", line 6: undefined variable: pause
How can I fix that?
Your plot command is incorrect because the line ends with ",\" which means your line is continuing and pause is being treated as a variable passed to plot. So pause doesn't exist.
I suggest removing ",\".

How to run a shell command in Gnuplot and place the output in new file

I have the following Gnuplot:
set encoding iso_8859_1
set key right bottom #font "Helvetica,17"
set ylabel "Lookup error probability" font "Helvetica,17"
set xlabel "Hight of the reader (m)" font "Helvetica,17"
set xtics font "Helvetica,15"
set ytics font "Helvetica,15"
set size 0.75, 1.05
set terminal postscript eps enhanced color #"Helvetica" 16 #size 3.5in,3in
set grid
set key spacing 1.5
set output "ProbError6x6.eps"
list(start,end,increment)=system(sprintf("seq %g %g %g", start, increment, end))
system("(awk '(NR>8 ){print; }' Hight_6x6.csv | sed -e 's/[",]/ /g' | sort -nk36) > pe_H_6x6.txt")
set print "pe_H_6x6.dat"
do for [i in list(2,3.5,0.25) ] {
stats "pe_H_6x6.txt" u ($36==i?($37/$38):1/0) name "A" nooutput
print i*1, A_mean, (A_mean - 1.833*A_ssd/sqrt(A_records)),\
(A_mean + 1.833*A_ssd/sqrt(A_records))
}
plot [][] "pe_H_6x6.dat" using 1:2:3:4 with yerrorlines ls 2 title "6x6 blocks"
The line with the system and with the awk code does not work in my Gnuplot script. However, it works in the unix shell. This code removes commas and , in Hight_6x6.csv, skips the first 8 lines and sort the result by the values of the 36th column.
I cannot make it work in the Gnuplot script.
The CSV file is in this link.
Your issue is probably that you include a double quote inside the command:
system("(awk '(NR>8 ){print; }' Hight_6x6.csv | sed -e 's/[",]/ /g' | sort -nk36) > pe_H_6x6.txt"
^
One work-around is to use backquotes, e.g.:
`(awk '(NR>8 ){print; }' Hight_6x6.csv | sed -e 's/[",]/ /g' | sort -nk36 > pe_H_6x6.txt`
Or as I would have written it:
`tail -n+8 Hight_6x6.csv | tr '",' ' ' | sort -nk36 > pe_H_6x6.txt`

Using gnuplot for files with variable names included

I have a data file that is set up as follows:
varName1= 1 varName2= 3
varName1= 3 varName2= 4
# and so on
Is there a gnuplot command that ignores the variable names?
I just need to plot the numbers.
I can't simply do:
plot "fileName.dat" linenumber
because the variable names are included.
In these cases I would suggest to use an external parser like awk or sed.
In your case this should work:
plot "< awk '{print $2 $3}' test.txt" w l
gnuplot will regard the variable names in your file just as another column. Simply plot fname using 2:4 will work in your example.
If you don't always have the space after "=", you can do set datafile separator '= '. (This sets " " and "=" as independend separators, not "= ".)

Howto improve a coloured line plot by key in third column?

I'm trying to plot temperatures of my laptop, here are my working files at github
I have epoch, temperature & kernel identifier data like so:
1357786501 72 3.6.11-1-ARCH
1357786801 72 3.6.11-1-ARCH
1357787101 60 3.0.57-1-lts
1357787401 54 3.0.57-1-lts
1357800301 52 3.0.57-1-lts
1357800601 48 3.6.11-1-ARCH
1357800902 45 3.6.11-1-ARCH
The closest I've got to what I want is (using this):
set term svg size 1024,708
set xdata time
set key outside
set timefmt "%s"
set ytics 5
set format x "%d/%m"
plot "< awk '{if($3 == \"3.0.57-1-lts\") print}' temp.csv" u 1:2 t column(3) w p pt 2, \
"< awk '{if($3 == \"3.6.10-1-ARCH\") print}' temp.csv" u 1:2 t column(3) w p pt 2, \
"< awk '{if($3 == \"3.6.11-1-ARCH\") print}' temp.csv" u 1:2 t column(3) w p pt 2, \
"< awk '{if($3 == \"3.8.1-1-mainline-dirty\") print}' temp.csv" u 1:2 t column(3) w p pt 2
gihub kaihendry
Is there a way to avoid using awk? When I don't use this awk, it fails to plot differing kernel identifiers.
Can I make it a continuous line with different colours instead somehow?
Any ideas how to make SVG output without width/height? Any tricks to make it look better?
If your version of Gnuplot is recent enough, you can use a for-loop and iterator to loop over the different strings you want to match, see for example manual page 88-89 or this blog entry. To ignore non-matching lines you can use the ternary operator (cond ? iftrue : iffalse) to set these values to "Not-A-Number" (1/0 or NaN):
set xdata time
set key outside
set timefmt '%s'
set ytics 5
set format x '%d/%m'
set style data linespoints
archs = "`cut -d' ' -f3 temp.csv | sort -u | tr '\n' ' '`"
plot for [arch in archs] 'temp.csv' using 1:((strcol(3) eq arch) ? $2:1/0) title arch

Resources