Spaces:
Paused
Paused
| """gr.BarPlot() component.""" | |
| from __future__ import annotations | |
| import warnings | |
| from collections.abc import Callable, Sequence | |
| from typing import TYPE_CHECKING, Any, Literal | |
| from gradio_client.documentation import document | |
| from gradio.components.base import Component | |
| from gradio.components.plot import AltairPlot, AltairPlotData, Plot | |
| if TYPE_CHECKING: | |
| import pandas as pd | |
| from gradio.components import Timer | |
| class BarPlot(Plot): | |
| """ | |
| Creates a bar plot component to display data from a pandas DataFrame (as output). As this component does | |
| not accept user input, it is rarely used as an input component. | |
| Demos: bar_plot | |
| """ | |
| data_model = AltairPlotData | |
| def __init__( | |
| self, | |
| value: pd.DataFrame | Callable | None = None, | |
| x: str | None = None, | |
| y: str | None = None, | |
| *, | |
| color: str | None = None, | |
| vertical: bool = True, | |
| group: str | None = None, | |
| title: str | None = None, | |
| tooltip: list[str] | str | None = None, | |
| x_title: str | None = None, | |
| y_title: str | None = None, | |
| x_label_angle: float | None = None, | |
| y_label_angle: float | None = None, | |
| color_legend_title: str | None = None, | |
| group_title: str | None = None, | |
| color_legend_position: Literal[ | |
| "left", | |
| "right", | |
| "top", | |
| "bottom", | |
| "top-left", | |
| "top-right", | |
| "bottom-left", | |
| "bottom-right", | |
| "none", | |
| ] | |
| | None = None, | |
| height: int | None = None, | |
| width: int | None = None, | |
| y_lim: list[int] | None = None, | |
| caption: str | None = None, | |
| interactive: bool | None = True, | |
| label: str | None = None, | |
| show_label: bool | None = None, | |
| container: bool = True, | |
| scale: int | None = None, | |
| min_width: int = 160, | |
| every: Timer | float | None = None, | |
| inputs: Component | Sequence[Component] | set[Component] | None = None, | |
| visible: bool = True, | |
| elem_id: str | None = None, | |
| elem_classes: list[str] | str | None = None, | |
| render: bool = True, | |
| key: int | str | None = None, | |
| sort: Literal["x", "y", "-x", "-y"] | None = None, | |
| show_actions_button: bool = False, | |
| ): | |
| """ | |
| Parameters: | |
| value: The pandas dataframe containing the data to display in a scatter plot. If a callable is provided, the function will be called whenever the app loads to set the initial value of the plot. | |
| x: Column corresponding to the x axis. | |
| y: Column corresponding to the y axis. | |
| color: The column to determine the bar color. Must be categorical (discrete values). | |
| vertical: If True, the bars will be displayed vertically. If False, the x and y axis will be switched, displaying the bars horizontally. Default is True. | |
| group: The column with which to split the overall plot into smaller subplots. | |
| title: The title to display on top of the chart. | |
| tooltip: The column (or list of columns) to display on the tooltip when a user hovers over a bar. | |
| x_title: The title given to the x axis. By default, uses the value of the x parameter. | |
| y_title: The title given to the y axis. By default, uses the value of the y parameter. | |
| x_label_angle: The angle (in degrees) of the x axis labels. Positive values are clockwise, and negative values are counter-clockwise. | |
| y_label_angle: The angle (in degrees) of the y axis labels. Positive values are clockwise, and negative values are counter-clockwise. | |
| color_legend_title: The title given to the color legend. By default, uses the value of color parameter. | |
| group_title: The label displayed on top of the subplot columns (or rows if vertical=True). Use an empty string to omit. | |
| color_legend_position: The position of the color legend. If the string value 'none' is passed, this legend is omitted. For other valid position values see: https://vega.github.io/vega/docs/legends/#orientation. | |
| height: The height of the plot in pixels. | |
| width: The width of the plot in pixels. If None, expands to fit. | |
| y_lim: A tuple of list containing the limits for the y-axis, specified as [y_min, y_max]. | |
| caption: The (optional) caption to display below the plot. | |
| interactive: Whether users should be able to interact with the plot by panning or zooming with their mouse or trackpad. | |
| label: The (optional) label to display on the top left corner of the plot. | |
| show_label: Whether the label should be displayed. | |
| every: Continously calls `value` to recalculate it if `value` is a function (has no effect otherwise). Can provide a Timer whose tick resets `value`, or a float that provides the regular interval for the reset Timer. | |
| inputs: Components that are used as inputs to calculate `value` if `value` is a function (has no effect otherwise). `value` is recalculated any time the inputs change. | |
| visible: Whether the plot should be visible. | |
| elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles. | |
| elem_classes: An optional list of strings that are assigned as the classes of this component in the HTML DOM. Can be used for targeting CSS styles. | |
| render: If False, component will not render be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later. | |
| key: if assigned, will be used to assume identity across a re-render. Components that have the same key across a re-render will have their value preserved. | |
| sort: Specifies the sorting axis as either "x", "y", "-x" or "-y". If None, no sorting is applied. | |
| show_actions_button: Whether to show the actions button on the top right corner of the plot. | |
| """ | |
| self.x = x | |
| self.y = y | |
| self.color = color | |
| self.vertical = vertical | |
| self.group = group | |
| self.group_title = group_title | |
| self.tooltip = tooltip | |
| self.title = title | |
| self.x_title = x_title | |
| self.y_title = y_title | |
| self.x_label_angle = x_label_angle | |
| self.y_label_angle = y_label_angle | |
| self.color_legend_title = color_legend_title | |
| self.group_title = group_title | |
| self.color_legend_position = color_legend_position | |
| self.y_lim = y_lim | |
| self.caption = caption | |
| self.interactive_chart = interactive | |
| if isinstance(width, str): | |
| width = None | |
| warnings.warn( | |
| "Width should be an integer, not a string. Setting width to None." | |
| ) | |
| if isinstance(height, str): | |
| warnings.warn( | |
| "Height should be an integer, not a string. Setting height to None." | |
| ) | |
| height = None | |
| self.width = width | |
| self.height = height | |
| self.sort = sort | |
| self.show_actions_button = show_actions_button | |
| if label is None and show_label is None: | |
| show_label = False | |
| super().__init__( | |
| value=value, | |
| label=label, | |
| show_label=show_label, | |
| container=container, | |
| scale=scale, | |
| min_width=min_width, | |
| visible=visible, | |
| elem_id=elem_id, | |
| elem_classes=elem_classes, | |
| render=render, | |
| key=key, | |
| every=every, | |
| inputs=inputs, | |
| ) | |
| def get_block_name(self) -> str: | |
| return "plot" | |
| def create_plot( | |
| value: pd.DataFrame, | |
| x: str, | |
| y: str, | |
| color: str | None = None, | |
| vertical: bool = True, | |
| group: str | None = None, | |
| title: str | None = None, | |
| tooltip: list[str] | str | None = None, | |
| x_title: str | None = None, | |
| y_title: str | None = None, | |
| x_label_angle: float | None = None, | |
| y_label_angle: float | None = None, | |
| color_legend_title: str | None = None, | |
| group_title: str | None = None, | |
| color_legend_position: Literal[ | |
| "left", | |
| "right", | |
| "top", | |
| "bottom", | |
| "top-left", | |
| "top-right", | |
| "bottom-left", | |
| "bottom-right", | |
| "none", | |
| ] | |
| | None = None, | |
| height: int | None = None, | |
| width: int | None = None, | |
| y_lim: list[int] | None = None, | |
| interactive: bool | None = True, | |
| sort: Literal["x", "y", "-x", "-y"] | None = None, | |
| ): | |
| """Helper for creating the bar plot.""" | |
| import altair as alt | |
| interactive = True if interactive is None else interactive | |
| orientation = {"field": group, "title": group_title} if group else {} | |
| x_title = x_title or x | |
| y_title = y_title or y | |
| # If horizontal, switch x and y | |
| if not vertical: | |
| y, x = x, y | |
| x = f"sum({x}):Q" | |
| y_title, x_title = x_title, y_title | |
| orientation = {"row": alt.Row(**orientation)} if orientation else {} # type: ignore | |
| x_lim = y_lim | |
| y_lim = None | |
| else: | |
| y = f"sum({y}):Q" | |
| x_lim = None | |
| orientation = {"column": alt.Column(**orientation)} if orientation else {} # type: ignore | |
| encodings = dict( | |
| x=alt.X( | |
| x, # type: ignore | |
| title=x_title, # type: ignore | |
| scale=AltairPlot.create_scale(x_lim), # type: ignore | |
| axis=alt.Axis(labelAngle=x_label_angle) | |
| if x_label_angle is not None | |
| else alt.Axis(), | |
| sort=sort if vertical and sort is not None else None, | |
| ), | |
| y=alt.Y( | |
| y, # type: ignore | |
| title=y_title, # type: ignore | |
| scale=AltairPlot.create_scale(y_lim), # type: ignore | |
| axis=alt.Axis(labelAngle=y_label_angle) | |
| if y_label_angle is not None | |
| else alt.Axis(), | |
| sort=sort if not vertical and sort is not None else None, | |
| ), | |
| **orientation, | |
| ) | |
| properties = {} | |
| if title: | |
| properties["title"] = title | |
| if height: | |
| properties["height"] = height | |
| if width: | |
| properties["width"] = width | |
| if color: | |
| color_legend_position = color_legend_position or "bottom" | |
| domain = value[color].unique().tolist() | |
| range_ = list(range(len(domain))) | |
| encodings["color"] = { | |
| "field": color, | |
| "type": "nominal", | |
| "scale": {"domain": domain, "range": range_}, | |
| "legend": AltairPlot.create_legend( | |
| position=color_legend_position, title=color_legend_title | |
| ), | |
| } | |
| if tooltip: | |
| encodings["tooltip"] = tooltip # type: ignore | |
| chart = ( | |
| alt.Chart(value) # type: ignore | |
| .mark_bar() # type: ignore | |
| .encode(**encodings) | |
| .properties(background="transparent", **properties) | |
| ) | |
| if interactive: | |
| chart = chart.interactive() | |
| return chart | |
| def preprocess(self, payload: AltairPlotData) -> AltairPlotData: | |
| """ | |
| Parameters: | |
| payload: The data to display in a bar plot. | |
| Returns: | |
| (Rarely used) passes the data displayed in the bar plot as an AltairPlotData dataclass, which includes the plot information as a JSON string, as well as the type of plot (in this case, "bar"). | |
| """ | |
| return payload | |
| def postprocess(self, value: pd.DataFrame | None) -> AltairPlotData | None: | |
| """ | |
| Parameters: | |
| value: Expects a pandas DataFrame containing the data to display in the bar plot. The DataFrame should contain at least two columns, one for the x-axis (corresponding to this component's `x` argument) and one for the y-axis (corresponding to `y`). | |
| Returns: | |
| The data to display in a bar plot, in the form of an AltairPlotData dataclass, which includes the plot information as a JSON string, as well as the type of plot (in this case, "bar"). | |
| """ | |
| # if None or update | |
| if value is None: | |
| return value | |
| if self.x is None or self.y is None: | |
| raise ValueError("No value provided for required parameters `x` and `y`.") | |
| chart = self.create_plot( | |
| value=value, | |
| x=self.x, | |
| y=self.y, | |
| color=self.color, | |
| vertical=self.vertical, | |
| group=self.group, | |
| title=self.title, | |
| tooltip=self.tooltip, | |
| x_title=self.x_title, | |
| y_title=self.y_title, | |
| x_label_angle=self.x_label_angle, | |
| y_label_angle=self.y_label_angle, | |
| color_legend_title=self.color_legend_title, | |
| color_legend_position=self.color_legend_position, # type: ignore | |
| group_title=self.group_title, | |
| y_lim=self.y_lim, | |
| interactive=self.interactive_chart, | |
| height=self.height, | |
| width=self.width, | |
| sort=self.sort, # type: ignore | |
| ) | |
| return AltairPlotData(type="altair", plot=chart.to_json(), chart="bar") | |
| def example_payload(self) -> Any: | |
| return None | |
| def example_value(self) -> Any: | |
| import pandas as pd | |
| return pd.DataFrame({self.x: [1, 2, 3], self.y: [4, 5, 6]}) | |