|
1 | 1 | """
|
2 |
| -============ |
3 |
| -Scatter Hist |
4 |
| -============ |
| 2 | +================= |
| 3 | +Scatter Histogram |
| 4 | +================= |
5 | 5 |
|
6 |
| -Creates histogram from scatter plot |
7 |
| -and adds them to the sides of the plot. |
| 6 | +Show the marginal distributions of a scatter as histograms at the sides of |
| 7 | +the plot. |
8 | 8 |
|
| 9 | +For a nice alignment of the main axes with the marginals, two options are shown |
| 10 | +below. |
| 11 | +
|
| 12 | +* the axes positions are defined in terms of rectangles in figure coordinates |
| 13 | +* the axes positions are defined via a gridspec |
| 14 | +
|
| 15 | +An alternative method to produce a similar figure using the ``axes_grid1`` |
| 16 | +toolkit is shown in the |
| 17 | +:doc:`/gallery/axes_grid1/scatter_hist_locatable_axes` example. |
| 18 | +
|
| 19 | +Let us first define a function that takes x and y data as input, as well |
| 20 | +as three axes, the main axes for the scatter, and two marginal axes. It will |
| 21 | +then create the scatter and histograms inside the provided axes. |
9 | 22 | """
|
| 23 | + |
10 | 24 | import numpy as np
|
11 | 25 | import matplotlib.pyplot as plt
|
12 |
| -from matplotlib.ticker import NullFormatter |
13 | 26 |
|
14 | 27 | # Fixing random state for reproducibility
|
15 | 28 | np.random.seed(19680801)
|
16 |
| - |
17 |
| - |
18 |
| -# the random data |
| 29 | +# some random data |
19 | 30 | x = np.random.randn(1000)
|
20 | 31 | y = np.random.randn(1000)
|
21 | 32 |
|
22 |
| -nullfmt = NullFormatter() # no labels |
| 33 | + |
| 34 | +def scatter_hist(x, y, axScatter, axHistx, axHisty): |
| 35 | + # no labels |
| 36 | + axHistx.tick_params(axis="x", labelbottom=False) |
| 37 | + axHisty.tick_params(axis="y", labelleft=False) |
| 38 | + |
| 39 | + # the scatter plot: |
| 40 | + axScatter.scatter(x, y) |
| 41 | + |
| 42 | + # now determine nice limits by hand: |
| 43 | + binwidth = 0.25 |
| 44 | + xymax = max(np.max(np.abs(x)), np.max(np.abs(y))) |
| 45 | + lim = (int(xymax/binwidth) + 1) * binwidth |
| 46 | + |
| 47 | + bins = np.arange(-lim, lim + binwidth, binwidth) |
| 48 | + axHistx.hist(x, bins=bins) |
| 49 | + axHisty.hist(y, bins=bins, orientation='horizontal') |
| 50 | + |
| 51 | + |
| 52 | +############################################################################# |
| 53 | +# |
| 54 | +# Axes in figure coordinates |
| 55 | +# -------------------------- |
| 56 | +# |
| 57 | +# To define the axes positions `Figure.add_axes` is provided with a rectangle |
| 58 | +# ``[left, bottom, width, height]`` in figure coordinates. The marginal axes |
| 59 | +# share one dimension with the main axes. |
23 | 60 |
|
24 | 61 | # definitions for the axes
|
25 | 62 | left, width = 0.1, 0.65
|
|
30 | 67 | rect_histx = [left, bottom_h, width, 0.2]
|
31 | 68 | rect_histy = [left_h, bottom, 0.2, height]
|
32 | 69 |
|
33 |
| -# start with a rectangular Figure |
34 |
| -plt.figure(figsize=(8, 8)) |
| 70 | +# start with a square Figure |
| 71 | +fig = plt.figure(figsize=(8, 8)) |
| 72 | + |
| 73 | +axScatter = fig.add_axes(rect_scatter) |
| 74 | +axHistx = fig.add_axes(rect_histx, sharex=axScatter) |
| 75 | +axHisty = fig.add_axes(rect_histy, sharey=axScatter) |
35 | 76 |
|
36 |
| -axScatter = plt.axes(rect_scatter) |
37 |
| -axHistx = plt.axes(rect_histx) |
38 |
| -axHisty = plt.axes(rect_histy) |
| 77 | +# use the previously defined function |
| 78 | +scatter_hist(x, y, axScatter, axHistx, axHisty) |
| 79 | + |
| 80 | +plt.show() |
39 | 81 |
|
40 |
| -# no labels |
41 |
| -axHistx.xaxis.set_major_formatter(nullfmt) |
42 |
| -axHisty.yaxis.set_major_formatter(nullfmt) |
43 | 82 |
|
44 |
| -# the scatter plot: |
45 |
| -axScatter.scatter(x, y) |
| 83 | +############################################################################# |
| 84 | +# |
| 85 | +# Using a gridspec |
| 86 | +# ---------------- |
| 87 | +# |
| 88 | +# We may equally define a gridspec with unequal width- and height-ratios to |
| 89 | +# achieve desired layout. Also see the :doc:`/tutorials/intermediate/gridspec` |
| 90 | +# tutorial. |
46 | 91 |
|
47 |
| -# now determine nice limits by hand: |
48 |
| -binwidth = 0.25 |
49 |
| -xymax = max(np.max(np.abs(x)), np.max(np.abs(y))) |
50 |
| -lim = (int(xymax/binwidth) + 1) * binwidth |
| 92 | +# start with a square Figure |
| 93 | +fig = plt.figure(figsize=(8, 8)) |
51 | 94 |
|
52 |
| -axScatter.set_xlim((-lim, lim)) |
53 |
| -axScatter.set_ylim((-lim, lim)) |
| 95 | +# Add a gridspec with two rows and two columns and a ratio of 2 to 7 between |
| 96 | +# the size of the marginal axes and the main axes in both directions. |
| 97 | +# Also adjust the subplot parameters for a square plot. |
| 98 | +gs = fig.add_gridspec(2, 2, width_ratios=(7, 2), height_ratios=(2, 7), |
| 99 | + left=0.1, right=0.9, bottom=0.1, top=0.9, |
| 100 | + wspace=0.05, hspace=0.05) |
54 | 101 |
|
55 |
| -bins = np.arange(-lim, lim + binwidth, binwidth) |
56 |
| -axHistx.hist(x, bins=bins) |
57 |
| -axHisty.hist(y, bins=bins, orientation='horizontal') |
| 102 | +axScatter = fig.add_subplot(gs[1, 0]) |
| 103 | +axHistx = fig.add_subplot(gs[0, 0], sharex=axScatter) |
| 104 | +axHisty = fig.add_subplot(gs[1, 1], sharey=axScatter) |
58 | 105 |
|
59 |
| -axHistx.set_xlim(axScatter.get_xlim()) |
60 |
| -axHisty.set_ylim(axScatter.get_ylim()) |
| 106 | +# use the previously defined function |
| 107 | +scatter_hist(x, y, axScatter, axHistx, axHisty) |
61 | 108 |
|
62 | 109 | plt.show()
|
| 110 | + |
| 111 | + |
| 112 | +############################################################################# |
| 113 | +# |
| 114 | +# ------------ |
| 115 | +# |
| 116 | +# References |
| 117 | +# """""""""" |
| 118 | +# |
| 119 | +# The use of the following functions, methods and classes is shown |
| 120 | +# in this example: |
| 121 | + |
| 122 | +import matplotlib |
| 123 | +matplotlib.figure.Figure.add_axes |
| 124 | +matplotlib.figure.Figure.add_subplot |
| 125 | +matplotlib.figure.Figure.add_gridspec |
| 126 | +matplotlib.axes.Axes.scatter |
| 127 | +matplotlib.axes.Axes.hist |
0 commit comments