Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

hex size in pyplot.hexbin based on frequency

Is there a way to increase the reltive sizes of hexagons in pyplot.hexbin based on their frequency? I can only see binsize for the keyword arguments, which affects the number of hexes, but not their size.

But in this article (around 2/3 in under the heading 'Multivariate Hexagonal Binning'), it discusses drawing hexagons with size proportional to count in order to more clearly observe trends (see following image taken from that article)

enter image description here

Have I missed a keyword argument that allows this?

Thanks!

like image 540
L. Robinson Avatar asked Jan 03 '23 19:01

L. Robinson


1 Answers

For the plot in question there is no advantage of using hexagonal binning since the hexagons have different sizes and hence would not allow a consistent binning throughout the plot. You may however use a constant binning and just shrink the cells, which do not have the maximal value.

import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection
from matplotlib.path import Path
from matplotlib.patches import PathPatch
import numpy as np; np.random.seed(42)

a = np.random.rand(200,2)
b = np.random.rand(200)
c = np.concatenate((a,np.c_[b,b]), axis=0)

fig, ax = plt.subplots()

hexbin = ax.hexbin(c[:,0],c[:,1],gridsize=20, linewidth=0 )

def sized_hexbin(ax,hc):
    offsets = hc.get_offsets()
    orgpath = hc.get_paths()[0]
    verts = orgpath.vertices
    values = hc.get_array()
    ma = values.max()
    patches = []
    for offset,val in zip(offsets,values):
        v1 = verts*val/ma+offset
        path = Path(v1, orgpath.codes)
        patch = PathPatch(path)
        patches.append(patch)

    pc = PatchCollection(patches)
    pc.set_array(values)
    ax.add_collection(pc)
    hc.remove()

sized_hexbin(ax,hexbin)
plt.show()

enter image description here


For comparisson, one may transmit the same information via a scatter plot. This code is potentially much more intuitive than the above.
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(42)

a = np.random.rand(200,2)
b = np.random.rand(200)
c = np.concatenate((a,np.c_[b,b]), axis=0)

fig, ax = plt.subplots()

h, ex, ey = np.histogram2d(c[:,0],c[:,1], bins=np.linspace(0,1,20))

X,Y = np.meshgrid(ex[:-1]+np.diff(ex)/2.,ey[:-1]+np.diff(ey)/2.)

ax.scatter(X.flatten(),Y.flatten(), 
           c=h.T.flatten(), s=h.T.flatten()**2,
           marker="h")

plt.show()

enter image description here

like image 103
ImportanceOfBeingErnest Avatar answered Jan 10 '23 23:01

ImportanceOfBeingErnest