I have a data file that I would like to plot as a heatmap. There are 3 columns: x, y, and the count at point (x,y). The problem is that the bins have different sizes in y (and not in x), for example
-0.3 0 0
-0.3 6.7082 0
-0.3 8.66025 0
-0.3 10.247 0
-0.3 11.619 0
-0.3 12.8452 0
...
But when I plot using for example
set view map
set size ratio -1
set key off
splot "histo.txt" u 1:2:3 w image
I get an image in which the bin sizes in the y direction are the same, thus the picture is distorted.
How can I plot a heatmap with different bin sizes in one direction? I also know exactly where each bin should begin and end in y, the values in the second column of the data file are a weigthed average.
Thank you.
Gnuplot offers basically two plotting styles suitable for heat maps, pm3d and image, which however have very different behaviour:
image:
Draws a pixel image
Always uses a regular grid, no matter what x or y values are used
Each quadrangle (here, the pixel) is centered on one data point
pm3d:
Draws vectorial quadrangles
Can use irregular grids with varying spacings
Draws each quadrangle with four data points as corners. The color is by default given by the mean value of those four points, that can be changed with set pm3d corners2color ...
Can interpolate
Many more features, applicable for 3d etc
So, to summarize: image can be used for heat maps and has its advantages, but in your case you need pm3d, which offers you the flexibility, you need.
Related
I'm sorry if this has already been asked, I couldn't find it anywhere, but I have an image plot on gnuplot of a three-columned data file for a y range [0:24] and I can't figure out how to use gnuplot to rearrange the image graph so my y axis runs from 16:24 and then 0:16 (in that order and on the same axis). The command I've been using is "plot [] [0:24] '/Users/eleanor/PycharmProjects/attempt2.gray' u 1:2:3 w image" but I don't know what command to use so that hour 16 is at the very bottom instead of 0, and then when y reaches 23:59 y goes to 0 next and then continues increasing up to 15:59 at the very top of the axis. I'm not sure if that makes sense or not, and I've already tried changing the y range to [16:15] and that did nothing except give me an error lol. Any tips would be very much appreciated! :)
a piece of the file im using is below (with the first column being the day of year, the second being the time in decimal hours, and the third being the data):
20 0.0 7.327484247409568
20 0.002777777777777778 8.304658863945411
20 0.005555555555555556 11.641408500506405
20 0.008333333333333333 6.543382279013497
20 0.011111111111111112 13.922090817182697
20 0.013888888888888888 10.696406455987988
20 0.016666666666666666 12.537636516165243
20 0.019444444444444445 11.816216763447612
20 0.022222222222222223 8.914413125514413
20 0.025 5.8225423124691496
20 0.027777777777777776 10.896730484548698
20 0.030555555555555555 9.097140108173859
As currently implemented, with image treats the entire block of data as a single entity. You can't chop it up into pieces within a single plot command. However if your data is dense enough, it may be that you can approximate the same effect by plotting each pixel as a colored square:
set xrange [*:*] noextend
set yrange [0:24]
plot 'datafile' using 1:(($2>16.)? ($2-16.) : ($2+8.)):3 with points pt 5 lc palette
I strongly recommend not making the range limits part of the plot command. Set them beforehand using set xrange and set yrange.
If necessary, you can adjust the size of the individual square "pixels" by using set pointsize P where P is a scale factor. It probably looks best if you make the points just large enough (or small enough) to touch each other. I think the default ones in the image I show are too large.
You can also use the boxxyerror plotting style instead of the image plotting style. Well, here's what the help for boxxyerror says
gnuplot> ? boxxyerror
The `boxxyerror` plot style is only relevant to 2D data plotting.
It is similar to the `xyerrorbars` style except that it draws rectangular areas
rather than crosses. It uses either 4 or 6 basic columns of input data.
Additional input columns may be used to provide information such as
variable line or fill color (see `rgbcolor variable`).
4 columns: x y xdelta ydelta
6 columns: x y xlow xhigh ylow yhigh
....
If you adopt the four-column plotting style above, you must specify xdelta and ydelta in addition to x and y to specify the rectangle. The xdelta and ydelta should be the half-width and half-height of each pixel. From your data, let's say xdelta is half of 1 and ydelta is half of 0.002777777777777778 hours.
Our final script will look like this.
In this script, the second column of "using" is the same as Ethan's answer.
dx = 1.0/2.0
dy = 0.002777777777777778/2.0
set xrange [-1:32]
set yrange [0:24]
set ytics ("16" 0, "20" 4, "0" 8, "4" 12, "8" 16, "12" 20, "16" 24)
set palette defined (0 "green", 0.5 "yellow", 1 "red")
unset key
plot "datafile" using 1:($2>16?($2-16):($2+8)):(dx):(dy):3 \
with boxxy palette
I used to make nice pm3d maps with gnuplot with a simple code like this:
set pm3d map
set palette
splot data using 1:2:3
But that had data organized as follows:
1 1 1
1 2 1
1 3 2
2 1 1
2 2 3
2 3 4
3 1 1
3 2 1
3 3 3
I never really understood the need for line break here but it worked. Now my data is quite different, the data in the first and second columns are not as simply repeated they are like this:
1.1 -1 2
1.2 3 3
1.11 4 4
...
I don't have any line breaks there since i have not idea how i should organise them. The question is, how would i make a heatmap from this? (rounding is not a good option)
Some sample data can be found here. They were created from an original 21x21 array (see below).
Some background
Originally, the data were in a table indexed by integers. It was basically a polar stereographic projection of the lunar surface. So i converted the indices to (x,y) distances then to planetocentric (latitude,longitude) pair and then to gnomonic polar coordinates recentered on a different point than one of the poles. I want to display the map as distance (x axis) and azimuth (y axis) (from the new centered point) and some value (the coloring of the map). The goal is to have something that looks like this:
The sample data you link to is highly structured, but not on an orthogonal grid. That is likely to produce artifacts. If the data were dense enough, you could simply draw each point as a solid block, perhaps with partial transparency. The example data you show is not very dense, however, so this is probably not suitable. I show such a plot below for reference.
set palette defined ( 0 "blue", 3 "green", 6 "yellow", 10 "red" )
set autoscale noextend
set pointsize 2
unset key
plot 'DT0C2.dat' using 1:2:3 with points pointtype 5 lc palette
The closest gnuplot has to dealing with unstructured sample is the dgrid3d mode. This basically uses the data points to assign value to nearby nodes on an orthogonal grid. Various weighting schemes are available to control how many data points contribute to each node and what is their relative contribution. The result is strongly dependent on choosing reasonable values for the orthogonal grid spacing and the weighting scheme. I won't attempt to describe all the options here. Please read the gnuplot documentation section on set dgrid3d. Here is a rough stab at it but I would want to understand the data a lot better to choose a good dgrid3d scheme. I think the sample data is not dense enough to produce a smooth result.
set palette defined ( 0 "blue", 3 "green", 6 "yellow", 10 "red" )
set autoscale noextend
set dgrid3d 75,75 gauss 100,25
set view map
splot 'DT0C2.dat' with pm3d
I have a file with X Y data points (> 10^4)
12.399999999999999 3.7333333333333334
22.13333333333334 34.93333333333333
13.600000000000001 10.133333333333333
94.26666666666667 26.
25.333333333333336 8.666666666666666
52. 38.
25.33333333333333 51.733333333333334
24.799999999999997 37.333333333333336
77.33333333333333 5.466666666666667
13.2 7.733333333333333
33.46666666666667 4.666666666666667
33.86666666666666 46.
52.8 3.466666666666667
24.400000000000002 20.933333333333334
54.53333333333334 27.6
121.73333333333335 30.133333333333333
103.73333333333333 13.466666666666667
47.599999999999994 5.333333333333333
...........
(positive and non-gridded), which I would like to plot with Gnuplot.
I have been looking different posts and examples, and they provide a function for the intensity or directly the Z values corresponding to the intensity, or they use an array of values indicating pixels or squared zones of an image.
I would like to ask if there is a way to plot an intensity map plot providing only the X and Y points. Also, I would like to know if it is possible to indicate the range to plot and the granularity (the bin size or the interpolation order).
Thank you very much for the help
EDIT (based on Comments)
I have tried set size square
set autoscale fix
unset key
set view map
set xrange [0:200]
set yrange [0:200]
set dgrid3d 10,10,4
splot "data.dat" w pm3d
Gnuplot tells me that I need a third column with the weights.
I have no third column in my dataset, just the X and Y values.
How could I correctly use dgrid3d, and plot an intensity map or frequency map of my points?
Note: My Gnuplot is version 5.2, and there is an option bin which can be used to bin x values, but I do not know if it can bin 2D points too
1-How can I rotate my plot so y would be the new x axis and vice versa?
2- Change the maximum value of y axis from 60 to 100.
The plot is created by this script in the terminal :
set palette grey
plot 'color_map.dat' matrix with image
You can exchange the x and y axes with the using modifier. (Just like for ordinary plots, except that for matrix data, columns 1 and 2 are not in your data file, but are inferred.)
plot 'color_map.dat' matrix using 2:1:3 with image
If you actually just want to change the maximum value on the y (new x) axis, you would use set xrange[:100]. But it sounds like you might actually want to scale the data itself, in which case you could use
plot 'color_map.dat' matrix using ($2/60.*100):1:3 with image
Try help plot matrix for more details.
Can I get gnuplot to display the exact y-value or height of a data point (plotted using "with boxes") over its bar? I would like the plot to be easy to read so nobody has to line up the top of a bar with the y-axis and guess what the value is.
You can use the labels style and combine it into the plot command with the boxes style. The labels style expects 3 columns of data - the x coordinate, the y coordinate, and the actual label text.
For example, with the following data
1 4
2 6
3 2
4 8
the command (we set the yrange to 0 - 10 and boxwidth to 0.9 and set a solid fill style)
plot datafile u 1:2 with boxes, "" u 1:2:2 with labels offset char 0,1
produces
Normally, the labels would be centered on the specified point (the top edge of the box). By specifying an offset, we can move them up to just above the box. Here we used no offset in the x direction, but a unit of 1 in the y direction. We used the character coordinate system, so this corresponds to moving up by one character unit.
I can only think of putting the values where you want them "manually" like this:
set label "value" at 12,34
The numbers are coordinates according to your x and y ranges.
An automatic way would use "with labels", see e.g.
http://gnuplot.sourceforge.net/demo_4.4/stringvar.html