Gnuplot plot data with text column as X axis - gnuplot

I have a text file as follows:
ls 10
cd 5
cut 12
awk 7
...
I would like to plot it using gnuplot with the text column as the X axis:
plot 'data.txt' u 1:2
But I get this error:
warning: Skipping data file with no valid points
^
x range is invalid
I appreciate your help

$data << EOD
ls 10
cd 5
cut 12
awk 7
EOD
# this is all just plot layout stuff; customize to taste
unset border
set tics scale 0
set xzeroaxis
set title "x coord = line number"
# use line number for x coordinate, column 1 for tic label
plot $data using 0:2:xticlabel(1) with impulse

Check help xticlabels.
And try this:
reset session
$Data <<EOD
ls 10
cd 5
cut 12
awk 7
... 9
EOD
set boxwidth 0.7
set style fill solid 1.0
set yrange[0:]
plot $Data u 2:xtic(1) w boxes

Related

gnuplot: how to draw a set of triangles from a file?

In gnuplot, we can set object polygon to draw a polygon, including triangles, given its coordinates.
But how to do draw a set of triangles whose coordinates are stored in a file where each line is in the format <x1> <y1> <x2> <y2> <x3> <y3>?
As for rectrangles/circles, this task can be done using plot and with boxxy/with circles options, but there is no with triangles option in gnuplot.
A possible solution is to use with vectors by drawing each edge, but it is a bit complicated and this method does not support color filling.
I cannot think of a way to do this in one step; the data format does not match any of gnuplot's plotting styles.
One approach is to transform the data via a temporary file. Here is an example that works in version 5.2 and newer. If you are using a newer gnuplot then you could substitute with polygons for with filledcurves closed.
$DATA << EOD
1 1 2 2 3 1
11 11 14 14 17 11
21 21 22 22 23 21
15 5 16 6 17 5
6 6 7 7 8 6
EOD
set table "temp.dat"
plot $DATA using (sprintf("%g %g\n %g %g\n %g %g\n \n",$1,$2,$3,$4,$5,$6)) with table
unset table
unset key
set style fill solid noborder
plot "temp.dat" using 1:2 with filledcurves closed fillcolor "forest-green"
Note: I was originally going to show use of a temporary datablock rather than an intermediate temporary file, but it this doesn't work because the formatted output from with table does not translate the newline characters \n into empty datablock lines.
Edit (show variable color)
The extra data field containing a RGB color must be present in every input line of the reformatted data, but only the value from the first vertex of each polygon is used. The sprintf format in this example has been modified to reproduce the color (NB: hexadecimal integer value) from the original data file accordingly, with zeros for the dummy values in the remaining polygon vertices.
$DATA << EOD
1 1 2 2 3 1 0x00ffff
11 11 14 14 17 11 0x191970
21 21 22 22 23 21 0x2e8b57
15 5 16 6 17 5 0xffc020
6 6 7 7 8 6 0x8b000
EOD
set table "temp.dat"
plot $DATA using (sprintf("%g %g 0x%x\n %g %g 0\n %g %g 0\n \n",$1,$2,int($7),$3,$4,$5,$6)) with table
unset table
unset key
set style fill solid noborder
plot "temp.dat" using 1:2:3 with filledcurves closed fillcolor rgb variable
My suggestion would have been the same as #Ethan's. Therefore, here is an alternative approach using set object polygon.
It also requires gnuplot>=5.2 since it uses indexing of datablock lines. Hence, the data should already be in a datablock without empty or commented lines. But how to get a file into a datablock?
Either something like:
set table $Data
plot FILE u 1:2:3:4:5:6:7 w table
unset table
or alternatively see here: gnuplot: load datafile 1:1 into datablock
Script:
### draw some colored triangles from a datablock
reset session
$Data <<EOD
0 0 2 1 1 2 0xff0000
5 1 3 2 4 4 0x00ff00
3 3 2 5 1 4 0x0000ff
EOD
vx(n,t) = word($Data[n],t*2-1) # vertex x-coordinate
vy(n,t) = word($Data[n],t*2) # vertex y-coordinate
color(n) = word($Data[n],7) # triangle color
set linetype 1 lc rgb "black"
do for [n=1:|$Data|] {
set obj n polygon from vx(n,1),vy(n,1) to vx(n,2),vy(n,2) to vx(n,3),vy(n,3) to vx(n,1),vy(n,1)
set obj n fc rgb color(n) fs solid 0.5 border lt 1 lw 3
}
set size square
set xrange[0:5]
set yrange[0:5]
plot NaN notitle # or plot something else
### end of script
Result:
Addition:
Alternatively, similar to Ethan's solution, plotting triangles instead of drawing triangles, but without using a temporary file on disk (but a datablock). The result is identical to the graph above. I haven't tested whether drawing or plotting is faster and/or more efficient if you want to draw/plot thousands of triangles.
Script:
### plot some colored triangles from a datablock
reset session
$Data <<EOD
0 0 2 1 1 2 0xff0000
5 1 3 2 4 4 0x00ff00
3 3 2 5 1 4 0x0000ff
EOD
vx(n,t) = word($Data[n],t*2-1) # vertex x-coordinate
vy(n,t) = word($Data[n],t*2) # vertex y-coordinate
color(n) = word($Data[n],7) # triangle color
set print $Triangles
do for [n=1:|$Data|] {
print sprintf("%s %s %s\n%s %s 0\n%s %s 0\n%s %s 0\n\n", \
vx(n,1),vy(n,1),color(n), vx(n,2),vy(n,2), vx(n,3),vy(n,3), vx(n,1),vy(n,1))
}
set print
set size square
set xrange[0:5]
set yrange[0:5]
set linetype 1 lc rgb "black" lw 3
set style fill solid 0.5
plot $Triangles u 1:2:3 w filledcurves lc rgb var notitle
### end of script

