@@ -5212,7 +5212,7 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
5212
5212
xscale = 'linear' , yscale = 'linear' ,
5213
5213
cmap = None , norm = None , vmin = None , vmax = None ,
5214
5214
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 ,
5216
5216
** kwargs ):
5217
5217
"""
5218
5218
call signature::
@@ -5221,7 +5221,7 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
5221
5221
xscale = 'linear', yscale = 'linear',
5222
5222
cmap=None, norm=None, vmin=None, vmax=None,
5223
5223
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
5225
5225
**kwargs)
5226
5226
5227
5227
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,
5273
5273
If not None, only display cells with more than *mincnt*
5274
5274
number of points in the cell
5275
5275
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
+
5276
5281
Other keyword arguments controlling color mapping and normalization
5277
5282
arguments:
5278
5283
@@ -5320,7 +5325,10 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
5320
5325
:class:`~matplotlib.collections.PolyCollection` instance; use
5321
5326
:meth:`~matplotlib.collection.PolyCollection.get_array` on
5322
5327
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
+
5324
5332
5325
5333
**Example:**
5326
5334
@@ -5331,8 +5339,10 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
5331
5339
5332
5340
self ._process_unit_info (xdata = x , ydata = y , kwargs = kwargs )
5333
5341
5342
+
5334
5343
x , y , C = cbook .delete_masked_points (x , y , C )
5335
5344
5345
+
5336
5346
# Set the size of the hexagon grid
5337
5347
if iterable (gridsize ):
5338
5348
nx , ny = gridsize
@@ -5357,6 +5367,11 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
5357
5367
xmax += padding
5358
5368
sx = (xmax - xmin ) / nx
5359
5369
sy = (ymax - ymin ) / ny
5370
+
5371
+ if marginals :
5372
+ xorig = x .copy ()
5373
+ yorig = y .copy ()
5374
+
5360
5375
x = (x - xmin )/ sx
5361
5376
y = (y - ymin )/ sy
5362
5377
ix1 = np .round (x ).astype (int )
@@ -5496,6 +5511,93 @@ def hexbin(self, x, y, C = None, gridsize = 100, bins = None,
5496
5511
5497
5512
# add the collection last
5498
5513
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
+
5499
5601
return collection
5500
5602
5501
5603
hexbin .__doc__ = cbook .dedent (hexbin .__doc__ ) % martist .kwdocd
0 commit comments