1

This seems like a simple task or a repeat, but bear with me-- I've searched for a little while and haven't found any easy answers.

I have a scatterplot that I would like to display as a heatmap. My values look like this:

{ (3, 3): 1.7314, (3,4):-6.99, (4,3):-17.3, (4, 4):-100.0 }

I would like to display a matrix starting with cell (3,3), which has a brightness of 1.7314, etc.

I have found several questions and answers regarding situations where you give lists of two dimensional tuples (X, Y) and the Z value (the intensity) for each point (x,y,z) is created by the number of occurrences around (x, y).

I have also used imshow to draw such a plot, but for imshow you drop the (3,3), etc. So things can be shifted strangely. One option is to use imshow and then manually adjust the axis labels afterward. But I feel like someone must have solved this before without hacking pylab too much.

What is the best way to do this?

user
  • 7,123
  • 7
  • 48
  • 90
  • Have you evaluated matplotlib? – Roger Feb 02 '12 at 18:21
  • What do you mean with "you drop the (3,3)"? – Ricardo Cárdenes Feb 02 '12 at 18:22
  • Take a look at [Generate a heatmap in MatPlotLib using a scatter data set](http://stackoverflow.com/questions/2369492/generate-a-heatmap-in-matplotlib-using-a-scatter-data-set). – Roger Feb 02 '12 at 18:23
  • @Roger `imshow` is from `matplotlib` / `pylab`, and is what I plan to use for the actual drawing. – user Feb 02 '12 at 18:26
  • 1
    @Roger: I think that's what he's talking about when he refers to solutions where the intensity is calculated using the number of occurrences around a certain `(x, y)` (in this case, using a histogram). – Ricardo Cárdenes Feb 02 '12 at 18:26
  • @Roger Please notice that I *do* have a `Z`. As I said, there are plenty of questions and answers that compute `Z` using frequency. I already have "brightness" values that I want to use. – user Feb 02 '12 at 18:27
  • @Oliver: I can't see the problem, unless your coordinates are not always integers. You should be able to populate an empty array with your intensity values and then just `imshow` it! – Ricardo Cárdenes Feb 02 '12 at 18:28
  • @RicardoCárdenes `imshow` only takes the matrix of `Z` values and doesn't make use of the `(X,Y)` matrix itself. So the axes automatically start at `(0,0)`. – user Feb 02 '12 at 18:30
  • @RicardoCárdenes Yes, but the axes labels are shifted. As I say, I could try to manually change them, but this feels like such well-worn territory, I thought I should ask if there is a better way (starting from the list of 3-tuples `(X,Y,Z)` and generating the plot). – user Feb 02 '12 at 18:32
  • @RicardoCárdenes, looks like I didn't read the question. Please disregard ;) – Roger Feb 02 '12 at 18:38

1 Answers1

2

Ok, let's try an easy example using your sample data:

import numpy as np
from pylab import * 

data = { (3, 3): 1.7314, (3,4):-6.99, (4, 3):-17.3, (4, 4):-100.0 }
matrix = np.zeros((5, 5))
for (x, y), z in data.items():
    matrix[y,x] = z

imshow(matrix[3:, 3:], origin='lower', interpolation='none', extent=[2.5, 4.5, 2.5, 4.5])
show()

As you see, you can control the axes by specifying the limits using extent. The default (if None) would be (-0.5, numcols-0.5, -0.5, numrows-0.5) (left, right, bottom, top) if you specify you want the origin in the lower part, for the Y axis.

Also, interpolation='none' is important for your case.

Ricardo Cárdenes
  • 9,004
  • 1
  • 21
  • 34
  • Ah, it was `extent` that I was having trouble finding. Thanks a lot! – user Feb 02 '12 at 18:56
  • Actually, there's an example using `extent` just under `imshow`'s [documentation](http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.imshow). It's just you needed too have a look to the source code :) – Ricardo Cárdenes Feb 02 '12 at 18:58
  • I think I would need to use interpolation = 'nearest'; 'none' crashes. – user Feb 02 '12 at 18:58
  • Hmm... any idea how to limit `extent` to a fixed set? I don't want to display axis labels for 0.5, 1.5, etc.; I only want numbers that I choose. – user Feb 02 '12 at 19:01
  • `None` doesn't crash, but `'none'` does. Perhaps we have different versions. – user Feb 02 '12 at 19:03
  • Hmm, it looks like I have to do it manually with `set_xticks` using the axes. It's amazing there isn't a stock function for this! – user Feb 02 '12 at 19:07
  • The ticks that are used depend on the number of elements and the size of the plot (I'm afraid), so in some cases you'll need to specify the ones you want. – Ricardo Cárdenes Feb 02 '12 at 19:13