How does gnuplot skip irrelevent column in plot? - gnuplot

I have a data file like this
# Time A irrelevent_col B
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
I am trying to plot two lines Time vs A, Time vs B with labels "A" and "B". How can I skip the "irrelevent_col" column?
I did the following, but the code still plots the "irrelevent_col" column. Shouldn't the ? : operator gets ride of that column?
set datafile commentschars "!!!"
plot for [i=2:4] filename using 1:(columnhead(i+1) ne "irrelevent_col" ? column(i) : 1/0) title columnhead(i+1)
Thanks!

If I understood correctly your question:
plot "filename" using 1:2 title "A" with lines,\
"filename" using 1:4 title "B" with lines

Let me repeat what I've understood from your question:
You have a large number of columns and you want to plot them all in a loop, but exclude a single column (or a few) by name.
Of course, you can specify all columns you do want to plot, like in #ViniciusPlacco's answer, however, as I understand that's what you wanted to avoid, since you have many more columns in your real data. You can also always use external tools to pre-process your data, but here I would like to suggest a gnuplot-only and hence platform-independent solution.
Why your solution is not working, I can only speculate: I guess using columnheader twice in a plot iteration creates problems (at least for gnuplot<=5.2). But I could be wrong. But as I will show below, your solution will work for gnuplot>=5.4.0.
Furthermore, you want to specify the columns by header not by column number.
In addition, your header line starts with the comment char '#', but you can easily change that to access the columnheader information.
In the example below you can specify a list of several headers which you don't want to plot. Maybe the script(s) can be further simplified.
Script: (works for gnuplot>=5.4.0, July 2020)
### exclude some columns by header from plotting loop (gnuplot>=5.4.0)
reset session
$Data <<EOD
# Time A B C D E
1 2 3 4 5 6
2 3 4 5 6 7
3 4 5 6 7 8
4 5 6 7 8 9
EOD
set datafile commentschars '' # no commentchar
set key top left noenhanced noautotitle
inList(w,list) = int(sum[_i=1:words(list)] w eq word(list,_i))
doNotPlot = 'B C'
color = 1
plot for [col=2:6] $Data u 1:((b=inList(myHeader=columnhead(col+1),doNotPlot)) ? \
NaN : ($0==1?color=color+1:0, column(col))) w lp pt 7 lc color ti (b ? '' : myHeader)
### end of script
Result:
For older gnuplot versions <5.4.0 you need a different approach:
get all headers into a string
specify all your headers of the columns you don't want to plot in a string
for gnuplot>=5.0.0, subtract two lists and keep the column numbers for the header you do want to plot
Script: (works for gnuplot>=5.2.2, Nov. 2017; result same as graph above)
### exclude some columns by header from plotting loop (gnuplot>=5.2.2)
reset session
$Data <<EOD
# Time A B C D E
1 2 3 4 5 6
2 3 4 5 6 7
3 4 5 6 7 8
4 5 6 7 8 9
EOD
set datafile commentschars '' # no commentchar
set key top left noenhanced noautotitle
inList(w,list) = int(sum[_i=1:words(list)] w eq word(list,_i))
doNotPlot = 'B C'
myHeaders = ''
color = 1
plot for [col=2:6] $Data u 1:((b=inList(myHeader=columnhead(col+1),doNotPlot)) ? NaN : \
($0==1 ? (color=color+1, myHeaders=myHeaders.' '.myHeader) : 0, column(col))) w lp pt 7 lc color, \
for [i=1:color] NaN w lp pt 7 lc i ti word(myHeaders,i)
### end of script
Script: (works for gnuplot>=5.0.0, Jan. 2015; result same as graph above)
### exclude some columns by header from plotting loop (gnuplot>=5.0.0)
reset session
$Data <<EOD
# Time A B C D E
1 2 3 4 5 6
2 3 4 5 6 7
3 4 5 6 7 8
4 5 6 7 8 9
EOD
set datafile commentschars '' # no commentchar
set datafile separator "\n" # or another character which is not in the header line
stats $Data u (allHeaders = strcol(1)[2:]) ever ::::0 nooutput # get header line into string
set datafile commentschar # reset to default
set datafile separator whitespace # ditto
inList(w,list) = int(sum[_i=1:words(list)] w eq word(list,_i))
subtractLists(list1,list2) = (_s=' ', sum[_j=1:words(list1)] (_s0=word(list1,_j), \
inList(_s0,list2) ? 0 : (_s=_s._s0.' ', \
myColNos=myColNos.' '._j), 0), _s)
doNotPlot = 'B C'
myColNos = ''
myHeaders = subtractLists(allHeaders,doNotPlot)
myColNo(i) = column((word(myColNos,i)))
set key top left noenhanced noautotitle
plot for [i=2:words(myHeaders)] $Data u 1:(myColNo(i)) w lp pt 7 ti word(myHeaders,i)
### end of script

