Irregular tile size in matplotlib hexbin

When creating a hexbin graph in matplotlib, I find that alternating rows of hexagonal plates have different sizes, sometimes significantly. This demo code shows the effect:

from matplotlib import pyplot as plt from matplotlib import cm as cm from matplotlib import mlab as ml import numpy as np n = 1e5 x = y = np.linspace(-5, 5, 100) X, Y = np.meshgrid(x, y) Z1 = ml.bivariate_normal(X, Y, 2, 2, 0, 0) Z2 = ml.bivariate_normal(X, Y, 4, 1, 1, 1) ZD = Z2 - Z1 x = X.ravel() y = Y.ravel() z = ZD.ravel() plt.subplot(111) plt.hexbin(x, y, C=z, gridsize=30, cmap=cm.jet, bins=None) plt.axis([x.min(), x.max(), y.min(), y.max()]) cb = plt.colorbar() cb.set_label('mean value') plt.show() 

In this image , with a grid of 30, you can see that alternating lines are slightly curled vertically:

The effect is not very significant, but in this enlarged view of the same hexbin chart, but with a grid of 80, small lines are almost twice as large as large rows. (The generated sample data begins to misalign with the grid, but this is an immaterial artifact.)

The hexbin documentation says:

gridsize: [100 | integer]

The default number of hexagons in the x direction is 100. The corresponding number of hexagons in the y direction is selected so that the hexagons are approximately regular. Alternatively, the grid set may be a tuple with two elements defining the number of hexagons in the x-direction and the y-direction.

This only ensures that the hexagons are โ€œapproximatelyโ€ regular, but it seems that especially in cases like the image with 80 faces above, the hexagons could be made much closer to the regular one, reducing the number of rows so small rows can be enlarged and made more regular. Or normal-sized rows can be scaled down vertically, while small ones can be scaled up vertically, keeping all lines the same height, even if the tiles do not have the correct shape.

What is the cause of this unevenness and can it be avoided?

+7
source share
1 answer

After several experiments, I think I found the reason. The documentation for hexbin also mentions:

line width: [No | scalar]

If None, rc lines.linewidth is used by default. Note that this is a tuple, and if you specify the lin lineidths argument, you must set it as a sequence of floats, as required by RegularPolyCollection.

Other keyword arguments controlling Collection properties:

edgecolors: [No | 'none' | color mpl | color sequence]

If "none", draws the edges of the same color as the fill color. This is the default because it avoids unsightly unpainted pixels between hexagons.

If None, draws the color outline by default.

If the color argument is matplotlib or a sequence of rgba tuples, the outlines are in the specified color.

Setting the line width to (0,), I set the ugly unpainted pixels, but my hexagons were the same size. It seems that some rows of hexagons were in a higher layer and stretched with excessively large borders protruding above adjacent rows. The line width value (1) gives the uneven results that I saw before, so this may be the default value. Line widths between 0 and 1 (I use 0.25) cover unpainted pixels without causing a lot of overlap, creating a much nicer plot. However, this only happens when saving the image using savefig () with a higher DPI than the default (I use dpi = 300). Calling show () or saving with DPI by default creates graphics with unpainted pixels. Thus, while this is effective, this workaround is somewhat limited.

+6
source

All Articles