kdiagram.plot.uncertainty.plot_polar_heatmap

kdiagram.plot.uncertainty.plot_polar_heatmap(df, r_col, theta_col, *, acov='default', theta_period=None, r_bins=20, theta_bins=36, statistic='count', cbar_label=None, title=None, figsize=(8, 8), cmap='viridis', mask_angle=False, mask_radius=False, show_grid=True, grid_props=None, savefig=None, dpi=300, ax=None)[source]

Plot a polar heatmap to visualize a 2D density distribution.

This function creates a heatmap on a polar grid to show the concentration of data points based on two variables: one mapped to the radius and another to the angle. It is highly effective for identifying patterns and correlations between a linear metric and a cyclical or ordered feature.

Parameters:
dfpd.DataFrame

The input DataFrame containing the data.

r_colstr

Name of the column to be used for the radial coordinate.

theta_colstr

Name of the column to be used for the angular coordinate.

acov{‘default’, ‘half_circle’, ‘quarter_circle’, ‘eighth_circle’},

default=’default’ Angular coverage of the plot:

  • 'default': full circle, \(2\pi\)

  • 'half_circle': \(\pi\)

  • 'quarter_circle': \(\pi/2\)

  • 'eighth_circle': \(\pi/4\)

(Value is case-insensitive; invalid values fall back to full circle with a warning.)

theta_periodfloat, optional

The period of the cyclical data in theta_col. For example, if theta_col represents the hour of the day, theta_period should be 24. If provided, the angle is mapped to [0, 2*pi] based on this cycle. If None, the angle is scaled from the data’s min/max values.

r_binsint, default=20

The number of bins to create along the radial axis.

theta_binsint, default=36

The number of bins to create around the angular axis.

statisticstr, default=’count’

The statistic to compute in each bin. Currently, only ‘count’ is supported, which corresponds to a 2D histogram.

cbar_labelstr, optional

Custom label for the color bar. If None, it defaults to the value of statistic.

titlestr, optional

The title for the plot. If None, a default is generated.

figsizetuple of (float, float), default=(8, 8)

Figure size in inches.

cmapstr, default=’viridis’

Matplotlib colormap for the heatmap.

mask_anglebool, default=False

If True, hide the angular tick labels (e.g., degrees).

mask_radiusbool, default=False

If True, hide the radial tick labels.

show_gridbool, default=True

Toggle gridlines via the package helper set_axis_grid.

grid_propsdict, optional

Keyword arguments passed to set_axis_grid for grid customization.

savefigstr, optional

If provided, save the figure to this path; otherwise the plot is shown interactively.

dpiint, default=300

Resolution for the saved figure.

Returns:
axmatplotlib.axes.Axes or None

The Matplotlib Axes object containing the plot, or None if the plot could not be generated.

Parameters:
  • df (DataFrame)

  • r_col (str)

  • theta_col (str)

  • acov (Literal['default', 'half_circle', 'quarter_circle', 'eighth_circle'])

  • theta_period (float | None)

  • r_bins (int)

  • theta_bins (int)

  • statistic (str)

  • cbar_label (str | None)

  • title (str | None)

  • figsize (tuple[float, float])

  • cmap (str)

  • mask_angle (bool)

  • mask_radius (bool)

  • show_grid (bool)

  • grid_props (dict[str, Any] | None)

  • savefig (str | None)

  • dpi (int)

  • ax (Axes | None)

Return type:

Axes | None

See also

matplotlib.pyplot.pcolormesh

Draw a pseudocolor plot with a nonregular rectangular grid.

numpy.histogram2d

Compute the bi-dimensional histogram of two data samples.

Notes

The heatmap is constructed by binning the 2D polar space and counting the number of data points that fall into each bin.

  1. Coordinate Mapping:

    • The radial data from r_col is used directly.

    • The angular data from theta_col, \(\theta_{data}\), is converted to radians in the range \([0, 2\pi]\). If theta_period (\(P\)) is given, the mapping is:

      (1)\[\theta_{rad} = \left( \frac{\theta_{data} \pmod P}{P} \right) \cdot 2\pi\]

      Otherwise, it is linearly scaled from the data’s range.

  2. Binning: The data space is divided into a grid of polar bins defined by r_bins and theta_bins. A 2D histogram is then computed, where the value of each cell \(C_{ij}\) is the number of data points \((r, \theta)\) that fall within the radial and angular bounds of that cell.

  3. Visualization: The resulting count matrix \(\mathbf{C}\) is visualized using pcolormesh, where the color of each cell corresponds to its count, creating the heatmap effect. See [1] for Matplotlib details.

References

Examples

>>> import numpy as np
>>> import pandas as pd
>>> from kdiagram.plot.uncertainty import plot_polar_heatmap
>>>
>>> # Simulate weather data with a daily cycle
>>> np.random.seed(42)
>>> n_points = 5000
>>> # Simulate hour of day with more events in the afternoon
>>> hour = np.concatenate([
...     np.random.normal(15, 2, int(n_points * 0.7)),
...     np.random.normal(5, 2, int(n_points * 0.3))
... ]) % 24
>>> # Simulate rainfall, correlated with afternoon hours
>>> rainfall = np.random.gamma(2, 5, n_points) + \
...     (hour > 12) * np.random.gamma(3, 5, n_points)
>>>
>>> df_weather = pd.DataFrame({'hour': hour, 'rainfall_mm': rainfall})
>>>
>>> # Generate the polar heatmap
>>> ax = plot_polar_heatmap(
...     df=df_weather,
...     r_col='rainfall_mm',
...     theta_col='hour',
...     theta_period=24,
...     r_bins=25,
...     theta_bins=24,
...     cmap='plasma',
...     title='Rainfall Intensity vs. Hour of Day',
...     cbar_label='Event Count'
... )