Related

How to plot points specified by ID column only with linespoints and multiple plots using gnuplot?

Say I have two files, each has 3 columns
file1:
ID X Y
10 0.1 some data as X
20 0.2
30 0.3
... ...
120 0.5
file2:
ID X Y
15 0.1 some data as X
30 0.2
45 0.3
60 0.4
... ...
120 0.6
I am doing
plot \
"file1" using 2:3 w linespoints lt 1 dt 1 lw 1 lc 1 title "file1",\
"file2" using 2:3 w linespoints lt 1 dt 1 lw 1 lc 2 title "file2"
which shows every point on the file.
If I only want points which its Row ID(first column) is 30, 60 ,90 ,120
How should I do? Thank you.
*In the actually case, I need to plot 12 file in one plot and each of them have 10000 rows but I only want to show 6 points.
You can filter your data with the ternary operator. Check help ternary.
For the filename and the filter I would define a function such that you have it compact in your plot command.
What myFilter(dcol,fcol) does is returning the value of the data column dcol if the filter column fcol is equal to one of the given values.
myFilename(n) creates the filename as a function of a number.
I don't have test files but the following should plot the 12 files names "file1.dat", ..., "file12.dat".
I hope you can adapt it to your exact needs.
Code:
### filter data with ternary operator
reset session
myFilename(n) = sprintf("file%d.dat",n)
myFilter(dcol,fcol) = column(fcol)==30 || column(fcol)==60 || \
column(fcol)==90 || column(fcol)==120 ? column(dcol) : NaN
set datafile missing NaN
plot for [i=1:12] myFileName(i) u 2:(myFilter(3,1)) w lp ti myFilename(i)
### end of code

categorising points by using of gnuplot

I am going to plot a file containing 4 columns. first and second column are x and y respectively. I want to categorize these point based on the third and fourth column. In fact, the third column should display the color (red or blue) of point and the fourth column should determine its type (square or circle ). how could I reach to this goal by gnu-plot?
I should mention that I tried this, by it does not work!
set style line 1 lc rgb 'red' pt 7
set style line 2 lc rgb 'red' pt 7
set style line 3 lc rgb 'blue' pt 9
set style line 4 lc rgb 'blue' pt 9
plot 'data' w ($3= 1 && $4= 1) ? p ls 1 \
: ($3= 1 && $4= 2) ? p ls 2 \
: ($3= 2 && $4= 1) ? p ls 3 \
: ($3= 2 && $4= 2) ? p ls 4
Please check help points. From the manual:
plot DATA using x:y:pointsize:pointtype:color \
with points lc variable pt variable ps variable
You don't show sample data. If you can adjust your data, the easiest would be the following below.
If you want to set the color by name in your file, check this.
Code:
### variable pointtype and color
reset session
$Data <<EOD
1 2 5 0xff0000
3 4 7 0xff0000
5 6 5 0x0000ff
7 8 7 0x0000ff
EOD
plot $Data u 1:2:3:4 w p ps 5 pt var lc rgb var
### end of code
Result:

Plotting same line number of several blocks data with gnuplot

