How to make a spider plot in gnuplot? - gnuplot

Let's say my data is in the form:
#atom a b c
43 1.2 1.3 1.4
44 1.2 1.4 1.8
45 1.3 1.8 1.9
46 2.0 2.3 2.4
47 1.5 1.6 1.8
And I want a plot like this one http://www.r-graph-gallery.com/143-spider-chart-with-saveral-individuals/ (the one in the middle).
how can I do that?
ps. The title in here (How to Create a Spider Plot in Gnuplot?) is misleading...

As far as I know, there is no built-in functionality which would directly give you the linked output. Nevertheless, one could improvise with the tools that Gnuplot does provide. The strategy would be to:
analyze the file and determine the number of vertices
generate the "polygonial" grid in parametric mode
plot the data using the filledcurves plotting style (with transparency)
For example (the data is represented as a datablock instead of directly passing a file):
reset session
set terminal pngcairo enhanced font "Times,16"
set output 'plot.png'
$DATA << EOD
#atom a b c
43 1.2 1.3 1.4
44 1.2 1.4 1.8
45 1.3 1.8 1.9
46 2.0 2.3 2.4
47 1.5 1.6 1.8
EOD
stats $DATA nooutput
N = STATS_columns
M = STATS_records
set angles degrees
set size ratio -1
set style fill transparent solid 0.25
unset key
unset border
unset xtics
unset ytics
colors = "dark-red royalblue forest-green"
set style line 42 lt 1 lc rgb '#333333' dt 3 lw 0.8
deltaR = 0.5
maxR = 3 + deltaR/4
numOfStepsInR = floor((1.*maxR) / deltaR)
#helper functions
alpha(i) = 90. - i*360./M
posX(i, r) = cos(alpha(i))*r
posY(i, r) = sin(alpha(i))*r
lcolor(i) = word(colors, i%words(colors) + 1)
do for [i=0:M-1] {
stats $DATA every ::i::i using (labelValue=$1) nooutput
set label sprintf("%d", labelValue) at posX(i,maxR),posY(i,maxR) center offset char posX(i,1),char posY(i,1)
}
do for [j=1:numOfStepsInR] {
set label sprintf("%.1f", j*deltaR) at 0,j*deltaR left offset char 0.5,0 tc rgb '#333333'
}
set parametric
set tr [0:1]
set xr [-1.1*maxR:1.1*maxR]
set yr [-1.1*maxR:1.1*maxR]
plot \
for [i=0:M-1] \
(cos(alpha(i))*(deltaR*(1-t)+t*maxR)),(sin(alpha(i))*(deltaR*(1-t)+t*maxR)) w l ls 42, \
for [i=0:M-1] for [j=1:numOfStepsInR] \
(j*deltaR*cos(alpha(i))*t + (1-t)*j*deltaR*cos(alpha(i+1))),(j*deltaR*sin(alpha(i))*t + (1-t)*j*deltaR*sin(alpha(i+1))) w l ls 42, \
for [i=2:N] $DATA u (posX($0, column(i))):(posY($0, column(i))) w filledcurves closed fc rgb lcolor(i-2) fs border lc rgb lcolor(i-2) lw 2, \
for [i=2:N] $DATA u (posX($0, column(i))):(posY($0, column(i))) w p ps 1.2 pt 7 lc rgb lcolor(i-2)
This produces:

Related

Handling out-of-range values with GNUPlot's splot

