I have a data file with 3 column and I want to plot with 2 of them. But I want to use the third with a condition to exclude or not the line from the plot (For example, if $3 < 10 the data line isn't valid). I know there is set datafile missing but this case is somewhat peculiar and I don't know how to do that. Any help is appreciated...
You can use conditional logic in the using expression in the plot command:
plot 'data.dat' u 1:($3 < 10 ? 1/0 : $2)
This command plots 1/0 (it skips that data point) if the value in the third column is < 10, and otherwise plots the value in the second column.
Related
I have a file that looks like this:
0 0.000000
1 0.357625
2 0.424783
3 0.413295
4 0.417723
5 0.343336
6 0.354370
7 0.349152
8 0.619159
9 0.871003
0.415044
The last line is the mean of the N entries listed right above it. What I want to do is to plot a chart that has each point listed and a line with the mean value. I know it involves replot in some way but I can't read the last value separately.
You can make two passes using the stats command to get the necessary data
stats datafile u 1 nooutput
stats datafile u ($0==(STATS_records-1)?$1:1/0) nooutput
The first pass of stats will summarize the data file. What we are actually interested in is the number of records in the file, which will be saved in the variable STATS_records.
The second pass will compute a column to analyze. If the line number (the value of $0) is equal to one less than the number of records (lines are numbered from 0, so this is the last line), than we get this value, otherwise we get an invalid value. This causes the stats command to only look at this last line. Now the value of the last line is stored in STATS_max (or STATS_min and several other variables).
Now we can create the plot using
plot datafile u 1:2, STATS_max
where we explicitly state columns 1 and 2 to make the first plot specification ignore that last line (actually, if we just do plot datafile it should default to this column selection and automatically ignore that last line, but this makes certain). This produces
An alternative way is to use external programs to filter the data. For example, if we have the linux command tail available, we could do1
ave = system("tail -1 datafile")
plot datafile u 1:2, ave+0
Here, ave will contain the last row of the file as a string. In the plot command we add 0 to it to force it to change to a number (otherwise gnuplot will think it is a filename).
Other external programs can be used to read that last line as well. For example, the following call to python3 (using Windows style shell quotes) does the same:
ave = system('python -c "print(open(datafile,\"r\").readlines()[-1])"')
or the following using AWK (again with Windows style shell quotes) has the same result:
ave = system('awk "END{print}"')
or even using Perl (again with Windows shell quotes):
ave = system('perl -lne "END{print $last} $last=$_" datafile')
1 This use of tail uses a now obsolete (according to the GNU manuals) command line option. Using tail -n 1 datafile is the recommended way. However, this shorter way is less to type, and if forward compatibility is not needed (ie you are using this script once), there is no reason not to use it.
Gnuplot ignores those lines with missing data (for example, the last line of your datafile has no column 2). Then, you can simply do the following:
stats datafile using 2 nooutput
plot datafile using 1:2, STATS_mean
The result:
There is no need for using external tools or using stats (unless the value hasn't been calculated already, but in your example it has).
During plotting of the data points you can assign the value of the first column, e.g. to the variable mean.
Since the last row doesn't contain a second column, no datapoint will be plotted, but this last value will be hold in the variable mean.
If you replace reset session with reset and read the data from a file instead of a datablock, this will work with gnuplot 4.6.0 or even earlier versions.
Minimal solution:
plot FILE u (mean=$1):2, mean
Script: (nicer plot and including data for copy & paste & run)
### plot values as points and last value from column 1 as line
reset session
$Data <<EOD
0 0.000000
1 0.357625
2 0.424783
3 0.413295
4 0.417723
5 0.343336
6 0.354370
7 0.349152
8 0.619159
9 0.871003
0.415044
EOD
set key top center
plot $Data u (mean=$1):2 w p pt 7 lc rgb "blue" ti "Data", \
mean w l lw 2 lc rgb "red"
### end of script
Result:
In GNUPLOT, I would like to plot 5 values on a single bar chart, separated with some spacing in between. If I have data formatted as such:
3342336, 3375103, 7110653, 32770, 0
where those 5 values are the y-values, how can I specify the x-values myself for where they should belong?
For example, I would like my bar chart to have each entry be of length 1,
so I plot y-value 3342336 at x-value 1,
y-value 3375103 at x-value 3,
y-value 7110653 at x-value 5,
y-value 32770 at x-value 7,
and y-value 0 at x-value 9.
I would appreciate any example code that can achieve this. Thanks.
If your data is in one row as shown, you can achieve this by using the plot for syntax looping over the column index, and calculating the x value from that index. We can grab the column by using the column function which retrieves the specified column number.
set boxwidth 1
set datafile separator comma # only if data is comma separated
plot for [i=1:5] (2*i-1):(column(i)) with boxes
If we need to ensure the same line type is used each time, we can explicitly state it in the plot command.
plot for [i=1:5] (2*i-1):(column(i)) with boxes lt 1
Additionally, if a key is to be generated, and we don't wish each plot statement to generate one, we can test for and only give a nonempty title on the first iteration (an empty title is treated the same as no title).
plot for [i=1:5] (2*i-1):(column(i)) with boxes lt 1 title (i==1)?"Title":""
If your data is separated into rows as is the normal format, this can be obtained a different way.
Gnuplot has several pseuduocolumns (see help pseudocolumns for details). In your case, column 0 is of interest. Column 0 gives the line number of the data starting at 0. Thus to get sequential odd numbers like that, you can use 2*$0+1.
For example, if your data (stored in datafile.txt) looks like
3342336
3375103
7110653
32770
0
and you wish to plot boxes of length 1 at those values, you can do
set boxwidth 1
plot "datafile.txt" u (2*$0+1):1 with boxes
This question is related to this one:
store commented value from data file in gnuplot
I formatted now every single data file that it looks like:
1.0 0.01
0.2 0.0163 0.0000125
0.4 0.0275 0.0001256
Then I tried to read the first line and store it into variables in this way:
set term push
set term unknown
plot dataFile every ::0::0 using (a=$0):(b=$1)
set term pop
But this is not working as it should, why? The rest of the file I plot as follows:
plot dataFile every ::1 using 1:2:3 with errorbars lt 1 linecolor "red",f(a,b)
Column counting starts at 1, the zeroth column is the row number. And you must also restrict to the first block (note the three colons). Try
plot dataFile every :::0::0 using (a=$1):(b=$2)
Alternatively you can use stats in a similar way:
stats dataFile every :::0::0 using 1:2
a = STATS_min_x
b = STATS_min_y
I have a file with 12 columns. I'd like to plot the data with x axis being my 1st column and y axis being the difference between the 2nd and the 8th columns.
I tried plot "test.dat" using 1:(8-2) but naturally, it is interpreted as 1:6. How can I do this?
You are missing $, just add them and they will allow you to reference the column contents
plot "test.dat" using 1:($8-$2) w linespoints
$1 is a shortcut for column(1) and if the column numbers are stored in variables i and j you must use the column statement to select the respective columns:
i = 8
j = 2
plot "test.dat" using 1:(column(i)-column(j)) w lp
plot "< awk '{print $8 - $2}' test"
I'd like to plot a histogram data already created, stored in hist.dat as:
#hist1
100
1
9
10
30
30
10
9
1
Where the (zeroth line is a comment), first line contains the summation of the y value of the histogram, and x values are 1, 2, ... (the line number). So without normation, I could use
plot "hist.dat" every::1 using 0:1
and with normation I could use
plot "hist.dat" every::1 using 0:($1/100)
The question is how can I refer the summated value (100)? Because I don't want to pre-read the file just to create a correct gnuplot code, so I dont't want to write down the value implicit. I already tried
plot "hist.dat" using 0:($1/(columnhead+0))
but columnhead cannot called within using (it is a string, that's why I tried to add 0 to make it int).
I don't want to modify the file or create a new one based on this one, I want to just use the appropriate gnuplot command. I would like to avoid neglecting the summated value and recalculating it again with gnuplot.
Solution: according to andyras who give the correct answer, a bit improved method is
first(x) = ($0 == 0) ? (first = column(x), 1/0) : first
plot "hist.dat" using 0:($1/first(1))
So you can use this to plot histograms if you have multiple columns as if the hist.dat were
#hist1 hist2
10000 8000
1000 50
9000 70
1000 1100
3000 4500
3000 1200
1000 700
9000 380
1000
How can I refer the summated value (100)? (without pre-reading the file)
Yes, using a gnuplot function:
first(x) = ($0 == 0) ? (first = $1, 1/0) : first
plot "hist.dat" using 0:($1/first($1))
If it is reading the first line, the function assigns the value from that line to the variable first and returns 1/0 (gnuplot treats it as missing data and won't extend the x range to include that point). Otherwise the function returns the value of first.
This way you don't even have to use every ::1.
If you didn't mind rereading the file you could use the stats command to find out the largest value in the file.