|
| 1 | +--- |
| 2 | +jupyter: |
| 3 | + jupytext: |
| 4 | + notebook_metadata_filter: all |
| 5 | + text_representation: |
| 6 | + extension: .md |
| 7 | + format_name: markdown |
| 8 | + format_version: '1.3' |
| 9 | + jupytext_version: 1.13.4 |
| 10 | + kernelspec: |
| 11 | + display_name: Python 3 |
| 12 | + language: python |
| 13 | + name: python3 |
| 14 | + language_info: |
| 15 | + codemirror_mode: |
| 16 | + name: ipython |
| 17 | + version: 3 |
| 18 | + file_extension: .py |
| 19 | + mimetype: text/x-python |
| 20 | + name: python |
| 21 | + nbconvert_exporter: python |
| 22 | + pygments_lexer: ipython3 |
| 23 | + version: 3.8.11 |
| 24 | + plotly: |
| 25 | + description: How to make 2D Histograms in Python with Plotly. |
| 26 | + display_as: statistical |
| 27 | + language: python |
| 28 | + layout: base |
| 29 | + name: 2D Histograms |
| 30 | + order: 5 |
| 31 | + page_type: u-guide |
| 32 | + permalink: python/2D-Histogram/ |
| 33 | + redirect_from: |
| 34 | + - python/2d-histogram/ |
| 35 | + - python/2d-histograms/ |
| 36 | + thumbnail: thumbnail/histogram2d.jpg |
| 37 | +--- |
| 38 | + |
| 39 | +## 2D Histograms or Density Heatmaps |
| 40 | + |
| 41 | +A 2D histogram, also known as a density heatmap, is the 2-dimensional generalization of a [histogram](/python/histograms/) which resembles a [heatmap](/python/heatmaps/) but is computed by grouping a set of points specified by their `x` and `y` coordinates into bins, and applying an aggregation function such as `count` or `sum` (if `z` is provided) to compute the color of the tile representing the bin. This kind of visualization (and the related [2D histogram contour, or density contour](https://plotly.com/python/2d-histogram-contour/)) is often used to manage over-plotting, or situations where showing large data sets as [scatter plots](/python/line-and-scatter/) would result in points overlapping each other and hiding patterns. For data sets of more than a few thousand points, a better approach than the ones listed here would be to [use Plotly with Datashader](/python/datashader/) to precompute the aggregations before displaying the data with Plotly. |
| 42 | + |
| 43 | +## Density Heatmaps with Plotly Express |
| 44 | + |
| 45 | +[Plotly Express](/python/plotly-express/) is the easy-to-use, high-level interface to Plotly, which [operates on a variety of types of data](/python/px-arguments/) and produces [easy-to-style figures](/python/styling-plotly-express/). The Plotly Express function `density_heatmap()` can be used to produce density heatmaps. |
| 46 | + |
| 47 | +```python |
| 48 | +import plotly.express as px |
| 49 | +df = px.data.tips() |
| 50 | + |
| 51 | +fig = px.density_heatmap(df, x="total_bill", y="tip") |
| 52 | +fig.show() |
| 53 | +``` |
| 54 | + |
| 55 | +The number of bins can be controlled with `nbinsx` and `nbinsy` and the [color scale](/python/colorscales/) with `color_continuous_scale`. |
| 56 | + |
| 57 | +```python |
| 58 | +import plotly.express as px |
| 59 | +df = px.data.tips() |
| 60 | + |
| 61 | +fig = px.density_heatmap(df, x="total_bill", y="tip", nbinsx=20, nbinsy=20, color_continuous_scale="Viridis") |
| 62 | +fig.show() |
| 63 | +``` |
| 64 | + |
| 65 | +Marginal plots can be added to visualize the 1-dimensional distributions of the two variables. Here we use a marginal [`histogram`](/python/histograms/). Other allowable values are `violin`, `box` and `rug`. |
| 66 | + |
| 67 | +```python |
| 68 | +import plotly.express as px |
| 69 | +df = px.data.tips() |
| 70 | + |
| 71 | +fig = px.density_heatmap(df, x="total_bill", y="tip", marginal_x="histogram", marginal_y="histogram") |
| 72 | +fig.show() |
| 73 | +``` |
| 74 | + |
| 75 | +Density heatmaps can also be [faceted](/python/facet-plots/): |
| 76 | + |
| 77 | +```python |
| 78 | +import plotly.express as px |
| 79 | +df = px.data.tips() |
| 80 | + |
| 81 | +fig = px.density_heatmap(df, x="total_bill", y="tip", facet_row="sex", facet_col="smoker") |
| 82 | +fig.show() |
| 83 | +``` |
| 84 | + |
| 85 | +### Displaying Text |
| 86 | + |
| 87 | +*New in v5.5* |
| 88 | + |
| 89 | +You can add the `z` values as text using the `text_auto` argument. Setting it to `True` will display the values on the bars, and setting it to a `d3-format` formatting string will control the output format. |
| 90 | + |
| 91 | +```python |
| 92 | +import plotly.express as px |
| 93 | +df = px.data.tips() |
| 94 | + |
| 95 | +fig = px.density_heatmap(df, x="total_bill", y="tip", text_auto=True) |
| 96 | +fig.show() |
| 97 | +``` |
| 98 | + |
| 99 | +### Other aggregation functions than `count` |
| 100 | + |
| 101 | +By passing in a `z` value and a `histfunc`, density heatmaps can perform basic aggregation operations. Here we show average Sepal Length grouped by Petal Length and Petal Width for the Iris dataset. |
| 102 | + |
| 103 | +```python |
| 104 | +import plotly.express as px |
| 105 | +df = px.data.iris() |
| 106 | + |
| 107 | +fig = px.density_heatmap(df, x="petal_length", y="petal_width", z="sepal_length", histfunc="avg") |
| 108 | +fig.show() |
| 109 | +``` |
| 110 | + |
| 111 | +### 2D Histograms with Graph Objects |
| 112 | + |
| 113 | +To build this kind of figure using [graph objects](/python/graph-objects/) without using Plotly Express, we can use the `go.Histogram2d` class. |
| 114 | + |
| 115 | + |
| 116 | +### 2D Histogram of a Bivariate Normal Distribution ### |
| 117 | + |
| 118 | +```python |
| 119 | +import plotly.graph_objects as go |
| 120 | + |
| 121 | +import numpy as np |
| 122 | +np.random.seed(1) |
| 123 | + |
| 124 | +x = np.random.randn(500) |
| 125 | +y = np.random.randn(500)+1 |
| 126 | + |
| 127 | +fig = go.Figure(go.Histogram2d( |
| 128 | + x=x, |
| 129 | + y=y |
| 130 | + )) |
| 131 | +fig.show() |
| 132 | +``` |
| 133 | + |
| 134 | +### 2D Histogram Binning and Styling Options ### |
| 135 | + |
| 136 | +```python |
| 137 | +import plotly.graph_objects as go |
| 138 | + |
| 139 | +import numpy as np |
| 140 | + |
| 141 | +x = np.random.randn(500) |
| 142 | +y = np.random.randn(500)+1 |
| 143 | + |
| 144 | +fig = go.Figure(go.Histogram2d(x=x, y=y, histnorm='probability', |
| 145 | + autobinx=False, |
| 146 | + xbins=dict(start=-3, end=3, size=0.1), |
| 147 | + autobiny=False, |
| 148 | + ybins=dict(start=-2.5, end=4, size=0.1), |
| 149 | + colorscale=[[0, 'rgb(12,51,131)'], [0.25, 'rgb(10,136,186)'], [0.5, 'rgb(242,211,56)'], [0.75, 'rgb(242,143,56)'], [1, 'rgb(217,30,30)']] |
| 150 | + )) |
| 151 | +fig.show() |
| 152 | +``` |
| 153 | +### Sharing bin settings between 2D Histograms |
| 154 | +This example shows how to use [bingroup](https://plotly.com/python/reference/histogram/#histogram-bingroup) attribute to have a compatible bin settings for both histograms. To define `start`, `end` and `size` value of x-axis and y-axis separately, set [ybins](https://plotly.com/python/reference/histogram2dcontour/#histogram2dcontour-ybins) and `xbins`. |
| 155 | + |
| 156 | +```python |
| 157 | +import plotly.graph_objects as go |
| 158 | +from plotly.subplots import make_subplots |
| 159 | + |
| 160 | +fig = make_subplots(2,2) |
| 161 | +fig.add_trace(go.Histogram2d( |
| 162 | + x = [ 1, 2, 2, 3, 4 ], |
| 163 | + y = [ 1, 2, 2, 3, 4 ], |
| 164 | + coloraxis = "coloraxis", |
| 165 | + xbins = {'start':1, 'size':1}), 1,1) |
| 166 | +fig.add_trace(go.Histogram2d( |
| 167 | + x = [ 4, 5, 5, 5, 6 ], |
| 168 | + y = [ 4, 5, 5, 5, 6 ], |
| 169 | + coloraxis = "coloraxis", |
| 170 | + ybins = {'start': 3, 'size': 1}),1,2) |
| 171 | +fig.add_trace(go.Histogram2d( |
| 172 | + x = [ 1, 2, 2, 3, 4 ], |
| 173 | + y = [ 1, 2, 2, 3, 4 ], |
| 174 | + bingroup = 1, |
| 175 | + coloraxis = "coloraxis", |
| 176 | + xbins = {'start':1, 'size':1}), 2,1) |
| 177 | +fig.add_trace(go.Histogram2d( |
| 178 | + x = [ 4, 5, 5, 5, 6 ], |
| 179 | + y = [ 4, 5, 5, 5, 6 ], |
| 180 | + bingroup = 1, |
| 181 | + coloraxis = "coloraxis", |
| 182 | + ybins = {'start': 3, 'size': 1}),2,2) |
| 183 | +fig.show() |
| 184 | +``` |
| 185 | + |
| 186 | +### 2D Histogram Overlaid with a Scatter Chart ### |
| 187 | + |
| 188 | +```python |
| 189 | +import plotly.graph_objects as go |
| 190 | + |
| 191 | +import numpy as np |
| 192 | + |
| 193 | +x0 = np.random.randn(100)/5. + 0.5 # 5. enforces float division |
| 194 | +y0 = np.random.randn(100)/5. + 0.5 |
| 195 | +x1 = np.random.rand(50) |
| 196 | +y1 = np.random.rand(50) + 1.0 |
| 197 | + |
| 198 | +x = np.concatenate([x0, x1]) |
| 199 | +y = np.concatenate([y0, y1]) |
| 200 | + |
| 201 | +fig = go.Figure() |
| 202 | + |
| 203 | +fig.add_trace(go.Scatter( |
| 204 | + x=x0, |
| 205 | + y=y0, |
| 206 | + mode='markers', |
| 207 | + showlegend=False, |
| 208 | + marker=dict( |
| 209 | + symbol='x', |
| 210 | + opacity=0.7, |
| 211 | + color='white', |
| 212 | + size=8, |
| 213 | + line=dict(width=1), |
| 214 | + ) |
| 215 | +)) |
| 216 | +fig.add_trace(go.Scatter( |
| 217 | + x=x1, |
| 218 | + y=y1, |
| 219 | + mode='markers', |
| 220 | + showlegend=False, |
| 221 | + marker=dict( |
| 222 | + symbol='circle', |
| 223 | + opacity=0.7, |
| 224 | + color='white', |
| 225 | + size=8, |
| 226 | + line=dict(width=1), |
| 227 | + ) |
| 228 | +)) |
| 229 | +fig.add_trace(go.Histogram2d( |
| 230 | + x=x, |
| 231 | + y=y, |
| 232 | + colorscale='YlGnBu', |
| 233 | + zmax=10, |
| 234 | + nbinsx=14, |
| 235 | + nbinsy=14, |
| 236 | + zauto=False, |
| 237 | +)) |
| 238 | + |
| 239 | +fig.update_layout( |
| 240 | + xaxis=dict( ticks='', showgrid=False, zeroline=False, nticks=20 ), |
| 241 | + yaxis=dict( ticks='', showgrid=False, zeroline=False, nticks=20 ), |
| 242 | + autosize=False, |
| 243 | + height=550, |
| 244 | + width=550, |
| 245 | + hovermode='closest', |
| 246 | + |
| 247 | +) |
| 248 | + |
| 249 | +fig.show() |
| 250 | +``` |
| 251 | + |
| 252 | +### Text on 2D Histogram Points |
| 253 | + |
| 254 | +In this example we add text to 2D Histogram points. We use the values from the `z` attribute for the text. |
| 255 | + |
| 256 | +```python |
| 257 | +import plotly.graph_objects as go |
| 258 | +from plotly import data |
| 259 | + |
| 260 | +df = data.tips() |
| 261 | + |
| 262 | +fig = go.Figure(go.Histogram2d( |
| 263 | + x=df.total_bill, |
| 264 | + y=df.tip, |
| 265 | + texttemplate= "%{z}" |
| 266 | + )) |
| 267 | + |
| 268 | +fig.show() |
| 269 | +``` |
| 270 | + |
| 271 | +#### Reference |
| 272 | +See https://plotly.com/python/reference/histogram2d/ for more information and chart attribute options! |
0 commit comments