I have a data file with the following structure
block1: line 1
line 2
line 3
.....
block2: line 1
line 2
line 3
......
block3: .....
To plot only the block2, I use the command
plot 'file' u x1:x2 every :::2::2 w l
How to gather only line 1 of each block on the plot command?
my guess would be, because the datapoints are from different blocks they are separated by an empty line. And datapoints separated by an empty line are not plotted connected using "with lines".
Try the following: write your desired data into a new table, like the example below (gnuplot 5.2.5).
### plot values of different blocks connected with lines
reset session
set colorsequence classic
$Data <<EOD
# block line xvalue yvalue
0 0 1 0
0 1 2 1
0 2 3 2
0 3 4 3
1 0 5 10
1 1 6 11
1 2 7 12
1 3 8 13
2 0 9 20
2 1 10 21
2 2 11 22
2 3 12 23
EOD
set table $Data2
plot $Data u 0:3:4 every ::0::0 with table
unset table
print $Data2
plot $Data u 3:4 w lp,\
$Data2 u 2:3 w lp
### end code
addition: if you want to do this with several files try the following below
(little drawback so far: points from different files are not connected)
### plot every Nth line of all blocks of several systematic files
reset session
FileCount = 2 # number of files
Col1 = 1 # e.g. column of x value
Col2 = 2 # e.g. column of y value
N = 0 # N=0 is first line of each datablock, N=1 second line, etc...
set print $EveryNthLineFromAllBlocksOfAllFiles
do for [i=1:FileCount] {
FILE = sprintf("name_%d.dat",i)
set table $EveryNthLine
plot FILE u Col1:Col2 every ::N::N with table
unset table
print $EveryNthLine
}
set print
print $EveryNthLineFromAllBlocksOfAllFiles
plot $EveryNthLineFromAllBlocksOfAllFiles u 1:2 w lp
### end code

Gnuplot: plotting points with variable point types

