Multiple data blocks, changing plot title - gnuplot

I'm trying to build a graph with a csv file.
It's supposed to have an undetermined number of data blocks inside.
My CSV looks like this :
year;amount;NAME1
year;amount;NAME1
year;amount;NAME1
year;amount;NAME2
year;amount;NAME2
year;amount;NAME2
So I want my graph to have two curves (or more if there's more blocks), one named NAME1 and the other NAME2.
The only way I've fount to retrieve the name is by using:
title columnhead(3)
But by using this, the first line of my csv is missing, and I can't figure why ...
Here's my script generating the image
gnuplot <<EOF
set terminal png
set title "Stages par professeur par années"
set output "stages_entr_ann.png"
set auto x
set key on outside left bmargin
set datafile separator ";"
set xtics 1
set ytics 1
stats 'fichier3_t.stat'
plot for [IDX=0:STATS_blocks-1] 'fichier3_t.stat' index IDX u 1:2 title columnhead(3) with linespoints ls IDX
EOF
(There's an unknow amount of blocks, so I'm using STATS_blocks)

The point is that columnhead expects something like this:
Year Amount Name
2013 5000 John
2014 8000 Max
2015 12000 Susanne
i.e. the first row of each colum is treated as label, not as data. While gnuplot extracts the name fine, it ignores the rest of the line.
There is no simple and direct solution for this, but you can do a workaround:
plot for [IDX=0:STATS_blocks-1] 'fichier3_t.stat' index IDX u 1:(1/0) title columnhead(3) with linespoints ls IDX, for [IDX=0:STATS_blocks-1] 'fichier3_t.stat' index IDX u 1:(1/0) notitle with linespoints ls IDX
To make it more clear:
plot 'fichier3_t.stat' ... u 1:(1/0) title columnhead(3) with linespoints ..., \
'fichier3_t.stat' ... u 1:2 notitle with linespoints ...
The first command is similar to yours, it just does not plot any data (because 1/0 is always invalid). It's only there to generate the entry in the legend (key).
The second command plots the data, but does not generate any entry in the legend. Just make sure the same line style is assigned to the two plots.
If the table is large and speed is a problem, you may also use every for the title generating command to reduce the number of points it trys to plot.
Finally, you may also get the message "No valid data in xrange" or similar. That's intended here but shouldn't be a problem.

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.

How to plot data with lines like "<text> <datetime>", with gnuplot?

My data is a typical CSV-like text where each line consists of two columns where the first is text and the second a unix timestamp, as follows:
Mom 1441008169
Dad 1442516527
Ken 1441783871
...
<text> <unix-timestamp>
I thought I could arrange the data along a timeline, drawing dots/shapes of color corresponding to the text in the line, at a point along the x axis corresponding to the timestamp. At best I got gnuplot to tell me:
line 0: Need using spec for y time data
when I tell it to:
set ydata time
set timefmt "%s"
plot "-"
<data>
EOF
I want to render a plot using dots, or diamonds or shapes with color corresponding to the text string in first column. In other words, if my text values fall within the set {"Mom", "Dad", "Ken"}, then gnuplot should draw these shapes corresponding to "Mom" in red, "Dad" in green, and "Ken" in blue, or something like that, at points corresponding to their respective timestamps along the x axis.
The challenge for me is to have gnuplot distinguish between the text strings. The data can be thought of as, for instance, incoming calls from a person where the timestamp indicates date and time for the call and text represents the person calling. I thought representing these data as plotted dots/orbs/diamonds/whatever of different color along a time line would be a good idea, visually.
How would I achieve that? I can, optionally, generate some sort of identifier table where the unique text strings are each equated to a unique sequential generated ID, if that helps gnuplot.
I guess what you want is something like this
The x-axis spans the time interval which is specified by your data file (2nd column). Each name (Ken, Mom, Dad) is represented by a different point type (pt) and a specific colour (lc rgb 'color').
You can generate this plot by the following commands (assuming your data file's name is 'test'):
set xdata time
set timefmt "%s"
set format x "%d/%m/%y"
set xtics rotate
unset ytics
set yrange[0:2]
plot 'test' u ($2):(stringcolumn(1) eq "Ken" ? 1 :1/0) w p pt 5 ps 1.5 lc rgb 'blue' t 'Ken',\
'' u ($2):(stringcolumn(1) eq "Dad" ? 1 :1/0) w p pt 7 ps 1.5 lc rgb 'red' t 'Dad',\
'' u ($2):(stringcolumn(1) eq "Mom" ? 1 :1/0) w p pt 3 ps 1.5 lc rgb 'green' t 'Mom'
You can use different point types by assigning different numbers to pt. ps specifies the point size.
Another representation I came up with is the following:
You can generate it with:
plot 'test' u ($2):(1):(stringcolumn(1)) with labels t '',\
'' u ($2):(0.95) with impulses t ''
I hope this answers your question, and it is what you were looking for.

Is there a way to put a label for the last entry in gnuplot?

I want to use gnuplot for real time plotting (Data gets appended to file which I use for plotting and I use replot for real time plotting). I also want to put a label for the latest entry which is plotted. So as to get a idea what is the latest value. Is there a way to do this?
If you are on a unixoid system, you can use tail to extract the last line from the file and plot it separately in whatever way you desire. To give a simple example:
plot\
"data.dat" w l,\
"< tail -n 1 data.dat" u 1:2:2 w labels notitle
This will plot the whole of data.dat with lines and the last point with labels, with the label depicting the value.
There is no need to use the Linux command tail, you can simply do it with gnuplot-only, hence platform-independently.
The principle: while plotting the data, you assign the values of column 1 and 2 to variables x0 and y0, respectively.
After the first plot command, x0 and y0 will contain the last values.
With this, you don't have to load the file a second time for extracting the last values.
For the label plotting, use these values and print the label with a sprintf() expression (check help sprintf).
The construct '+' u ... every ::0::0 is just one way of many ways to plot a single data point.
Data: SO28152083.dat
1 5.1
2 2.2
3 3.3
4 1.4
5 4.5
Script: (works with gnuplot 4.4.0, March 2010 or even with earlier versions)
### plot last value as label
reset
FILE = "SO28152083.dat"
set key noautotitle
set offsets 0.5,0.5,1,1
plot FILE u (x0=$1):(y0=$2) w lp pt 7 lc rgb "red" ti "data", \
'+' u (x0):(y0):(sprintf("%g",y0)) every ::0::0 w labels offset 0,1
### end of script
Result:

Gnuplot read line style from data file column

I'd like to draw an impulse graph from a text file that looks like this:
II 5 0 0 288.40 1.3033e+14
II 6 0 0 289.60 1.5621e+14
II 1 4 0 302.70 3.0084e+13
II 2 4 0 303.40 4.0230e+13
II 1 5 1 304.40 3.4089e+13
The plot conceptually should be plot "datafile.dat" using 5:6 w impulses ls $2.
Basically, given a previously defined set of line styles, I'd like to input the line style number from column 2 for every couple of plotted points from column 5 and 6.
Also I'd like to create a text box, for every plotted point, taking strings from the first four columns.
Does somebody know if that's possible?
To use the data from column two as line style use set style increment user and linecolor variable:
set style increment user
plot "datafile.dat" using 5:6:2 with impulses lc var
In order to place a label, use the labels plotting style:
plot "datafile.dat" using 5:6:1 with labels offset 0,1
Putting everything together, you have:
set style increment user
set for [i=1:6] style line i lt i
set yrange [0:*]
set offsets 0,0,graph 0.1,0
plot "datafile.dat" using 5:6:2 with impulses lc var, "" using 5:6:1 with labels offset 0,1
The result with 4.6.3 is:
Thanks for the helpful answer above. It almost solved my problem
I'm actually trying to use a column from my data file to specify a linestyle (dot, squares,triangles, whatever as long as it's user-defined), and not a linecolor. Is there any way to do that?
This line works : I get points with different colors (specified in column 4), but the point style is the same.
plot "$file" u 1:2:4 w p notitle lc var, "" using 1:2:3 with labels offset 0,1 notitle
Replacing lc with ls after defining my own styles doesn't work (ls can't have variable as an option)
I can live without different linestyles, but it would be much prettier.
You only have to replace the lineset for [i=1:6] style line i lt i for set for [i=1:6] style line i lt i pt %, Where % can be any type of point you want