I use the splot commadn to produce a heat map of the earth. The x- and y-values represent lattitude and longitude of a specific point on the Earth's surface, while the related z-value is the outcome of an analysis. The zrange is between 0 and 60. However, for some locations on Earth, there is no result available (which is correct) and z is set to 9999 for these cases.
I'm using the following script to produce the heat map:
set terminal png large size 1600,\
1200 font arial 24 crop
set output "map.png"
set palette model RGB defined (0 "dark-green",1 "forest-green",2 "green",3 "light-green",4 "dark-yellow",5 "yellow",6 "red",7 "dark-red")
set xrange[-180.00: 180.00]
set yrange[ -90.00: 90.00]
set zrange[ *: 60]
set grid
set pm3d map
set xlabel "Longitude [deg]"
set ylabel "Latitude [deg]"
unset key
set cblabel "Time [h]"
splot "output\\map.dat" u 5:6:8,\
"input\\world.dat" u 1:2:( .00) w l lw 1 lt -1
It works fine but because of the limitation in zrange, regions with z > 60 are shown in white.
I want to have something like a condition which enables that all 9999 z-values are shown in a specific colour like purple with a declaration like "no result" in the legend.
Any idea how to achieve this?
Thanks in advance,
Florian
Not exactly sure how to modify the style for the selected points, but you can use the ternary operator not to draw them at all. Something like:
splot "output\\map.dat" u 5:6:(($8<=60)?($8):(1/0))
You basically want to have 3 "ranges" of colors:
0 to 60 your defined palette colors
>60 "out of range" color
=9999 "no data" color
Not sure if splot ... w pm3d will allow an easy "independent" setting for z and color.
Furthermore, if you have NxN datapoints you will get (N-1)x(N-1) quadrangles and the color is determined by the z-values of the involved vertices (check help corners2color) and http://gnuplot.sourceforge.net/demo_5.5/pm3d.html (the very last graph). Maybe there is an easy way which I am not aware of.
That's why I would perfer the plotting style with boxxyerror (check help boxxyerror), maybe this is not the intended way, but it is rather flexible. If you are running gnuplt 5.4 you have the function palette() (check help palette).
I would take for missing data (backgroundcolor here:white) and for data out of range "grey", but you can easily change it. You can skip the random data generation part and in the plot command replace $Data with your filename and the corresponding columns. As well, replace 180./N and 90./N with the width (delta longitude) and height (delta latitude) of one data element.
Script: (requires gnuplot>=5.4)
### define separate color for missing values
reset session
set xrange[-180:180]
set yrange[-90:90]
# create some "random" test data
N = 90
set samples N
set isosamples N
set table $Data
c = 0.05
x0 = 70 # (rand(0)*360-180) # or random
y0 = -50 # (rand(0)*180-90) #
size0 = 2
x1 = -150 # (rand(0)*360-180) # or random
y1 = -20 # (rand(0)*180-90) #
size1 = 1
holeP0(x,y) = (1-erf((x-x0)*c/size0)**2) * (1-erf((y-y0)*c/size0)**2)
holeP1(x,y) = (1-erf((x-x1)*c/size1)**2) * (1-erf((y-y1)*c/size1)**2)
f(x,y) = rand(0)<holeP0(x,y) || rand(0)<holeP1(x,y) ? 9999 : (sin(1.3*x*c)*cos(.9*y*c)+cos(.8*x*c)*sin(1.9*y*c)+cos(y*.2*x*c**2))*11.5+33
splot f(x,y)
unset table
set palette model RGB defined (0 "dark-green",1 "forest-green",2 "green",3 "light-green",4 "dark-yellow",5 "yellow",6 "red",7 "dark-red")
myZmin = 0
myZmax = 60
myColorNoData = 0xffffff
myColorOutOfRange = 0x999999
set rmargin screen 0.8
set colorbox user origin screen 0.85,graph 0.2 size graph 0.05,graph 0.8
set cblabel "Amplitude"
set cbrange [myZmin:myZmax]
set tics out
set style fill solid 1.0 border
set key noautotitle at graph 1.27, graph 0.15 reverse Left samplen 2
myColor(col) = (z=column(col), z==9999 ? myColorNoData : z>myZmax ? myColorOutOfRange : palette(z))
plot $Data u 1:2:(180./N):(90./N):(myColor(3)) w boxxy lc rgb var, \
"world.dat" u 1:2:(0) w l lc "black", \
NaN w l lc palette, \
keyentry w boxes lc rgb 0x000000 fill empty ti "no data", \
keyentry w boxes lc rgb myColorOutOfRange ti "\ndata out\nof range"
### end of script
Result:

Set color to grey for points below some cutoff when plotting with palette in Gnuplot