How to plot simple line segments in GNUPlot?

I am trying to draw a rudimentary line segment from (0,0) to (0,1). I already have an input file, but I want to add a line to it.
I have read through Line plot in GnuPlot where line width is a third column in my data file? and Plot line segments from a datafile with gnuplot among many other examples. Everyone is doing something much more complex than what I want, I only want the line segment added to my GNUPlot script.
I normally enter the data in to GNUPlot thus:
$DATA << EOD
.... other data
EOD
$LS << EOL
0 0
0 1
EOL
plot $DATA using 1:2:3 with points
plot $LS with lines
but this doesn't work, nor does
plot $LS using 1:2 with lines
How can I plot this simple line segment from (0,0) to (0,1)?
What does "doesn't work" mean? You don't even show the resulting graph. By the way what do you use the 3rd column for?
Your first example will make a plot only with your data and then a new plot with only the line segment.
And in your second example, the line from 0,0 to 0,1 in your plot is identical with the y-axis and therefore hard to see as long as the xrange starts from 0. You can easily check this, e.g. if you set the color to red or linewidth to 3 , e.g.
plot $LS u 1:2 lc "red" lw 3
You also can make your line segment "visible" if you set xrange[-0.2:]. Check the following example
Code:
### plotting simple line segments
reset session
$DATA << EOD
0.1 0.2 1
0.3 0.4 2
0.5 0.6 3
0.7 0.5 4
EOD
$LS1 << EOL
0 0
0 1
EOL
$LS2 <<EOL
0 0
1 1
EOL
set xrange [-0.2:]
plot $DATA using 1:2:3 with points pt 7, \
$LS1 u 1:2 with lines, \
$LS2 u 1:2 with lines
### end of code
Result:
You can use headless arrows to plot arbitrary line segments.
set xrange [0:1]
set yrange [0:1]
set arrow 1 from 0,0 to 0,1 nohead lw 3 lc 2
set arrow 2 from 0,0 to 1,1 nohead lw 2
plot NaN t''

Plotting with GNU Plot, title based on column name

I have a file composed of 3 columns, which format is: X Axis Value | Title ID | Y axis Value
I donĀ“t know how to plot it using columns 1:3 and 2 for the title name. Here is an example:
X Axis Plot Y Axis
2000 plot1 1.2
2000 plot2 4.6
2000 plot3 5.7
3000 plot1 5.8
3000 plot2 7.5
3000 plot3 8.3
So here, we will have 3 plots which should have second column values on their names (1, 2 and 3); 2000 and 3000 would be the X axis values and the thrid column represents de Y value.
So, the "title-2" graph would be: (2000, 4.6) and (3000, 7.5)
If you are a UNIX user or the "grep" command is callable from gnuplot, you may consider the following approach.
set xrange [1000:4000]
set yrange [0:10]
plot for [i=1:3] \
sprintf("< grep plot%i test.dat",i) using 1:3 with linespoints title sprintf("plot%i", i)
The above plot command is a bit more complicated because of the use of "for loop" and "sprintf", but is equivalent to the following.
plot "< grep plot1 test.dat" using 1:3 with linespoints title "plot1", \
"< grep plot2 test.dat" using 1:3 with linespoints title "plot2", \
"< grep plot3 test.dat" using 1:3 with linespoints title "plot3"
The adapted "gnuplot only" version for your case might look like this.
fcol is the filter column number, myKey your keyword, and dcol the data column number. It's not clear to me whether you want 3 lines in 1 graph, or 3 lines in 3 graphs on 1 canvas (multiplot, like example below), or the graph in 1 file on disk or maybe distributed on 3 files on disk.
Code:
### split data by keyword for each plot
reset session
$Data <<EOD
X Axis Plot Y Axis
2000 plot1 1.2
2000 plot2 4.6
2000 plot3 5.7
3000 plot1 5.8
3000 plot2 7.5
3000 plot3 8.3
EOD
myFilter(fcol,myKey,dcol) = strcol(fcol) eq myKey ? column(dcol) : NaN
set datafile missing NaN
set key top left
set multiplot layout 3,1
do for [i=1:3] {
myKey = sprintf("plot%d",i)
set title myKey
plot $Data u 1:(myFilter(2,myKey,3)) w lp pt 7 lc i title myKey
}
unset multiplot
### end of code
Result:
Addition: (all lines in one plot)
If you have regular file pattern in your rows, e.g. 1,2,3,1,2,3,1,2,3,... or 1,1,1,2,2,2,3,3,3,... you possibly could also work with every, check help every.
However, this filtering with the ternary operator should work for all cases, including random 1,3,2,2,3,1,1,2,3,... sequences.
Code:
### split data by keyword
reset session
$Data <<EOD
X Axis Plot Y Axis
2000 plot1 1.2
2000 plot2 4.6
2000 plot3 5.7
3000 plot1 5.8
3000 plot2 7.5
3000 plot3 8.3
EOD
myFilter(fcol,myKey,dcol) = strcol(fcol) eq myKey ? column(dcol) : NaN
set datafile missing NaN
set key top left
myKey(i) = sprintf("plot%d",i)
set title "Plot 1,2,3"
plot for [i=1:3] $Data u 1:(myFilter(2,myKey(i),3)) w lp pt 7 lc i title myKey(i)
### end of code
Result:

