gnuplot plot from string - string

Is it possible to pass to plot data in a string?
I mean do something like this:
plot "09-13-2010,2263.80 09-14-2010,2500" using 1:2 with lines

It is possible to do something like:
set xdata time
set timefmt "%m-%d-%y"
plot "< echo '09-13-2010,2263.80 09-14-2010,2500' | tr ' ' '\n' | tr ',' ' '" using 1:2 with lines
Where the < character indicates to Gnuplot that we want our input from the output of a command. Gnuplot separates records with a newline. Groups of records are separated by a blank record. Within a record, the default column separator is a space. In the above example tr is used to split your data into lines, and the rewrite the lines into records.
Another way to plot your data from a string is to use the "-" input specifier, and then load the data in from the command line. A program could easily emit the following:
set xdata time
set timefmt "%m-%d-%y"
plot '-' using 1:2 with lines
09-13-2010 2263.80
09-14-2010 2500
e
Your best bet is to use an input file like:
09-13-2010 2263.80
09-14-2010 2500
Assuming the input file is named mydata.txt, you can then plot it with the commands:
set xdata time
set timefmt "%m-%d-%y"
plot 'mydata.txt' using 1:2 with lines
All the examples above give you something like:
If you want to plot two data series using dates and the `-' input you could do the following:
set xdata time
set timefmt "%m-%d-%y"
plot '-' using 1:2 title "Series 1" with lines,'-' using 1:2 title "Series 2" with lines
09-13-2010 2263.80
09-14-2010 2500
e
09-13-2010 2500
09-14-2010 2263.80
e
The previous example gives:

Related

Subtract smoothed data from original

I wonder whether there is a way to subtract smoothed data from original ones when doing things of the kind:
plot ["17.12.2020 08:00:00":"18.12.2020 20:00:00"] 'data3-17-28.csv1' using 4:5 title 'Sensor 3' with lines, \
'' using 4:5 smooth acsplines
Alternatively I would need to do it externally, of course.
As #Suntory already suggested you can plot smoothed data into a table.
However, keep in mind, the number of datapoints will be determined by set samples, default setting is 100 and the smoothed datapoints will be equidistant. So, if you set samples to the number of your datapoints and your data is equidistant as well, then all should be fine.
Concatenating data line by line is not straightforward in gnuplot, since gnuplot is not intended to do such operations.
The following gnuplot-only solution assumes that you have your data in a datablock $Data without headers and empty lines. If not, you could either plot it with table from file into a table named $Data or use the following approach in the accepted answer of this question: gnuplot: load datafile 1:1 into datablock
If you don't have equidistant data, you need to interpolate data, which is also not straightforward in gnuplot, see: Resampling data with gnuplot
It's up to you: either you use external tools (which might not be platform-independent) or you apply a somewhat cumbersome platform independent gnuplot-only solution.
Code:
### plot difference of data to smoothed data
reset session
$Data <<EOD
1 0
2 13
3 16
4 17
5 11
6 8
7 0
EOD
stats $Data u 0 nooutput # get number of rows or datapoints
set samples STATS_records
set table $Smoothed
plot $Data u 1:2 smooth acsplines
unset table
# put both datablock into one
set print $Difference
do for [i=1:|$Data|] {
print sprintf('%s %s',$Data[i],$Smoothed[i+4])
}
set print
plot $Data u 1:2 w lp pt 7, \
$Smoothed u 1:2 w lp pt 6, \
$Difference u 1:($2-$4) w lp pt 4 lc "red"
### end of code
Result:
If I well understand you would like this :
First write your smooth's data in out.csv file
set table "out.csv" separator comma
plot 'file' u 4:5 smooth acsplines
unset table
Then this line will paste 'out.csv' to file as an appended column.You will maybe need to delete first lines using sed command (sed '1,4d' out.csv)
stats 'file' matrix
Thanks to stats we automatically get the number of column in your original data (STATS_size_x).
plot "< paste -d' ' file out.csv" u 4:($5-$(STATS_size_x+2)) w l
Could you please try this small code on your data.

Gnuplot: CSV and Date on X-Axis

I want to plot cryptocurrency data which is stored in a CSV file.
This is what the CSV file looking at the moment:
Date,Total,XMR,ETH,BTC,BCH
2018-01-20 14:28:09,-48.31496473496111,-2.618473974057121,9.759254879456023,-32.73371338624,-22.72203225412001
2018-01-20 14:32:42,-48.70059864440001,-2.6060653245296663,9.414353657705647,-32.67846583748799,-22.830421140088
2018-01-20 14:35:22,-48.63036074628374,-2.5440902562853935,9.414353657705647,-32.67846583748799,-22.822158310216004
2018-01-20 14:39:31,-48.541251796683724,-2.5440902562853935,9.414353657705647,-32.58935688788797,-22.822158310216004
This is my gnuplot script so far:
set key inside bottom right
set title 'Revenues'
set datafile separator ','
set ylabel 'EUR'
set grid
plot for [col=2:5] "data.txt" using 0:col with lines lw 2 title columnheader
This is what the result looks like:
But as you can see in the first column, every data set has a date which I also want to use. It should appear as the x axis label in a shorter form (e.g. 18/20/01) and the axis should also scale correctly.
My approach was this:
set xtics rotate
set timefmt '%Y-%m-%d %H-%M-%S'
set format x "%d-%m"
set xdata time
plot for [col=2:5] "data.txt" using 0:col:xtic(1) with lines lw 2 title columnheader
...which results in...
As you can see, the label for the x axis is the correct column but it's neither the format I want nor it's scaled (mention that I changed the last date to 2019).
Can you tell me how I can achieve this?
Gnuplot start counting columns at 1:
set datafile separator ","
set timefmt '%Y-%m-%d %H-%M-%S'
set format x "%d-%m"
set xdata time
plot for [col=2:5] "data.txt" using 1:col

In the gnuplot how do I plot data from two different files into a single plot?

I have two different files to plot in the gnuplot. they use a) different separator b) different time on x-axis
hence for each of them to plot separately I need to pass
set datafile separator
set timefmt
I would like to impose/overlay both data in a single graph such, that they are aligned with time
how could I do this?
The problem with the different separators can be addressed by using the format after the using modifier to specify a different separator for each file, e.g.:
plot 'file1.dat' u 1:2 '%lf,%lf'
plots a two column file with comma separator. See help\using for some more detail.
I am not expert of time formats, so I don't know how to deal with the timestamp format problem. But maybe you can use some function like strftime(). I never tried it, but it seems to me it does what you need.
You're right, you will need to pass set datafile separator and set timefmt once per file. You can do it like this:
set terminal <whatever>
set output <whatever.wht>
set xdata time # tell gnuplot to parse x data as time
set format x '%F' # time format to display on plot x axis
set datafile separator ' ' # separator 1
set timefmt '%F' # time format 1
plot 'file1'
set datafile separator ',' # separator 2
set timefmt '%s' # time format 2
replot 'file2'
The replot command by itself replots the previous line, and if you specify another line to be plotted that will go on top of the first one like I did here.
It seems to me that you have 2 options. The first is to pick a datafile format and beat both datafiles into that format, maybe using awk:
plot '<awk "-f;" "{print $1,$2}" data1' using 1:2 w lines,\
'data2' using 1:2 w lines
*Note, your awk command will almost certainly be different, this just shows how to use awk in an inline pipe.
Your second option is to use multiplot with explicit axes alignment:
set multiplot
set xdata time
set datafile sep ';' #separator for first file
set timefmt "..." #time format for first file
set lmargin at screen 0.9
set rmargin at screen 0.1
set tmargin at screen 0.9
set bmargin at screen 0.1
unset key
plot 'data1' u 1:2 w lines ls 1 nontitle
set key #The second plot command needs to add both "titles" to the legend/key.
set datafile sep ',' #separator for second file
set timefmt "..." #time format for second file
unset border
unset xtics
unset ytics
#unset other stuff that you set to prevent it from being plotted twice.
plot NaN w lines ls 1 title "title-for-plot-1", \
'data1' u 1:2 w lines ls 2 title "title-for-plot-2"
The plot NaN trick is only necessary if you want to have things show up correctly in the legend. If you're not using a legend, you can not worry about it.
This works for me :
reset
set term pngcairo
set output 'wall.png'
set xlabel "Length (meter)"
set ylabel "error (meter)"
set style line 1 lt 1 linecolor rgb "yellow" lw 10 pt 1
set style line 2 lt 1 linecolor rgb "green" lw 10 pt 1
set style line 3 lt 1 linecolor rgb "blue" lw 10 pt 1
set datafile separator ","
set key
set auto x
set xtics 1, 2, 9
set yrange [2:7]
set grid
set label "(Disabled)" at -.8, 1.8
plot "file1.csv" using 1:2 ls 1 title "one" with lines ,\
"file2.csv" using 1:2 ls 2 title "two" with lines ,\
"file3.csv" using 1:2 ls 3 title "three" with lines
set output

Reading gnuplot legend from csv

I've got a data.csv file which is structured like this:
n John Smith stats Sam Williams stats
1 23.4 44.1
2 32.1 33.5
3 42.0 42.1
Currently I'm plotting with the following command in gnuplot:
plot 'data.csv' using 1:2 title 'John' with lines, '' using 1:3 title 'Sam' with lines
The question is how to retrieve first names from the first line of .csv rather than entering them manually?
In addition, is it possible to make it adjustable in case I add a column to the table, so it automatically adds another line with the appropriate title?
You say you have a csv file, so I assume your data file looks like this (and is saved in infile.csv):
n,John Smith stats,Sam Williams stats
1,23.4,44.1
2,32.1,33.5
3,42.0,42.1
If your version of Gnuplot is recent enough, you can use columnhead as the title argument:
echo "
set datafile separator ','
plot 'infile.csv' using 1:2 with lines title columnhead
" | gnuplot --persist
Or use the key option:
echo "
set datafile separator ','
set key autotitle columnhead
plot 'infile.csv' using 1:2 with lines, '' using 1:3 with lines
" | gnuplot --persist
Edit - shorten headings
echo "
set datafile separator ','
set key autotitle columnhead
plot '< sed -r \"1 s/,([^ ]+)[^,]+/,\1/g\" infile.csv' using 1:2 with lines, '' using 1:3 with lines
" | gnuplot --persist
Output:
Note this answer to a follow-up question may also be relevant.
You want to extract only a portion of the columnheader for the legend.
Update:
This is a task which you can easily do with gnuplot>=5.4.0. Check help columnheader and help word.
plot for [col=2:4] FILE u 1:col w l title word(columnheader(col),1)
However, the above command will not work with gnuplot versions 4.6.0 to 5.2.8. Whereas title columnheader(col) will work, but title word(columnheader(col),1) will not.
Workaround: (for gnuplot versions 4.6.0 to 5.2.8)
Again a strange gnuplot-only workaround.
In short: In a plot for loop which starts at 1 you assign the header of column 2 to the variable myHeader, however, you are plotting nothing (NaN) with title myHeader='' (empty string will not generate a keyentry). In the next iteration you plot column 2, with the previously extracted header. This will continue until the last column (here: N=4).
Data: SO13371449.csv (some more example data added)
n, John Smith stats, Sam Williams stats, Tom Muller stats
1, 23.4, 44.1, 22.1
2, 32.1, 33.5, 25.7
3, 42.0, 42.1, 40.0
Script: (works for gnuplot>=4.6.0)
### get only a portion of columnheader for the title (gnuplot>=4.6.0)
reset
FILE = "SO13371449.csv"
set datafile separator ","
myHeader = ''
N=4
plot for [col=1:N] FILE u ($0==0 && col<N ? myHeader=word(strcol(col+1),1) : 0, \
col==1 ? NaN : $1):col w lp pt 7 title myHeader
### end of script
Result: (created with gnuplot 4.6.0)

gnuplot using vertically stored datafile

I am trying to figure out the basic syntax to draw a line graph of a server's disk usage. The data is stored in a Oracle database which obviously stores new data on separate rows, not on the same row. From what I have read so far, gnuplot seems to prefer related data to be on the same row. My data looks like this.
#disk date GB_used
disk1 20121022 99
disk1 20121023 104
disk2 20121022 170
disk2 20121023 182
Can gnuplot handle data in this format? The graph output would have 2 lines, one for disk1 and one for disk2. The data file only has a few disk_numbers but will eventually contain hundreds of rows from records for each day.
I assume you want to plot GB_used vs date for disk1 and disk2. If that's the case, this is almost the format gnuplot likes:
#disk date GB_used
disk1 20121022 99
disk1 20121023 104
disk2 20121022 170
disk2 20121023 182
Here's a simple awk script to convert it:
awk 'BEGIN{getline;x=$1;print $0}{if($1!=x){print '\n\n';print$0;x=$1}else{print $0}}' example.dat
In this case, gnuplot would want you to separate the two datasets by 1 or 2 blank lines. If you separate by 1 blank line, gnuplot will plot 2 lines of the same linetype
If you separate by 2 blank lines, gnuplot will plot both data sets, and you can make it plot with different line types:
plot for [idx=0:1] 'example.dat' i idx u 2:3 w lines
Essentially the same effect can be achieved by filtering as demonstrated in the answer by #andyras
Yes, it can, but you may have to trick it a bit. Here is the basic plot command:
plot "< sed 's/^disk//' data.dat" using ($1==1?$2:1/0):3 title 'disk 1', \
'' using ($1==2?$2:1/0):3 title 'disk 2'
First I run the data file through sed to remove the string 'disk' from each row. Then gnuplot makes a conditional comparison after the using keyword. In the first plot command, it checks if the first data column is equal to 1 (which it would be for 'disk1' - 'disk'), if so it plots the second column vs. the third, else it plots 1/0 (which gnuplot ignores).
I tried doing it in pure gnuplot:
plot 'data.dat' u ($1 eq 'disk1'?$2:1/0):3 t 'disk 1', \
'' u ($1 eq 'disk2'?$2:1/0):3 t 'disk 2'
but it did not like the string comparison in the plot command.
To get the time format right you will want to do something like
set xdata time
set timefmt '%Y%m%d'
set format x '%F'
before the plot command.
EDIT:
As #mgilson pointed out, the strcol command can be used if you want a 'pure gnuplot' solution:
plot 'data.dat' u (strcol(1) eq 'disk1'?$2:1/0):3 t 'disk 1', \
'' u (strcol(1) eq 'disk2'?$2:1/0):3 t 'disk 2'

Resources