Sorry for the long and probably poor title.
I am trying to plot some data in gnuplot, where the data file has the format
x y z
1.0 1.5 0.1
1.3 1.8 0.7
2.1 3.7 1.1
3.1 4.3 1.5
3.7 4.7 1.8
I want to plot y vs. x and, for each point, indicate the value of z by the color of the point. Currently I use the following code for this:
size = 0.5
type = 7
set term pngcairo
set output 'Foo.png'
set palette rgbformulae 22,13,-31
set cblabel "z"
unset key
set xlabel 'x'
set ylabel 'y'
set title 'y vs. x'
plot "Data.txt" u 1:2:3 w p pt type ps size palette
This works, but I would like to make the following change: For each point whose z value is below a cutoff, say 1.0, I want the color to be set to grey, regardless of the z-value. Then for z-values greater than or equal to the cutoff, I want the color to be picked from the palette according to the z-value.
Thus, I want the color to go discontinuously from grey to blue (for the current palette) at the cutoff value. Can this be done, and if so how?
It is difficult to do with a palette based on rgbformulae. It's relatively easy with a defined palette. Here is an example that gives a palette close to what you chose, with a dark gray tacked on at the bottom end. cbrange is then set so that your z cutoff is the minimum. All z values below cbmin will be assigned the endpoint value, which is dark gray in this case.
set xrange [0:1]; set yrange [0:pi]
set sample 100; set isosample 100
set palette defined (-0.01 "grey20", 0 "blue", 0.4 "green", 0.6 "yellow", 1.0 "red")
zmin = -0.6
set cbrange [zmin: *]
set xyplane at zmin
splot cos(x)*sin(y+y*(x*x)) with pm3d
After gnuplot 5.4, this can be achieved by using the function "palette()" in "using" and combining it with the "with point lc rgb variable".
size = 3 ### 0.5 in original code
type = 7
set term pngcairo
set output 'Foo.png'
set palette rgbformulae 22,13,-31
set cblabel "z"
unset key
set xlabel 'x'
set ylabel 'y'
set title 'y vs. x'
set cbrange [0:2] ### this is required by palette() function
gray = 0x808080 ### gray color expressed by integer
plot NaN w p palette, \
"Data.txt" u 1:2:($3<1 ? gray : palette($3)) w p pt type ps size lc rgb variable
The RGB value passed to "lc rgb variable" are determined by comparing $3 with threshold value 1(for example).
"NaN w p palette" is a dummy plot, a technique for forcing the colorbox to appear. Without it, the colorbox will not be displayed.
Here is a gnuplot 5.2 version. You can use a rgbformulae palette.
It uses the datablock $PALETTE which is created after carrying out the command test palette.
Code: (tested with gnuplot as low as 5.2.0)
### cut-off colors for a given rgbformulae palette (gnuplot >=5.2)
reset session
# create some test data
set xrange [-5:5]
set yrange [-5:5]
set samples 50
set isosamples 50
set table $Data
splot (sin(1.3*x)*cos(.9*y)+cos(.8*x)*sin(1.9*y)+cos(y*.2*x))*3
unset table
set palette rgbformulae 22,13,-31
test palette # necessary to put the palette into the datablock $PALETTE
myColorMin = 0
myColorMax = 6
myOutOfRangeColor = 0x808080
myColorPos(c) = int(255.0 * (c-myColorMin)/(myColorMax - myColorMin))+1
myColor(c) = c<myColorMin || c>myColorMax ? myOutOfRangeColor : \
(int(word($PALETTE[myColorPos(c)],2)*0xff)<<16) + \
(int(word($PALETTE[myColorPos(c)],3)*0xff)<<8) + \
(int(word($PALETTE[myColorPos(c)],4)*0xff))
set cbrange [myColorMin:myColorMax]
set view 36, 72
set ztics 5
splot $Data u 1:2:3:(myColor($3)) w pm3d lc rgb variable notitle
### end of code
Result:

gnuplot: How to plot points over the bars of a clustered histogram?

