how to set the grid when using pcolormesh

Maxibon Source

I am using pcolormesh to create a grid that overlaps a 2dhistogram.

import matplotlib.pyplot as plt
import numpy as np
import random

x = [random.randrange(1,161,1) for _ in range (10)]
y = [random.randrange(1,121,1) for _ in range (10)]

fig, ax = plt.subplots()

ax.set_xlim(0,160)
ax.set_ylim(0,120)

zi, yi, xi = np.histogram2d(y, x, bins=(50,120))
zi = np.ma.masked_equal(zi, 0)

ax.pcolormesh(xi, yi, zi, edgecolors='black')
scat = ax.scatter(x, y, s=2)

Although, this code only produces a grid that covers the outermost xy data points. enter image description here

I'd like the grid to be constant with the set axes limits (x = 0,160), (y = 0,120). So The grid is constantly covering the plotted area. From 0,0 to 160,120.

I have tried to use the vmin, vmax function in pcolormesh. But this just produces a blank figure. I don't get an error code though?

ax.pcolormesh(xi, yi, zi, edgecolors='black', vmin = (0,0), vmax = (120,160))

Is there another way to extend the grid to the desired axes limits?

pythonnumpymatplotlibplothistogram

Answers

answered 3 months ago swenzel #1

One problem is that the histogram2d function determines the bins itself if you use it like you do.
This means that both the offset and the width of your bins is unclear until runtime because they depend on your random points rather than on your axis limits. Now once the bins are found you could read back their shape and set an axis grid accordingly. But it's easier to create your own bins so you get a grid that spans the whole axis ranges.
Then you can set the edges of your bins as minor ticks and enable a grid on them.
Using the lines created by pcolormesh would work too but when using it you will get some lines that are thicker than others (this has to do with line positions falling between pixels). With axis grid this doesn't happen but some lines appear to cut through your bins. In the end it's a matter of taste which one you prefer. You can always play around with edgecolor and linewidth until pcolormesh shows a decent result.

import matplotlib.pyplot as plt
import numpy as np
import random

x = [random.randrange(1,161,1) for _ in range (10)]
y = [random.randrange(1,121,1) for _ in range (10)]

fig, ax = plt.subplots()

ax.set_xlim(0,160)
ax.set_ylim(0,120)

bins = [
    np.linspace(*ax.get_xlim(), 120),
    np.linspace(*ax.get_ylim(), 50)
]

# Note that I switched back to x, y and used zi.T later which I find
# more readable
zi, xi, yi = np.histogram2d(x, y, bins=bins)
zi = np.ma.masked_equal(zi, 0)

# Either use the next four lines for axis grid
ax.pcolormesh(xi, yi, zi.T)    
ax.set_xticks(bins[0], minor=True)
ax.set_yticks(bins[1], minor=True)
ax.grid(True, which='minor')

# or use the next line to stick with edges drawn by pcolormesh
# ax.pcolormesh(xi, yi, zi.T, edgecolor='black')
scat = ax.scatter(x, y, s=2)

plot created by the provided code

comments powered by Disqus