Skip to content

Commit 58e39b4

Browse files
committed
added marginal density option to hexbin
svn path=/trunk/matplotlib/; revision=6743
1 parent 7f1a1e6 commit 58e39b4

File tree

5 files changed

+114
-9
lines changed

5 files changed

+114
-9
lines changed

CHANGELOG

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2009-01-06 Added marginals kwarg to hexbin to plot marginal densities
2+
JDH
3+
14
2009-01-06 Change user-visible multipage pdf object to PdfPages to
25
avoid accidents with the file-like PdfFile. - JKS
36

boilerplate.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def %(func)s(*args, **kwargs):
102102
cmappable = {
103103
'contour' : 'if ret._A is not None: gci._current = ret',
104104
'contourf': 'if ret._A is not None: gci._current = ret',
105-
'hexbin' : 'gci._current = ret',
105+
'hexbin' : 'gci._current = ret[0]',
106106
'scatter' : 'gci._current = ret',
107107
'pcolor' : 'gci._current = ret',
108108
'pcolormesh' : 'gci._current = ret',

examples/pylab_examples/hexbin_demo2.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,14 @@
3939
gridsize=30
4040

4141
plt.subplot(211)
42-
plt.hexbin(x,y, C=z, gridsize=gridsize )
42+
plt.hexbin(x,y, C=z, gridsize=gridsize, marginals=True)
4343
plt.axis([xmin, xmax, ymin, ymax])
4444
cb = plt.colorbar()
4545
cb.set_label('mean value')
4646

47+
4748
plt.subplot(212)
48-
plt.hexbin(x,y, gridsize=gridsize )
49+
plt.hexbin(x,y, gridsize=gridsize)
4950
plt.axis([xmin, xmax, ymin, ymax])
5051
cb = plt.colorbar()
5152
cb.set_label('N observations')

lib/matplotlib/axes.py

+105-3
Original file line numberDiff line numberDiff line change
@@ -5212,7 +5212,7 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
52125212
xscale = 'linear', yscale = 'linear',
52135213
cmap=None, norm=None, vmin=None, vmax=None,
52145214
alpha=1.0, linewidths=None, edgecolors='none',
5215-
reduce_C_function = np.mean, mincnt=None,
5215+
reduce_C_function = np.mean, mincnt=None, marginals=True,
52165216
**kwargs):
52175217
"""
52185218
call signature::
@@ -5221,7 +5221,7 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
52215221
xscale = 'linear', yscale = 'linear',
52225222
cmap=None, norm=None, vmin=None, vmax=None,
52235223
alpha=1.0, linewidths=None, edgecolors='none'
5224-
reduce_C_function = np.mean, mincnt=None,
5224+
reduce_C_function = np.mean, mincnt=None, marginals=True
52255225
**kwargs)
52265226
52275227
Make a hexagonal binning plot of *x* versus *y*, where *x*,
@@ -5273,6 +5273,11 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
52735273
If not None, only display cells with more than *mincnt*
52745274
number of points in the cell
52755275
5276+
*marginals*: True|False
5277+
if marginals is True, plot the marginal density as
5278+
colormapped rectagles along the bottom of the x-axis and
5279+
left of the y-axis
5280+
52765281
Other keyword arguments controlling color mapping and normalization
52775282
arguments:
52785283
@@ -5320,7 +5325,10 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
53205325
:class:`~matplotlib.collections.PolyCollection` instance; use
53215326
:meth:`~matplotlib.collection.PolyCollection.get_array` on
53225327
this :class:`~matplotlib.collections.PolyCollection` to get
5323-
the counts in each hexagon.
5328+
the counts in each hexagon.. If marginals is True, horizontal
5329+
bar and vertical bar (both PolyCollections) will be attached
5330+
to the return collection as attributes *hbar* and *vbar*
5331+
53245332
53255333
**Example:**
53265334
@@ -5331,8 +5339,10 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
53315339

53325340
self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
53335341

5342+
53345343
x, y, C = cbook.delete_masked_points(x, y, C)
53355344

5345+
53365346
# Set the size of the hexagon grid
53375347
if iterable(gridsize):
53385348
nx, ny = gridsize
@@ -5357,6 +5367,11 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
53575367
xmax += padding
53585368
sx = (xmax-xmin) / nx
53595369
sy = (ymax-ymin) / ny
5370+
5371+
if marginals:
5372+
xorig = x.copy()
5373+
yorig = y.copy()
5374+
53605375
x = (x-xmin)/sx
53615376
y = (y-ymin)/sy
53625377
ix1 = np.round(x).astype(int)
@@ -5496,6 +5511,93 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
54965511

54975512
# add the collection last
54985513
self.add_collection(collection)
5514+
if not marginals:
5515+
return collection
5516+
5517+
5518+
if C is None:
5519+
C = np.ones(len(x))
5520+
5521+
def coarse_bin(x, y, coarse):
5522+
ind = coarse.searchsorted(x).clip(0, len(coarse)-1)
5523+
mus = np.zeros(len(coarse))
5524+
for i in range(len(coarse)):
5525+
mu = reduce_C_function(y[ind==i])
5526+
mus[i] = mu
5527+
return mus
5528+
5529+
coarse = np.linspace(xmin, xmax, gridsize)
5530+
5531+
xcoarse = coarse_bin(xorig, C, coarse)
5532+
valid = ~np.isnan(xcoarse)
5533+
verts, values = [], []
5534+
for i,val in enumerate(xcoarse):
5535+
thismin = coarse[i]
5536+
if i<len(coarse)-1:
5537+
thismax = coarse[i+1]
5538+
else:
5539+
thismax = thismin + np.diff(coarse)[-1]
5540+
5541+
if not valid[i]: continue
5542+
5543+
verts.append([(thismin, 0), (thismin, 0.05), (thismax, 0.05), (thismax, 0)])
5544+
values.append(val)
5545+
5546+
values = np.array(values)
5547+
trans = mtransforms.blended_transform_factory(
5548+
self.transData, self.transAxes)
5549+
5550+
5551+
hbar = mcoll.PolyCollection(verts, transform=trans, edgecolors='face')
5552+
5553+
hbar.set_array(values)
5554+
hbar.set_cmap(cmap)
5555+
hbar.set_norm(norm)
5556+
hbar.set_alpha(alpha)
5557+
hbar.update(kwargs)
5558+
self.add_collection(hbar)
5559+
5560+
coarse = np.linspace(ymin, ymax, gridsize)
5561+
ycoarse = coarse_bin(yorig, C, coarse)
5562+
valid = ~np.isnan(ycoarse)
5563+
verts, values = [], []
5564+
for i,val in enumerate(ycoarse):
5565+
thismin = coarse[i]
5566+
if i<len(coarse)-1:
5567+
thismax = coarse[i+1]
5568+
else:
5569+
thismax = thismin + np.diff(coarse)[-1]
5570+
if not valid[i]: continue
5571+
verts.append([(0, thismin), (0.0, thismax), (0.05, thismax), (0.05, thismin)])
5572+
values.append(val)
5573+
5574+
values = np.array(values)
5575+
5576+
5577+
trans = mtransforms.blended_transform_factory(
5578+
self.transAxes, self.transData)
5579+
5580+
vbar = mcoll.PolyCollection(verts, transform=trans, edgecolors='face')
5581+
vbar.set_array(values)
5582+
vbar.set_cmap(cmap)
5583+
vbar.set_norm(norm)
5584+
vbar.set_alpha(alpha)
5585+
vbar.update(kwargs)
5586+
self.add_collection(vbar)
5587+
5588+
5589+
5590+
collection.hbar = hbar
5591+
collection.vbar = vbar
5592+
5593+
def on_changed(collection):
5594+
hbar.set_cmap(collection.get_cmap())
5595+
hbar.set_clim(collection.get_clim())
5596+
vbar.set_cmap(collection.get_cmap())
5597+
vbar.set_clim(collection.get_clim())
5598+
5599+
collection.callbacksSM.connect('changed', on_changed)
5600+
54995601
return collection
55005602

55015603
hexbin.__doc__ = cbook.dedent(hexbin.__doc__) % martist.kwdocd

setupext.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1066,8 +1066,7 @@ def build_windowing(ext_modules, packages):
10661066
global BUILT_WINDOWING
10671067
if BUILT_WINDOWING: return # only build it if you you haven't already
10681068
module = Extension('matplotlib._windowing',
1069-
['src/_windowing.cpp',
1070-
],
1069+
['src/_windowing.cpp'],
10711070
)
10721071
add_windowing_flags(module)
10731072
ext_modules.append(module)
@@ -1341,7 +1340,7 @@ def build_gdk(ext_modules, packages):
13411340
temp_copy('src/_backend_gdk.c', 'src/backend_gdk.c')
13421341
module = Extension(
13431342
'matplotlib.backends._backend_gdk',
1344-
['src/backend_gdk.c', ],
1343+
['src/backend_gdk.c'],
13451344
libraries = [],
13461345
include_dirs=numpy_inc_dirs,
13471346
)

0 commit comments

Comments
 (0)