I have x,y values for points in the first 2 colums and a number that indicates the point type (symbol) in the 3. column, in one data file. How do I plot data points with different symbols?
Unfortunately, there isn't a way (AFAIK) to automatically set the point of the plot from a column value using vanilla GNUPLOT.
However, there is a way to get around that by setting a linestyle for each data series, and then plotting the values based on that defined style:
set style line 1 lc rgb 'red' pt 7 #Circle
set style line 2 lc rgb 'blue' pt 5 #Square
Remember that the number after pt is the point-type.
Then, all you have to do is plot (assuming that the data in "data.txt" is ordered ColX ColY Col3):
plot "data.txt" using 1:2 title 'Y Axis' with points ls 1, \
"data.txt" using 1:3 title 'Y Axis' with points ls 2
Try it here using this data (in the section titled "Data" - also note that column 3 "Symbol" is noted used, it's mainly there for illustrative purposes):
# This file is called force.dat
# Force-Deflection data for a beam and a bar
# Deflection Col-Force Symbol
0.000 0 5
0.001 104 5
0.002 202 7
0.003 298 7
And in the Plot Script Heading:
set key inside bottom right
set xlabel 'Deflection (m)'
set ylabel 'Force (kN)'
set title 'Some Data'
set style line 1 lc rgb 'red' pt 7
set style line 2 lc rgb 'blue' pt 5
plot "data.txt" using 1:2 title 'Col-Force' with points ls 1, \
"data.txt" using 1:3 title 'Beam-Force' with points ls 2
The one caveat is of course that you have have to reconfigure your data input source.
REFERENCES:
http://www.gnuplotting.org/plotting-single-points/
http://www.gnuplotting.org/plotting-data/
Here is a possible solution (which is a simple extrapolation from gnuplot conditional plotting with if), that works as long as you don't have tens of different symbols to handle.
Suppose I want to plot 2D points in a coordinate system. I have only two symbols, that I arbitrarily represented with a 0 and a 1 in the last column of my data file :
0 -0.29450470209121704 1.2279523611068726 1
1 -0.4006965458393097 1.0025811195373535 0
2 -0.7109975814819336 0.9022682905197144 1
3 -0.8540692329406738 1.0190201997756958 1
4 -0.5559651851654053 0.7677079439163208 0
5 -1.1831613779067993 1.5692367553710938 0
6 -0.24254602193832397 0.8055955171585083 0
7 -0.3412654995918274 0.6301406025886536 0
8 -0.25005266070365906 0.7788659334182739 1
9 -0.16853423416614532 0.09659398347139359 1
10 0.169997438788414 0.3473801910877228 0
11 -0.5252010226249695 -0.1398928463459015 0
12 -0.17566296458244324 0.09505800902843475 1
To achieve what I want, I just plot my file using conditionals. Using an undefined value like 1/0 results in no plotting of the given point:
# Set styles
REG_PTS = 'pointtype 7 pointsize 1.5 linecolor rgb "purple"'
NET_PTS = 'pointtype 4 pointsize 1.5 linecolor rgb "blue"'
set grid
# Plot each category with its own style
plot "data_file" u 2:($4 == 0 ? $3 : 1/0) title "regular" #REG_PTS, \
"data_file" u 2:($4 == 1 ? $3 : 1/0) title "network" #NET_PTS
Here is the result :
Hope this helps
Variable pointype (pt variable) was introduced (I guess) not until gnuplot 5.2.0 (Sept 2017) (check help points).
Just in retrospective, another (awkward) solution would be the following for those who are still using such early versions.
Data:
1 1.0 4 # empty square
2 2.0 5 # filled square
3 3.0 6 # empty circle
4 4.0 7 # filled circle
5 5.0 8 # empty triangle up
6 6.0 9 # filled triangle down
7 7.0 15 # filled pentagon (cross in gnuplot 4.6 to 5.0)
Script: (works from gnuplot>=4.6.0, March 2012; but not necessary since 5.2.0)
### variable pointtype for gnuplot>=4.6
reset
FILE = 'SO23707979.dat'
set key noautotitle
set offsets 1,1,1,1
set pointsize 4
stats FILE u 0 nooutput
N = STATS_records # get the number of rows
p0=x1=y1=NaN
plot for [n=0:N-1 ] FILE u (x0=x1, x1=$1, x0):(y0=y1, y1=$2, y0):(p0=$3) \
every ::n::n w p pt p0 lc rgb "red", \
FILE u 1:2 every ::N-1::N-1 w p pt p0 lc rgb "red"
### end of script
Result:

Plot cyclic sum of some row data

I have a data file that store for a given timestamp k values.
Ex:
# data.dat
# Example for k = 3
# Time ID value
1 0 1.555
1 1 1.76
1 2 12.56
2 0 1.75
2 1 2.04
2 2 13.04
3 0 2.01
3 1 0.52
3 2 12.99
# ...
I can print individually the data of each ID versus the time as follows:
set xrange [0:4]
set yrange[0:14]
set xtics 1
plot "data.dat" every 3 using 1:3 title "ID=0" with lp, \
"" every 3::1 using 1:3 title "ID=1" with lp, \
"" every 3::2 using 1:3 title "ID=2" with lp
Yet I'm interested to plot the average sum of the 3 values vs time.
Of course, I could regenerate a new data file containing (with evaluated sum):
# avg_data.dat modified to
# Example for k = 3
# Time ID value
1 (1.555+1.76+12.56)/3
2 (1.75+2.04+13.04)/3
3 (2.01+0.52+12.99)/3
# ...
But of course, I'm seeking an automated way do express that in gnuplot using the data.dat file directly...
Drawing some inspiration from the running average demo on the gnuplot site:
k = 3
back1 = back2 = back3 = 0
shifter(x) = (back3 = back2, back2 = back1, back1 = x)
avger(x,y) = (shifter(x), y == k - 1 ? (back1 + back2 + back3)/3 : 1/0)
plot 'data.dat' u 1:(avger($3, $2)) with points pt 7
This works for me in gnuplot 4.6.1. If you want to have the points at each timestep connected in a line, it may be better to preprocess the data, since gnuplot in general won't connect points resulting from an expression evaluation (see discussion here and here, and in the gnuplot docs for set datafile missing).

Resources