How can I do this in gnuplot:
plot "test.csv" using 1:2 if value_in_column_3 == 80.0
It should only select those rows where column 3 == 80.0 and ignore all other rows (It should not plot a 0 for the other rows, simply ignore them)
Thanks in advance.
Consider the following dataset (1.dat),
1 0.8 0
2 0.6 0
3 0.9 1
4 1.1 0
5 0.7 0
6 0.6 1
where we want to plot the first two columns only when the third one equals zero. Then you can try this:
plot '1.dat' using 1:($3==0?$2:1/0)
(Credit to markjoe on Gnuplot mailing-list.)
Case where one wants to plot conditionally on another column containing text:
data
1 0.8 a
2 0.6 a
3 0.9 a
1 2.1 b
2 1.7 b
3 1.6 b
code
set terminal postscript color
set xrange [0:4]
set yrange [0:3]
plot "1.dat" using 1:(stringcolumn(3) eq "a"? $2:1/0) title "a" lc rgb "blue" ,\
"" using 1:(stringcolumn(3) eq "b"? $2:1/0) title "b" lc rgb "red"
command
gnuplot < 1.par > 1.ps
As chl says above, the only way to do this in gnuplot is rather hacky: you have to use gnuplot's terniary ?: operator to generate a numerical error on the points you want to filter out of your dataset.
I may be biased here as I'm an author on the project, but you may want to have a look at Pyxplot http://www.pyxplot.org.uk (also free and open source), written by a group of gnuplot users who were a bit fed up with hacky syntax like this.
Its syntax is very similar to gnuplot, but with extensions. For what you want, you can specify a "select criterion" in the plot command, and points are only included if it tests True. See http://pyxplot.org.uk/current/doc/html/sec-select_modifier.html for more information.
Another hack would be to use a shell command like awk:
plot "< awk '$3==80.0 { print $1, $2 }' test.csv" using 1:2
If you are calling a script, use column(2) instead of $2
plot "1.dat" using 1:(stringcolumn(3) eq "a"? column(2):1/0) title "a" lc rgb "blue" ,\
"" using 1:(stringcolumn(3) eq "b"? column(2):1/0) title "b" lc rgb "red"
Related
I'm working on a temperature graph and would like to put the last data point in the title. I can use column(2) to kind of do this but I'd like to add some descriptive text as well. I'm trying the code below to concatentate some text with the data value but getting this error: line 0: f_sprintf: attempt to print numeric value with string format
plot "/tmp/data.txt" using 1:2 with lines ls 2 title sprintf('Current :%sF', column(2))
I've tried changing the sprintf modifer to %d along with various flavors of concatenation with the dot character and haven't found the right combination.
Most probably there are various solutions. The first possibility which comes to my mind (I guess requiring gnuplot >5.2) is using keyentry, check help keyentry. While plotting you are asigning column 2 to a variable. After plotting, this variable holds the last value of column 2, which you use later in keyentry, which is a keyentry without plotting anything. There would also be workarounds for older gnuplot versions.
Code:
### last value into key
reset session
$Data <<EOD
1 7.1
2 6.2
3 5.3
4 4.4
5 3.5
6 2.6
7 1.7
8 0.8
EOD
plot $Data u 1:(a=$2) w lp pt 7 lc 1 notitle, \
keyentry w lp pt 7 lc 1 ti sprintf("Last y value: %g",a)
### end of code
Result:
The problem here is that the title string is evaluated by gnuplot before the data is parsed and plot is performed.
A trick is to store the last value of temperature, and plot it afterwards.
T=0
plot "/tmp/data.txt" using 1:(T=column(2)) w l ls 2 notitle, \
1/0 w l ls 2 title sprintf('Current: %.1fF', T)
I would like to draw a line with plots that contain "jumping" values.
Here is an example: when we have plots of sin(x) for several cycles and plot it, unrealistic line will appear that go across from right to left (as shown in following figure).
One idea to avoid this might be using with linespoints (link), but I want to draw it without revising the original data file.
Do we have simple and robust solution for this problem?
Assuming that you are plotting a function, that is, for each x value there exists one and only one corresponding y value, the easiest way to achieve what you want is to use the smooth unique option. This smoothing routine will make the data monotonic in x, then plot it. When several y values exist for the same x value, the average will be used.
Example:
Data file:
0.5 0.5
1.0 1.5
1.5 0.5
0.5 0.5
Plotting without smoothing:
set xrange [0:2]
set yrange [0:2]
plot "data" w l
With smoothing:
plot "data" smooth unique
Edit: points are lost if this solution is used, so I suggest to improve my answer.
Here can be applied "conditional plotting". Suppose we have a file like this:
1 2
2 5
3 3
1 2
2 5
3 3
i.e. there is a backline between 3rd and 4th point.
plot "tmp.dat" u 1:2
Find minimum x value:
stats "tmp.dat" u 1:2
prev=STATS_min_x
Or find first x value:
prev=system("awk 'FNR == 1 {print $1}' tmp.dat")
Plot the line if current x value is greater than previous, or don't plot if it's less:
plot "tmp.dat" u ($0==0? prev:($1>prev? $1:1/0), prev=$1):2 w l
OK, it's not impossible, but the following is a ghastly hack. I really advise you add an empty line in your dataset at the breaks.
$dat << EOD
1 1
2 2
3 3
1 5
2 6
3 7
1 8
2 9
3 10
EOD
plot for [i=0:3] $dat us \
($0==0?j=0:j=j,llx=lx,lx=$1,llx>lx?j=j+1:j=j,i==j?$1:NaN):2 w lp notit
This plots your dataset three times (acually four, there is a small error in there. I guess i have to initialise all variables), counts how often the abscissa values "jump", and only plots datapoints if this counter j is equal to the plot counter i.
Check the help on the serial evaluation operator "a, b" and the ternary operator "a?b:c"
If you have data in a repetitive x-range where the corresponding y-values do not change, then #Miguel's smooth unique solution is certainly the easiest.
In a more general case, what if the x-range is repetitive but y-values are changing, e.g. like a noisy sin(x)?
Then compare two consecutive x-values x0 and x1, if x0>x1 then you have a "jump" and make the linecolor fully transparent, i.e. invisible, e.g. 0xff123456 (scheme 0xaarrggbb, check help colorspec). The same "trick" can be used when you want to interrupt a dataline which has a certain forward "jump" (see https://stackoverflow.com/a/72535613/7295599).
Minimal solution:
plot x1=NaN $Data u 1:2:(x0=x1,x1=$1,x0>x1?0xff123456:0x0000ff) w l lc rgb var
Script:
### plot "folded" data without connecting lines
reset session
# create some test data
set table $Data
plot [0:2*pi] for [i=1:4] '+' u 1:(sin(x)+rand(0)*0.5) w table
unset table
set xrange[0:2*pi]
set key noautotitle
set multiplot layout 1,2
plot $Data u 1:2 w l lc "red" ti "data as is"
plot x1=NaN $Data u 1:2:(x0=x1,x1=$1,x0>x1?0xff123456:0x0000ff) \
w l lc rgb var ti "\n\n\"Jumps\" removed\nwithout changing\ninput data"
unset multiplot
### end of script
Result:
I am using
G N U P L O T
Version 4.6 patchlevel 4 last modified 2013-10-02
Build System: Linux x86_64
which I want to use to plot data from a file that is roughly set up like this
0.0 a1 b1
0.0 a2 b2
...
0.1 a1 b1*
0.1 a2 b2*
...
for each unique value in the first column I want to plot b over a. To do this I have created a do loop which contains conditional plotting
do for [t=0:34] {
print 0.2000*t
plot 'twopi5101/profile.dat' u ($1==0.2000*t ? ($3-7.5) : 1/0):8 notitle w l lt 1 lc 1, \
'twopi5101/profile.dat' u ($1==0.2000*t ? ($3-7.5) : 1/0):9 notitle w l lt 1 lc 2
}
unfortunately this loop (and similar loops for other files) will consistently miss some plots
0.0
0.2
0.4
0.6
warning: Skipping data file with no valid points
warning: Skipping data file with no valid points
more> ;print 0.2000*t;plot 'twopi5101/profile.dat' u ($1==0.2000*t ? ($3-7.5) : 1/0):8 notitle w l lt 1 lc 1, 'twopi5101/profile.dat' u ($1==0.2000*t ? ($3-7.5) : 1/0):9 notitle w l lt 1 lc 2;
^
x range is invalid
however, if I manually input the 0.6 there is no problem at all
gnuplot> plot 'twopi5101/profile.dat' u ($1==0.6 ? ($3-7.5) : 1/0):8 notitle w l lt 1 lc 1, \
'twopi5101/profile.dat' u ($1==0.6 ? ($3-7.5) : 1/0):9 notitle w l lt 1 lc 2
gnuplot>
There seems to be no logical explanation for why this should happen, or even a pattern for points missed.
of the interval [0.0:6.0] gnuplot skipped:
0.6,1.2,1.4,2.4,2.8,3.4,3.8,4.6,4.8,5.6,5.8
and it does so consistently every time I run the loop, even if I run it over just part of that interval (e.g. running from 0.6 to 2.0 will again skil 0.6,1.2 and 1.4).
I've run into the same behavior in a number of other cases for larger intervals/more plots. I have no idea what would even cause something like this or if there is some error in my formatting of the loop to explain it.
(terminals I use are either 'wxt' or postscript enhanced)
That's because testing floating point values on equality is generally not a good idea. Let's consider for example:
gnuplot> print 0.6==0.6
1
gnuplot> print 0.6==3*0.2
0
This is a consequence of the fact that numbers like 0.2 are not represented exactly.
I would suggest to first convert the first column in your data to an integer value by, e.g.,
floor(($1 + 0.05)*10)
Here it is assumed that the column in question contains only multiples of 0.1. The factor 0.05 is present to ensure that possible inaccurate input such as or example 0.1000001 or 0.0999999 gets converted to 1.
This converted value can be then used in the filtering within the plot command, e.g.,
plot 'twopi5101/profile.dat' u (floor(($1+0.05)*10)==2*t?($3-7.5):1/0):8
Alternatively, one could replace the condition $1==0.2000*t with something like abs($1 - 0.2000*t)<5E-2
I am plotting a histogram rowstacked very similar to this graph (the last one on this page) :
What I would like to do is to have different colors for each year bin. This colors would repeat from a newhistogram to another. I have not yet found a way to do this.
An example with my data of what I am trying to accomplish is
Thank you for your help.
So what is your actual problem with this? Using the histograms plotting should work fine. Consider the following data file
A -1 1 -0.5 0.5
B -2 2 -1 1
C -3 3 -1.5 1.5
D -4 4 -2 2
E -5 5 -2.5 2.5
F -4 4 -2 2
G -3 3 -1.5 1.5
which you can plot with
set key tmargin horizontal
set style fill solid noborder
set style data histograms
set style histogram gap 1
plot 'data.dat' using 2:xtic(1) title "First",\
'' using 4 title "Second",\
newhistogram at 0,\
'' using 3 title "Third",\
'' using 5 title "Fourth"
The result is
Here, I explicitely assume, that in one column you have only negative or only positive values. But that isn't necessary in general. All further fine-tuning depends on your actual data file format, and other, unknown, conditions.
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