I'm making some speedup graphs using histogram clustered. For each instance, I group the speedup reached using 2,4,8,16 and 32 computers. I also use a line to indicate the "linear speedup". However, for each instance/computer, I would like also to place a point on top of it, to indicate a value I'm comparing my speedup to.
I've tried to use the same strategy for plotting the boxes, but using points instead. However, the points are plotted on the same place, they are not obeying the ''clustered'' spacing.
Here is the code I'm using:
set yrange [0:105]
set grid ytics
set style line 1 lc rgb '#0e1111' lt 1 lw 2 pt -1 ps 1.0
set xlabel "Instance" font "sans, 18"
set ylabel "Normalized Speedup (In %)" font "sans, 18"
set style histogram clustered
plot for [COL=2:2] 'data.dat' using COL:xticlabels(1) title columnheade lc rgbcolor "black" lt -1 fs pattern 3,\
for [COL=3:3] 'data.dat' using COL:xticlabels(1) title columnheade lc rgbcolor "black" lt -1 fs pattern 1,\
"linear.t" t "Lin" with linespoints ls 1
Example of data
0 2 4 8 16 32
ta22 65.67 37.98 38.16 30.91 19.24
ta23 73.69 45.59 48.59 44.20 34.19
That's what I got. The points are what I would like to have.
Is it possible to have such a thing? It would also work like an error bar. However, without line and just a ''max''.
Thank you all!
I couldn't run your code. But, based on your image, I understood you problem.
To plot the points with you want, I created a file called points.dat.
0 2 4 8 16 32
ta22 75.67 47.98 48.16 40.91 29.24
ta23 83.69 55.59 58.59 54.20 44.19
This one nothing else is that your data + 10.
The gnuplot code
reset # Restore the default settings
set encoding utf8 # Selects the character encoding
set terminal pngcairo size 800,500 # Generates output in png
set output 'histogram.png' # The filename
set grid ytics ls -1 lc 'gray' # Grid lines ytics only
set yrange [0:100] # Yrange 0 to 100 (% ?)
set style data histograms # Type of data: histograms
set style histogram clustered gap 1 # Type of histogram: clustered with gap 1
set style fill transparent solid 1 border lt -1 # Style: fillstyle and border
stats 'points.dat' skip 1 matrix nooutput # Statistical summary with skip
# for header and without output
numRows = STATS_size_y # Y size of matrix (rows)
numCols = STATS_size_x # X size of matrix (columns)
array Value[numRows*(numCols-1)] # Create an array based on size of data
position = 0 # Count to position on array
# Loop for populate the array
do for [i=1:numRows]{
do for [j=2:numCols]{
# Statistical summary (with skip for header) at each value and without output
stats 'points.dat' skip 1 u j every ::i-1::i-1 nooutput
position = position + 1 # Increase the count of position
Value[position] = STATS_min # Define the array-value as result of statistical analysis
}
}
# Mapping functions:
# i-cluster/rows (x-values),
# j-column (y-values)
# ignore the cluster name ($1)
posX(i, j) = (i - 1) + 1.0*(j - numCols + 3)/numCols # To X-values
posY(i, j) = i == 1 ? Value[j] : Value[numCols - 1 + j] # To Y-values
# The plot itself as newhistogram and nested loops:
# i-loop to bars and title as columnheade
# j-loop to rows (x-values)
# k-loop to columns (y-values)
plot \
newhistogram ,\
for [i=2:numCols]\
'data.dat' u i:xticlabels(1) ls i-1 title columnheade,\
for [j=1:numRows] \
for [k=1:numCols-1] \
'+' u (posX(j, k)):(posY(j, k)) w p pt 5 ps 0.75 lc 'black' notitle
produces

Merge key entries in gnuplot

