mgplot.fill_between_plot
Plot a filled region between two bounds.
1"""Plot a filled region between two bounds.""" 2 3from collections.abc import Callable 4from typing import Final, NotRequired, Unpack 5 6from matplotlib.axes import Axes 7from pandas import DataFrame 8 9from mgplot.axis_utils import map_periodindex, set_labels 10from mgplot.keyword_checking import BaseKwargs, report_kwargs, validate_kwargs 11from mgplot.settings import get_setting 12from mgplot.utilities import check_clean_timeseries, constrain_data, get_axes 13 14# --- constants 15ME: Final[str] = "fill_between_plot" 16REQUIRED_COLUMNS: Final[int] = 2 17DEFAULT_COLOR: Final[str] = "steelblue" 18DEFAULT_ALPHA: Final[float] = 0.3 19 20 21class FillBetweenKwargs(BaseKwargs): 22 """Keyword arguments for the fill_between_plot function.""" 23 24 ax: NotRequired[Axes | None] 25 color: NotRequired[str] 26 alpha: NotRequired[float] 27 label: NotRequired[str | None] 28 linewidth: NotRequired[float] 29 edgecolor: NotRequired[str | None] 30 zorder: NotRequired[int | float] 31 plot_from: NotRequired[int | None] 32 max_ticks: NotRequired[int] 33 tick_relabel: NotRequired[Callable[[str], str]] 34 35 36def fill_between_plot(data: DataFrame, **kwargs: Unpack[FillBetweenKwargs]) -> Axes: 37 """Plot a filled region between lower and upper bounds. 38 39 Args: 40 data: DataFrame - A two-column DataFrame with PeriodIndex. 41 The first column is the lower bound, the second is the upper bound. 42 kwargs: FillBetweenKwargs - keyword arguments for the plot. 43 44 Returns: 45 Axes - matplotlib Axes object. 46 47 Raises: 48 TypeError: If data is not a DataFrame. 49 ValueError: If data does not have exactly two columns. 50 51 """ 52 # --- validate inputs 53 report_kwargs(caller=ME, **kwargs) 54 validate_kwargs(schema=FillBetweenKwargs, caller=ME, **kwargs) 55 56 if not isinstance(data, DataFrame): 57 raise TypeError(f"data must be a DataFrame for {ME}()") 58 59 if len(data.columns) != REQUIRED_COLUMNS: 60 raise ValueError(f"data must have exactly two columns for {ME}(), got {len(data.columns)}") 61 62 # --- check and constrain data 63 data = check_clean_timeseries(data, ME) 64 data, kwargs_d = constrain_data(data, **kwargs) 65 66 # --- handle PeriodIndex conversion 67 saved_pi = map_periodindex(data) 68 if saved_pi is not None: 69 data = saved_pi[0] 70 71 # --- get axes 72 axes, kwargs_d = get_axes(**kwargs_d) 73 74 if data.empty or data.isna().all().all(): 75 print(f"Warning: No data to plot in {ME}().") 76 return axes 77 78 # --- extract bounds 79 lower = data.iloc[:, 0] 80 upper = data.iloc[:, 1] 81 82 # --- extract plot arguments 83 color = kwargs_d.get("color", DEFAULT_COLOR) 84 alpha = kwargs_d.get("alpha", DEFAULT_ALPHA) 85 label = kwargs_d.get("label", None) 86 linewidth = kwargs_d.get("linewidth", 0) 87 edgecolor = kwargs_d.get("edgecolor", None) 88 zorder = kwargs_d.get("zorder", None) 89 90 # --- plot 91 axes.fill_between( 92 data.index, 93 lower, 94 upper, 95 color=color, 96 alpha=alpha, 97 label=label, 98 linewidth=linewidth, 99 edgecolor=edgecolor, 100 zorder=zorder, 101 ) 102 103 # --- set axis labels 104 if saved_pi is not None: 105 set_labels( 106 axes, 107 saved_pi[1], 108 kwargs_d.get("max_ticks", get_setting("max_ticks")), 109 tick_relabel=kwargs_d.get("tick_relabel"), 110 ) 111 112 return axes
ME: Final[str] =
'fill_between_plot'
REQUIRED_COLUMNS: Final[int] =
2
DEFAULT_COLOR: Final[str] =
'steelblue'
DEFAULT_ALPHA: Final[float] =
0.3
class
FillBetweenKwargs(mgplot.keyword_checking.BaseKwargs):
22class FillBetweenKwargs(BaseKwargs): 23 """Keyword arguments for the fill_between_plot function.""" 24 25 ax: NotRequired[Axes | None] 26 color: NotRequired[str] 27 alpha: NotRequired[float] 28 label: NotRequired[str | None] 29 linewidth: NotRequired[float] 30 edgecolor: NotRequired[str | None] 31 zorder: NotRequired[int | float] 32 plot_from: NotRequired[int | None] 33 max_ticks: NotRequired[int] 34 tick_relabel: NotRequired[Callable[[str], str]]
Keyword arguments for the fill_between_plot function.
def
fill_between_plot( data: pandas.DataFrame, **kwargs: Unpack[FillBetweenKwargs]) -> matplotlib.axes._axes.Axes:
37def fill_between_plot(data: DataFrame, **kwargs: Unpack[FillBetweenKwargs]) -> Axes: 38 """Plot a filled region between lower and upper bounds. 39 40 Args: 41 data: DataFrame - A two-column DataFrame with PeriodIndex. 42 The first column is the lower bound, the second is the upper bound. 43 kwargs: FillBetweenKwargs - keyword arguments for the plot. 44 45 Returns: 46 Axes - matplotlib Axes object. 47 48 Raises: 49 TypeError: If data is not a DataFrame. 50 ValueError: If data does not have exactly two columns. 51 52 """ 53 # --- validate inputs 54 report_kwargs(caller=ME, **kwargs) 55 validate_kwargs(schema=FillBetweenKwargs, caller=ME, **kwargs) 56 57 if not isinstance(data, DataFrame): 58 raise TypeError(f"data must be a DataFrame for {ME}()") 59 60 if len(data.columns) != REQUIRED_COLUMNS: 61 raise ValueError(f"data must have exactly two columns for {ME}(), got {len(data.columns)}") 62 63 # --- check and constrain data 64 data = check_clean_timeseries(data, ME) 65 data, kwargs_d = constrain_data(data, **kwargs) 66 67 # --- handle PeriodIndex conversion 68 saved_pi = map_periodindex(data) 69 if saved_pi is not None: 70 data = saved_pi[0] 71 72 # --- get axes 73 axes, kwargs_d = get_axes(**kwargs_d) 74 75 if data.empty or data.isna().all().all(): 76 print(f"Warning: No data to plot in {ME}().") 77 return axes 78 79 # --- extract bounds 80 lower = data.iloc[:, 0] 81 upper = data.iloc[:, 1] 82 83 # --- extract plot arguments 84 color = kwargs_d.get("color", DEFAULT_COLOR) 85 alpha = kwargs_d.get("alpha", DEFAULT_ALPHA) 86 label = kwargs_d.get("label", None) 87 linewidth = kwargs_d.get("linewidth", 0) 88 edgecolor = kwargs_d.get("edgecolor", None) 89 zorder = kwargs_d.get("zorder", None) 90 91 # --- plot 92 axes.fill_between( 93 data.index, 94 lower, 95 upper, 96 color=color, 97 alpha=alpha, 98 label=label, 99 linewidth=linewidth, 100 edgecolor=edgecolor, 101 zorder=zorder, 102 ) 103 104 # --- set axis labels 105 if saved_pi is not None: 106 set_labels( 107 axes, 108 saved_pi[1], 109 kwargs_d.get("max_ticks", get_setting("max_ticks")), 110 tick_relabel=kwargs_d.get("tick_relabel"), 111 ) 112 113 return axes
Plot a filled region between lower and upper bounds.
Args: data: DataFrame - A two-column DataFrame with PeriodIndex. The first column is the lower bound, the second is the upper bound. kwargs: FillBetweenKwargs - keyword arguments for the plot.
Returns: Axes - matplotlib Axes object.
Raises: TypeError: If data is not a DataFrame. ValueError: If data does not have exactly two columns.