mgplot.bar_plot
bar_plot.py This module contains functions to create bar plots using Matplotlib. Note: bar plots in Matplotlib are not the same as bar charts in other libraries. Bar plots are used to represent categorical data with rectangular bars. As a result, bar plots and line plots typically cannot be plotted on the same axes.
1""" 2bar_plot.py 3This module contains functions to create bar plots using Matplotlib. 4Note: bar plots in Matplotlib are not the same as bar charts in other 5libraries. Bar plots are used to represent categorical data with 6rectangular bars. As a result, bar plots and line plots typically 7cannot be plotted on the same axes. 8""" 9 10# --- imports 11from typing import Any, Final 12from collections.abc import Sequence 13from pandas import DataFrame, period_range, PeriodIndex 14import matplotlib.pyplot as plt 15from matplotlib.pyplot import Axes 16 17from mgplot.settings import DataT, get_setting 18from mgplot.utilities import apply_defaults, get_color_list, get_axes, constrain_data 19from mgplot.kw_type_checking import ( 20 ExpectedTypeDict, 21 validate_expected, 22 report_kwargs, 23 validate_kwargs, 24) 25from mgplot.date_utils import set_labels 26 27 28# --- constants 29BAR_KW_TYPES: Final[ExpectedTypeDict] = { 30 "color": (str, Sequence, (str,)), 31 "width": float, 32 "stacked": bool, 33 "rotation": (int, float), 34 "bar_legend": bool, 35 "max_ticks": int, 36 "plot_from": (int, PeriodIndex, type(None)), 37} 38validate_expected(BAR_KW_TYPES, "bar_plot") 39 40 41# --- functions 42def bar_plot( 43 data: DataT, 44 **kwargs, 45) -> Axes: 46 """ 47 Create a bar plot from the given data. Each column in the DataFrame 48 will be stacked on top of each other, with positive values above 49 zero and negative values below zero. 50 51 Parameters 52 - data: Series - The data to plot. Can be a DataFrame or a Series. 53 - **kwargs: dict Additional keyword arguments for customization. 54 - color: list - A list of colors for the each series (column) in the DataFrame. 55 - width: float - The width of the bars. 56 - stacked: bool - If True, the bars will be stacked. 57 - rotation: int - The rotation angle in degrees for the x-axis labels. 58 - bar_legend: bool - If True, show the legend. Defaults to True 59 if more than one bar being plotted for each category. 60 - "max_ticks": int - The maximum number of ticks on the x-axis, 61 (this option only applies to PeriodIndex data.). 62 63 Note: This function does not assume all data is timeseries with a PeriodIndex, 64 65 Returns 66 - axes: Axes - The axes for the plot. 67 """ 68 69 # --- check the kwargs 70 me = "bar_plot" 71 report_kwargs(called_from=me, **kwargs) 72 validate_kwargs(BAR_KW_TYPES, me, **kwargs) 73 74 # --- get the data 75 # no call to check_clean_timeseries here, as bar plots are not 76 # necessarily timeseries data. If the data is a Series, it will be 77 # converted to a DataFrame with a single column. 78 df = DataFrame(data) # really we are only plotting DataFrames 79 df, kwargs = constrain_data(df, **kwargs) 80 item_count = len(df.columns) 81 82 defaults: dict[str, Any] = { 83 "color": get_color_list(item_count), 84 "width": get_setting("bar_width"), 85 "stacked": False, 86 "rotation": 90, 87 "bar_legend": (item_count > 1), 88 "max_ticks": 10, 89 } 90 bar_args, remaining_kwargs = apply_defaults(item_count, defaults, kwargs) 91 92 # --- plot the data 93 axes, _rkwargs = get_axes(**remaining_kwargs) 94 95 df.plot.bar( 96 ax=axes, 97 color=bar_args["color"], 98 stacked=bar_args["stacked"][0], 99 width=bar_args["width"][0], 100 legend=bar_args["bar_legend"][0], 101 ) 102 103 rotate_labels = True 104 if isinstance(df.index, PeriodIndex): 105 complete = period_range( 106 start=df.index.min(), end=df.index.max(), freq=df.index.freqstr 107 ) 108 if complete.equals(df.index): 109 # if the index is complete, we can set the labels 110 set_labels(axes, df.index, bar_args["max_ticks"][0]) 111 rotate_labels = False 112 113 if rotate_labels: 114 plt.xticks(rotation=bar_args["rotation"][0]) 115 116 return axes
BAR_KW_TYPES: Final[ExpectedTypeDict] =
{'color': (<class 'str'>, <class 'collections.abc.Sequence'>, (<class 'str'>,)), 'width': <class 'float'>, 'stacked': <class 'bool'>, 'rotation': (<class 'int'>, <class 'float'>), 'bar_legend': <class 'bool'>, 'max_ticks': <class 'int'>, 'plot_from': (<class 'int'>, <class 'pandas.core.indexes.period.PeriodIndex'>, <class 'NoneType'>)}
def
bar_plot(data: ~DataT, **kwargs) -> matplotlib.axes._axes.Axes:
43def bar_plot( 44 data: DataT, 45 **kwargs, 46) -> Axes: 47 """ 48 Create a bar plot from the given data. Each column in the DataFrame 49 will be stacked on top of each other, with positive values above 50 zero and negative values below zero. 51 52 Parameters 53 - data: Series - The data to plot. Can be a DataFrame or a Series. 54 - **kwargs: dict Additional keyword arguments for customization. 55 - color: list - A list of colors for the each series (column) in the DataFrame. 56 - width: float - The width of the bars. 57 - stacked: bool - If True, the bars will be stacked. 58 - rotation: int - The rotation angle in degrees for the x-axis labels. 59 - bar_legend: bool - If True, show the legend. Defaults to True 60 if more than one bar being plotted for each category. 61 - "max_ticks": int - The maximum number of ticks on the x-axis, 62 (this option only applies to PeriodIndex data.). 63 64 Note: This function does not assume all data is timeseries with a PeriodIndex, 65 66 Returns 67 - axes: Axes - The axes for the plot. 68 """ 69 70 # --- check the kwargs 71 me = "bar_plot" 72 report_kwargs(called_from=me, **kwargs) 73 validate_kwargs(BAR_KW_TYPES, me, **kwargs) 74 75 # --- get the data 76 # no call to check_clean_timeseries here, as bar plots are not 77 # necessarily timeseries data. If the data is a Series, it will be 78 # converted to a DataFrame with a single column. 79 df = DataFrame(data) # really we are only plotting DataFrames 80 df, kwargs = constrain_data(df, **kwargs) 81 item_count = len(df.columns) 82 83 defaults: dict[str, Any] = { 84 "color": get_color_list(item_count), 85 "width": get_setting("bar_width"), 86 "stacked": False, 87 "rotation": 90, 88 "bar_legend": (item_count > 1), 89 "max_ticks": 10, 90 } 91 bar_args, remaining_kwargs = apply_defaults(item_count, defaults, kwargs) 92 93 # --- plot the data 94 axes, _rkwargs = get_axes(**remaining_kwargs) 95 96 df.plot.bar( 97 ax=axes, 98 color=bar_args["color"], 99 stacked=bar_args["stacked"][0], 100 width=bar_args["width"][0], 101 legend=bar_args["bar_legend"][0], 102 ) 103 104 rotate_labels = True 105 if isinstance(df.index, PeriodIndex): 106 complete = period_range( 107 start=df.index.min(), end=df.index.max(), freq=df.index.freqstr 108 ) 109 if complete.equals(df.index): 110 # if the index is complete, we can set the labels 111 set_labels(axes, df.index, bar_args["max_ticks"][0]) 112 rotate_labels = False 113 114 if rotate_labels: 115 plt.xticks(rotation=bar_args["rotation"][0]) 116 117 return axes
Create a bar plot from the given data. Each column in the DataFrame will be stacked on top of each other, with positive values above zero and negative values below zero.
Parameters
- data: Series - The data to plot. Can be a DataFrame or a Series.
- **kwargs: dict Additional keyword arguments for customization.
- color: list - A list of colors for the each series (column) in the DataFrame.
- width: float - The width of the bars.
- stacked: bool - If True, the bars will be stacked.
- rotation: int - The rotation angle in degrees for the x-axis labels.
- bar_legend: bool - If True, show the legend. Defaults to True if more than one bar being plotted for each category.
- "max_ticks": int - The maximum number of ticks on the x-axis, (this option only applies to PeriodIndex data.).
Note: This function does not assume all data is timeseries with a PeriodIndex,
Returns
- axes: Axes - The axes for the plot.