I would like to plot data with lines and points with different colors. It seems to exist different solutions:
https://stackoverflow.com/a/31887351/4373898 , https://stackoverflow.com/a/31562632/4373898
https://gnuplot-tricks.blogspot.fr/2009/12/defining-some-new-plot-styles.html
However, none of them handle the key properly, showing only one entry with both the line and a point with different colors...
Is there another way to achieve it?
This is minimal (non-)working example.
set key bottom right
plot '+' using 1:1 title "same data with different lines and points color" with lines lc 'blue', '' using 1:1 every 3 notitle with points ps 1.2 pt 7 lc 'red';
Kind regards,
Alexis.
If your plot is not too complex, you could perhaps achieve this by playing with the spacing parameter of the legend. Setting spacing to -1 achieves that the labels/symbols overlap:
set terminal pngcairo enhanced
set output 'fig.png'
set xr [-pi/2:pi/2]
set yr [0:1]
set key at graph 0.95,graph 0.9 spacing -1
plot \
cos(x) w l lc rgb 'dark-red' lw 2, \
'-' w p lc rgb 'royalblue' pt 7 ps 2 t ' '
-1 0.540302
0 1
1 0.540302
e
which gives
However, the disadvantage is that the setting is in a sense global - should the plot contain more functions/data files, everything would overlap. In order to use this "method" in this particular case, it would be necessary to invoke multiplot and create the keys separately.
Having 3 different colors for a linespoints plot is certainly "non-standard" and as you noticed a challenge especially for the proper key.
Here is a suggestion without using multiplot. Personally, I would use multiplot only if absolutely necessary. Otherwise you will lose the benefits of automargin and autoscale and you have to deal with margins and ranges, etc. yourself as you did in your solution.
Since the automatic creation of the key is the problem, then "do-it-yourself".
Update: simplified plot command and legend at graph coordinates.
This suggestion draws the legend via labels and arrows. You give the position and distances of the legend in graph coordinates.
The mix of points and linespoints within a for loop is taken from here.
Script: (works with gnuplot>=5.0.0, Jan. 2015)
### legend for plot with linespoints and different colors for line, fill and border
reset session
# no. lw pt colorLine colorFill colorBorder label
mySettings = '\
1 2 5 0x00ff00 0xffff00 0xff0000 "x + 1" \
2 2 7 0x0000ff 0xff00ff 0x000000 "x^2 - 8" \
' # end of settings
myLw(n) = real(word(mySettings,n*7-5)) # linewidth
myPt(n) = int(word(mySettings,n*7-4)) # pointtype
cL(n) = int(word(mySettings,n*7-3)) # color line
cF(n) = int(word(mySettings,n*7-2)) # color fill
cB(n) = int(word(mySettings,n*7-1)) # color border
myLabel(n) = word(mySettings,n*7) # label
myLt(n) = n==1 ? 1 : -2
myPtL(v,i) = i==1 ? 0 : i==2 ? myPt(v) : myPt(v)-1
myColor(v,i) = i==1 ? cL(v) : i==2 ? cF(v) : cB(v)
myPs = 3 # fixed pointsize
# Legend position graph units
xPos = 0.05 # x-position
yPos = 0.95 # y-position
dy = 0.07 # y distance
dx = 0.025 # x length
set for [i=1:words(mySettings)/7] arrow from graph xPos-dx,yPos-(i-1)*dy to graph xPos+dx,yPos-(i-1)*dy \
lw myLw(i) lc rgb myColor(i,1) nohead back
set for [i=1:2] for [j=2:3] label myLabel(i) at graph xPos,yPos-(i-1)*dy left offset 3,0 \
point pt myPtL(i,j) ps myPs lc rgb myColor(i,j) lw myLw(i) front
set samples 11 # samples for functions
set key noautotitle
set grid x
set grid y
f1(x) = x + 1
f2(x) = x**2 - 8
plot for [i=1:3] f1(x) w lp lt myLt(i) pt myPtL(1,i) ps (i>>1)*myPs lc rgb myColor(1,i) lw myLw(1), \
for [i=1:3] [-5:5] f2(x) w lp lt myLt(i) pt myPtL(2,i) ps (i>>1)*myPs lc rgb myColor(2,i) lw myLw(2)
### end of script
Result:
Thanks ewcz for your answer, it is a first step toward the expected result. However, as you stated it, this is a little bit trickier to adapt it if you have multiple functions/data to display on the same plot.
Below is a minimal working example with two functions (and thus, two key entries) with a line, points, and points outline of different colors.
# These parameters are used to compute the spacing between entries of the key
pointSize = 1;
yticsScale = 1;
# We use the default spacing (1.25)
keySpacing = pointSize*yticsScale*1.25;
# Initial coordinate of the key
keyY = 4; # In character system
keyX = 0.87; # In graph system
# Just to generate data
set samples 20;
set xrange [-pi:pi];
set term pngcairo;
set output 'graph.png';
set xlabel "x"
set ylabel "y"
# Set the alignment (and thus the coordinate point) of the key
# Set the spacing to -1 to stack different (thanks to ewcz for the idea)
set key bottom right spacing -1
# Start a multiplot
set multiplot
# Make plots as big as possible
set origin 0,0
set size 1,1
# Set the key position
set key at graph keyX, character keyY
# Plot multiple times the same function with different styles.
# Make sure that all functions have a title (empty if necessary).
plot cos(x+pi) w l lc "light-red", \
cos(x+pi) w p pt 5 ps 1.8 lc "dark-red" t ' ', \
cos(x+pi) w p pt 5 ps 1.2 lc "red" t ' '
# Update key coordinates for the next plot
keyY = keyY + keySpacing
# Draw the key of the next plot at the new coordinates
set key at graph keyX, character keyY
plot cos(x) w l lc "light-blue", \
cos(x) w p pt 7 ps 1.8 lc "dark-blue" t ' ', \
cos(x) w p pt 7 ps 1.2 lc "blue" t ' ';
# That's all
unset multiplot
set output;
The resulting plot:
Hope that will help others.
Kind regards.
Alexis
Edit:
The previous code works if both functions/data have the same ranges (on x and y) allowing autoscale to work properly.
In the case of data where you do not know the ranges, you must compute it before plotting.
# Just to generate data
set samples 20;
# First data will be defined on [-pi:pi] with values between -1 and 1.
set table '1.dat'
plot [-pi:pi] cos(x)
unset table
# Second data will be defined on [-pi/2,pi/2] with values between 0 and -2
set table '2.dat'
plot [-pi/2:pi/2] 2*cos(x+pi)
unset table
# These parameters are used to compute the spacing between entries of the key
pointSize = 1;
yticsScale = 1;
keySpacingScale = 1.25; # Gnuplot default spacing
keySpacing = pointSize * yticsScale * keySpacingScale; # Spacing computation
set pointsize pointSize;
set ytics scale yticsScale;
set key spacing -1; # Make key entries overlapping (thanks ewcz for the idea)
# Initial coordinate of the key
keyY = 4.5; # In character system
keyX = 0.98; # In graph system
set term pngcairo;
set output 'graph.png';
# Remove redundant objects
# Borders, labels, tics will be drawn for each plot, this is not necessary as all plots will be stacked. So remove then.
set border 0
set tics textcolor "white" # Dirty tricks to keep plots aligned but to not show the tics
set xlabel " " # The same
set ylabel " " # The same
# Compute the ranges
min(v1, v2) = (v1 < v2) ? v1 : v2;
max(v1, v2) = (v1 > v2) ? v1 : v2;
# Get min and max for the data
stats [*:*] [*:*] '1.dat' name 'f1' nooutput;
stats [*:*] [*:*] '2.dat' name 'f2' nooutput;
# Get the range limits
xmin = min(f1_min_x, f2_min_x)
xmax = max(f1_max_x, f2_max_x)
ymin = min(f1_min_y, f2_min_y)
ymax = max(f1_max_y, f2_max_y)
# Autoscale the range to match all the data
set xrange [* < xmin:xmax < *] writeback
set yrange [* < ymin:ymax < *] writeback
# Start a multiplot
set multiplot
# Make plots as big as possible
set origin 0,0
set size 1,1
# Set the key
set key bottom right at graph keyX, character keyY
# Plot multiple times the same function with different styles.
# Make sure that all functions have a title (empty if necessary).
plot '1.dat' w l lc "light-red" t "cos(x)", \
'' w p pt 5 ps 1.8 lc "dark-red" t ' ', \
'' w p pt 5 ps 1.2 lc "red" t ' '
# Update key coordinates for the next plot
keyY = keyY + keySpacing
# Draw the key of the next plot at the new coordinates
set key at graph keyX, character keyY
# Display at least once the labels
set border
set tics textcolor "black"
set xlabel "x"
set ylabel "y"
# Disable ranges autoscaling
set xrange restore
set yrange restore
plot '2.dat' w l lc "light-blue" t "2cos(x+pi)", \
'' w p pt 5 ps 1.8 lc "dark-blue" t ' ', \
'' w p pt 5 ps 1.2 lc "blue" t ' '
# That's all
unset multiplot
set output;
One more time the resulting plots:
Kind regards,
Alexis