How do I set axis label with column header in gnuplot?

My question is very simple. Suppose I have a datafile with column headers, like as follows
first second
1 1
2 1
3 6
4 9
In gnuplot how do i make it so that the datafile is plotted using the column header as axis label? e.g. by calling
plot datafile using 1:2
i get the xaxis labeled first and the yaxis labeled second?
edit: I do know that I can use the column header as a key entry via set key auto title column head, however that's not quite what I'm looking for.
To elaborate the suggestion of #andyras, here is how you can do it:
datafile = 'filename.txt'
firstrow = system('head -1 '.datafile)
set xlabel word(firstrow, 1)
set ylabel word(firstrow, 2)
plot datafile using 1:2
You must plot with the explicit using statement, otherwise gnuplot will complain about bad data on line 1.
I don't think this feature is built in to gnuplot; you would probably have to use an awk-like utility to pull those labels out of a datafile.
You could try submitting a feature request on gnuplot's sourceforge site, and get feedback from the developers there.
Another question where people believe it can't be done with gnuplot. Here is a simple gnuplot-only solution without external tools, hence platform-independent.
Data: SO16089301.dat
first second
1 1
2 1
3 6
4 9
Script: (works with gnuplot 4.6.0, March 2012)
### extracting axes labels from datafile
reset
FILE = 'SO16089301.dat'
stats FILE u (myX=strcol(1), myY=strcol(2)) every ::0::0 nooutput
set xlabel myX
set ylabel myY
plot FILE u 1:2 w lp pt 7 lc rgb "red"
### end of script
Result:
I think it is supported. You are just supposed to be able to use "":
plot 'file' using "first":"second"
Although, if you want to do math in your using specification, you'll need the column("") function, too
plot 'file' using "first":(column("second")-(column("thrid"))
(Using only quoted header names with the math didn't work for me, anyway.)

Resources