10

I want to do something similar to http://matplotlib.org/examples/pylab_examples/hist2d_log_demo.html but I've read that using pylab for code other than in python interactive mode is bad practice so I'd like to do this with matplotlib.pyplot. However, I can't figure out how to make this code work using pyplot. Using, pylab, the example given is

from matplotlib.colors import LogNorm
from pylab import *

#normal distribution center at x=0 and y=5
x = randn(100000)
y = randn(100000)+5

hist2d(x, y, bins=40, norm=LogNorm())
colorbar()
show()

I've tried a lot like

import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
h1 = ax1.hist2d([1,2],[3,4])

and from here I've tried everything from plt.colorbar(h1) plt.colorbar(ax1) plt.colorbar(fig) ax.colorbar() etc etc and I can't get anything to work.

In general, I'm honestly not really clear on the relationship between pylab and pyplot, even after reading http://matplotlib.org/faq/usage_faq.html. For example show() in pylab seems to become plt.show() in pyplot, but for some reason colorbar doesn't become plt.colorbar()?

For example,

knightian
  • 683
  • 1
  • 7
  • 20
  • Actually `colorbar` leaves in matplotlib itself: [link](http://matplotlib.org/api/colorbar_api.html). So you might want to `import matplotlib as mpl` and `mpl.colorbar()`. – arbulgazar Jul 02 '14 at 06:07

2 Answers2

10

A colorbar needs a ScalarMappable object as its first argument. plt.hist2d returns this as the forth element of the returned tuple.

h = hist2d(x, y, bins=40, norm=LogNorm())
colorbar(h[3])

Complete code:

from matplotlib.colors import LogNorm
import matplotlib.pyplot as plt
import numpy as np

#normal distribution center at x=0 and y=5
x = np.random.randn(100000)
y = np.random.randn(100000)+5

h = plt.hist2d(x, y, bins=40, norm=LogNorm())
plt.colorbar(h[3])
show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
3

This should do it:

from matplotlib.colors import LogNorm
import matplotlib.pyplot as plt
from numpy.random import randn

#normal distribution center at x=0 and y=5
x = randn(100000)
y = randn(100000)+5

H, xedges, yedges, img = plt.hist2d(x, y, norm=LogNorm())
extent = [yedges[0], yedges[-1], xedges[0], xedges[-1]]
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
im = ax.imshow(H, cmap=plt.cm.jet, extent=extent, norm=LogNorm())
fig.colorbar(im, ax=ax)
plt.show()

Notice how colorbar is attached to "fig", not "sub_plot". There are some other examples of this here. Notice how you also need to generate a ScalarMappable with imshow, as explained in the API here.

Community
  • 1
  • 1
philE
  • 1,655
  • 15
  • 20
  • Thanks! `imshow()` seems like it's treating numbers as pixel values? Just for testing, I'm using x=[1,2,3] and y=[4,5,6] and I'm not sure if that's correct, but I'm getting a very smooth rainbow image, even though I'm using tiny arrays, and I can't figure out what's generating these images. I'm also getting a colorbar ranging from 1-6 which is confusing to me? Ideally I'd want the colorbar scale to align with the histogram, but perhaps it's linked with the imshow instead? – knightian Jul 02 '14 at 07:03
  • `imshow` takes the MxN array given to plot out and shows the corresponding histogram. I've fixed the code in my answer accordingly. To see concretely what I'm talking about, look at `H` with a modified version of your example with x=[1, 2, 3, 3] y=[4, 5, 6, 6] . If you take away the `norm` argument, you should get what you're looking for, now. If you want to discretize the output, there's a good example [here](http://stackoverflow.com/questions/14777066/matplotlib-discrete-colorbar). There are some other nice examples [here](http://jakevdp.github.io/mpl_tutorial/tutorial_pages/tut3.html). – philE Jul 02 '14 at 17:51
  • note, `imshow` assumes, like you say, that each value is a pixel value, thus every color 'box' is the same size as every other color box. If you need to set different sizes (such as when putting a heat map on a map projection) you should use [pcolormesh](http://matplotlib.org/examples/pylab_examples/pcolor_demo.html). – mnky9800n May 25 '16 at 15:51
  • Another note: `im = ax.imshow(H, cmap=plt.cm.jet, extent=extent, norm=LogNorm())` should be `im = ax.imshow(H.T, cmap=plt.cm.jet, extent=extent, norm=LogNorm(), origin='lower')`, changing `H` to `H.T` and adding `, origin='lower'`, to have `imshow()` look like `hist2d()` – Daniel-Dane Aug 19 '19 at 12:10