gnuplot - Histogram with histeps connects bars

This is a minimal working example of the code I'm using:
#!/bin/bash
gnuplot << EOF
set term postscript portrait color enhanced
set encoding iso_8859_1
set output 'temp.ps'
set grid noxtics noytics noztics front
set size ratio 1
set multiplot
set lmargin 9; set bmargin 3; set rmargin 2; set tmargin 1
n=32 #number of intervals
max=13. #max value
min=-3.0 #min value
width=(max-min)/n #interval width
hist(x,width)=width*floor(x/width)+width/2.0
set boxwidth width
set style fill solid 0.25 noborder
plot "< awk '{if (3.544068>=\$1) {print \$0}}' /data_file" u (hist(\$2,width)):(1.0) smooth freq w boxes lc rgb "red" lt 1 lw 1.5 notitle
EOF
which gets me this:
What I need is to use histeps instead, but when I change boxes for histeps in the plotcommand above, I get:
What is going on here??
Here's the data_file. Thank you!
EDIT: If having histeps follow the actual outer bars limits instead of interpolating values in between (like boxesdoes) is not possible, then how could I draw just the outline of a histogram made with boxes?
EDIT2: As usual mgilson, your answer is beyond useful. One minor glitch though, this is the output I'm getting which when I combine both plots with the command:
plot "< awk '{if (3.544068>=\$1) {print \$0}}' data_file" u (hist(\$2,width)):(1.0) smooth freq w boxes lc rgb "red" lt 1 lw 1.5 notitle, \
"<python pyscript.py data_file" u 1:2 w histeps lc rgb "red" lt 1 lw 1.5 notitle
Something appears to be shifting the output of the python script and I can't figure out what it might be.
(Fixed in comments)
The binning is quite easy if you have python + numpy. It's a very popular package, so you should be able to find it in your distribution's repository if you're on Linux.
#Call this script as:
#python this_script_name.py 3.14159 data_file.dat
import numpy as np
import sys
n=32 #number of intervals
dmax=13. #max value
dmin=-3.0 #min value
#primitive commandline parsing
limit = float(sys.argv[1]) #first argument is the limit
datafile = sys.argv[2] #second argument is the datafile to read
data = [] #empty list
with open(datafile) as f: #Open first commandline arguement for reading.
for line in f: #iterate through file returning 1 line at a time
line = line.strip() #remove whitespace at start/end of line
if line.startswith('#'): #ignore comment lines.
continue
c1,c2 = [float(x) for x in line.split()] #convert line into 2 floats and unpack
if limit >= c1: #Check to make sure first one is bigger than your 3.544...
data.append(c2) #If c1 is big enough, then c2 is part of the data
counts, edges = np.histogram(data, #data to bin
bins=n, #number of bins
range=(dmin,dmax), #bin range
normed=False #numpy2.0 -- use `density` instead
)
centers = (edges[1:] + edges[:-1])/2. #average the bin edges to the center.
for center,count in zip(centers,counts): #iterate through centers and counts at same time
print center,count #write 'em out for gnuplot to read.
and the gnuplot script looks like:
set term postscript portrait color enhanced
set output 'temp.ps'
set grid noxtics noytics noztics front
set size ratio 1
set multiplot
set lmargin 9
set bmargin 3
set rmargin 2
set tmargin 1
set style fill solid 0.25 noborder
plot "<python pyscript.py 3.445 data_file" u 1:2 w histeps lc rgb "red" lt 1 lw 1.5 notitle
I'll explain more when I get a little more free time ...

Resources