Plotting same line number of several blocks data with gnuplot - 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

Related

plotting single (datum,column) from each block with lines in gnuplot

I have a data file containing constant-size blocks of data. In order to plot element (n,m) from each block I do
pl file u m ev ::n-1::n-1
This works fine, but the graph is displayed in point style since this is default for data. When I add "with lines" to the command above, this produces an empty graph.
Maybe there are shorter solutions, but the first solution which comes to my mind is to plot the data into a datablock and then plot this datablock. This will remove empty lines and hence datapoints will be connected when plotting with lines or with linespoints.
Code:
### plot individual datapoints from each block with lines
reset session
$Data <<EOD
1 11
2 12
3 13
4 14
5 15
6 16
7 17
8 18
9 19
EOD
m = 2
n = 1
set table $DataSelected
plot $Data u m every ::n-1::n-1 w table
unset table
plot $DataSelected u 1 w linespoints pt 7
### end of code
Result:

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

Calculate y from x for a single label

I want to manually add a label in the graph at a certain x position by only entering x and calculate y from the datapoint.
e.g.:
1 set terminal png
2 set output 'test2.png'
3
4 x = 3
5 y = 33
6 set label "test" at x,y
7
8 plot '-' using 1:2 with lines
9 1 11
10 2 22
11 3 33
12 4 22
13 5 33
So, I don't want to hardcode "33" in line 5.
Is that possible?
(I have googled this question and inspected the possible duplicates offered by Stackoverflow after I entered the title. Nada.)
Method 1 (data scan)
For not too-large inputs, one could load the x/y data into two separate arrays and then locate the y-value corresponding to a given x-value:
$DATA <<EOD
1 11
2 22
3 33
4 22
5 33
EOD
stat $DATA nooutput
N = STATS_records
array data_x[N]
array data_y[N]
stat $DATA u (data_x[1+$0]=$1,data_y[1+$0]=$2,$1):2 nooutput
x0 = 3
y0 = NaN
do for [i=1:N] {
if (data_x[i] == x0) {
y0 = data_y[i]
}
}
set label "test" at x0,y0
plot $DATA using 1:2 with lines t ''
The trick here is the second stat command which is used solely in order to populate the arrays data_x, and data_y. The expression (data_x[1+$0]=$1,data_y[1+$0]=$2,$1):2 basically evaluates for each row in the data to 1:2. However, due to the comma operator, it has the side effect of setting the corresponding elements of data_x, and data_y.
Method 2 (fitting)
As an approximate alternative, one might fit a narrow Gaussian centered at x0 = 3 to the input data set. If the characteristic width sigma of this Gaussian is smaller than the characteristic spacing between data points, then the amplitude should match the input y-value:
$DATA <<EOD
1 11
2 22
3 33
4 22
5 33
EOD
x0 = 3
sigma = 0.1
f(x) = a*exp(-(x - x0)**2 / (2*sigma**2))
fit f(x) $DATA using 1:2 via a
print a
y0 = a
set label "test" at x0,y0
plot $DATA using 1:2 with lines t ''
Method 3 (external tool)
As a more robust alternative, one could delegate this task to an external utility invoked in Gnuplot via the system call. The example is using gawk to scan the input data file. If it finds a matching value in the first column, it prints the corresponding y value and exits (so that only the first occurence is reported):
inputFileName = 'data.txt'
x0 = 3
getY(fName, x) = system(sprintf("gawk '$1==%d{print $2;exit}' '%s'", x, fName))
y0 = getY(inputFileName, 3)
set label "test" at x0,y0
plot inputFileName using 1:2 with lines t ''
You say "manually", so maybe interactive placement is an option? A mouse click on the desired location will load variables MOUSE_X and MOUSE_Y, which can then be used to generate a label. There is a demo "mouselabels.dem" in the distribution that automates this and might be informative, but in essence you would do
plot FOO # initial plot with no labels
pause mouse # wait for mouse click
set label 1 "test" at MOUSE_X, MOUSE_Y
replot # same plot with a label at the requested position

How does gnuplot skip irrelevent column in plot?

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

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