Separate key (legend) for colors and markers

I have a plot with several types of objects (each read from a separate file). I'm plotting the same several functions for all of them, all on the same graph (same X-axis).
I set the markers (pt) explicitly for each, and the color (lc), so the same object has the same marker, but the same function has the same color. As an example we have 2 files, one for each object (| is just to separate the files here):
0 0 0 | 0 1 1
1 1 2 | 1 1 2
Let's call the left file A, the right B. Column 1 in each file is the x axis, column 2 is using 1:2, and column 3 is using 1:3. So using the above files in an interactive session:
gnuplot> plot "A" using 1:2 with lp pt 1 lc 'black'
gnuplot> replot "A" using 1:3 with lp pt 1 lc 'red'
gnuplot> replot "B" using 1:2 with lp pt 2 lc 'black'
gnuplot> replot "B" using 1:3 with lp pt 2 lc 'red'
we get:
Is it possible to have the key separated, so A/B appear next to their respective marker, and the function name ("using...") appears next to a line (or anything) with the appropriate color?
Right now by omitting titles (notitle in the plot command) I can get one or the other, though I would have to settle on some uniform arbitrary marker/color (depending on what I chose to set as key). Can I:
Get two keys somehow? - Preferably setting the missing attribute (color or marker) to something not in the plot.
If not, can I customize a manual legend somehow?
I am not fully sure what you want to achieve, nevertheless as for the splitting of the key, I don't think that Gnuplot has some "out-of-the-box" feature for this. However, you could (ab)use multiplot to achieve this effect. The idea is basically to generate two overlapping plots - one with points and one with lines - and to position the keys independently:
set terminal pngcairo rounded font ",16"
set output 'fig.png'
$A << EOD
0 0 0
1 1 2
EOD
$B << EOD
0 1 1
1 1 2
EOD
set multiplot
set xtics out nomirror
set ytics out nomirror
eps = 0.1
set lmargin at screen eps
set rmargin at screen 1 - eps/2
set bmargin at screen eps
set tmargin at screen 1 - eps/2
#common key settings
set key left top Left reverse spacing 1.5
set key at screen 0.1,screen 1-eps
plot \
$A u 1:2 with p ps 1.5 pt 1 lc 'black' t 'A', \
$A u 1:3 with p ps 1.5 pt 1 lc 'red' t 'A' , \
$B u 1:2 with p ps 1.5 pt 2 lc 'black' t 'B', \
$B u 1:3 with p ps 1.5 pt 2 lc 'red' t 'B'
unset border; unset xtics; unset ytics
set key at screen 0.3,screen 1-eps
plot \
$A u 1:2 with l lc 'black' t 'using 1:2', \
$A u 1:3 with l lc 'red' t 'using 1:3', \
$B u 1:2 with l lc 'black' t '', \
$B u 1:3 with l lc 'red' t ''
This would give you:

Why my commands do not work for gnuplot?

I have input file test.dat that contains
1 1
2 2
3 3
4 4
I wrote the script for gnuplot:
gnuplot <<EOF
set term png size 1000,1000;
set output "out.png";
set arrow from graph 0,1 to graph 0,1.1 filled
set arrow from graph 1,0 to graph 1.1,0 filled
set tmargin 5
set rmargin 20
set border 3
set tics nomirror
set grid
set xtics font "Verdana,14"
set ytics font "Verdana,14"
set nokey
set style line 1 lt 1 lw 3 pt 3 linecolor rgb "black"
set ylabel "Efficiency, %" offset 2,0,0 font "Verdana,14"
set xlabel "Cores, N" offset 0,0,0 font "Verdana,14"
func1(x) = x / 2
func2(x) = x * 2
plot "test.dat" u (func1($1)):(func2($2)) ls 1 smooth csplines;
EOF
But the error occurs when you try to start it:
gnuplot> plot "test.dat" u (func1()):(func2()) ls 1 smooth csplines;
line 0: invalid expression
The dollar signs are interpreted as starting a shell variable. Use column instead:
gnuplot <<EOF
set term png size 1000,1000;
set output "out.png";
func1(x) = x / 2
func2(x) = x * 2
plot "test.dat" u (func1(column(1))):(func2(column(2))) ls 1 smooth csplines;
EOF

Resources