# Sub plots

Multiple sub plots can be combined into one plot using the `make_subplots` function. This function accepts multiple plot objects, and returns a single plot object. The plot objects can be any of the plot types supported by Deephaven Express. They can be arranged in a grid, or in a single row or column. The `shared_xaxes` and `shared_yaxes` parameters can be used to share axes between plots.

## Examples

### Four unique plots

Create a series of plots as subplots, all providing unique perspectives on the data of interest.

```python order=tipping_plots,tips
import deephaven.plot.express as dx

tips = dx.data.tips()  # import a ticking version of the Tips dataset

# create 4 plots from within make_subplots
tipping_plots = dx.make_subplots(
    dx.scatter(
        tips, x="TotalBill", y="Tip", by="Sex", title="Tip amount by total bill"
    ),
    dx.violin(tips, y="TotalBill", by="Day", title="Total bill distribution by day"),
    dx.pie(
        tips.count_by("Count", by=["Sex", "Smoker"])
        .update_view("SmokerStatus = Smoker == `No` ? `non-smoker` : `smoker`")
        .update_view("SmokerLabel = Sex + ` ` + SmokerStatus"),
        names="SmokerLabel",
        values="Count",
        title="Total bill by sex and smoking status",
    ),
    dx.bar(
        tips.view(["TotalBill", "Tip", "Day"]).avg_by("Day"),
        x="Day",
        y=["TotalBill", "Tip"],
        title="Average tip as a fraction of total bill",
    ),
    rows=2,
    cols=2,
    shared_xaxes=False,
    shared_yaxes=False,
)
```

### Existing Titles as Subplot Titles

By default, titles from the original figures are converted to subplot titles if they exist.

```python order=tipping_plots,lunch_tips,dinner_tips
import deephaven.plot.express as dx

tips = dx.data.tips()

lunch_tips = tips.where("Time = `Lunch`")
dinner_tips = tips.where("Time = `Dinner`")

# Figures with titles
lunch_chart = dx.scatter(lunch_tips, x="TotalBill", y="Tip", title="Lunch Tips")
dinner_chart = dx.scatter(dinner_tips, x="TotalBill", y="Tip", title="Dinner Tips")

# Use existing titles as subplot titles
tipping_plots = dx.make_subplots(
    lunch_chart, dinner_chart, cols=2
)
```

### Adding New Subplot Titles

Add titles to individual subplots using the `subplot_titles` parameter. Provide a list or tuple of titles, ordered from left to right, top to bottom.

```python order=tipping_plots,lunch_tips,dinner_tips
import deephaven.plot.express as dx

tips = dx.data.tips()

lunch_tips = tips.where("Time = `Lunch`")
dinner_tips = tips.where("Time = `Dinner`")

# Add titles to subplots
tipping_plots = dx.make_subplots(
    dx.scatter(lunch_tips, x="TotalBill", y="Tip"),
    dx.scatter(dinner_tips, x="TotalBill", y="Tip"),
    cols=2,
    subplot_titles=["Lunch Tips", "Dinner Tips"],
)
```

### Adding a Title

Add a title to the combined subplot figure using the `title` parameter.

```python order=tipping_plots,tips
import deephaven.plot.express as dx

tips = dx.data.tips()

tipping_plots = dx.make_subplots(
    dx.scatter(tips, x="TotalBill", y="Tip", by="Day"),
    dx.histogram(tips, x="TotalBill"),
    cols=2,
    title="Tipping Analysis",
)
```

### Share Axes

Share axes between plots with the `shared_xaxes` and `shared_yaxes` parameters.

#### Share All Axes

When `shared_xaxes` or `shared_yaxes` is set to `"all"`, all axes of the same type are shared.
When one axis is adjusted, all axes are adjusted to match.

```python order=tipping_plots,lunch_tips,dinner_tips
import deephaven.plot.express as dx

tips = dx.data.tips()  # import a ticking version of the Tips dataset

# filter the tips dataset for separate lunch and dinner charts
lunch_tips = tips.where("Time = `Lunch`")
dinner_tips = tips.where("Time = `Dinner`")

# create chart that shares all axes
tipping_plots = dx.make_subplots(
    dx.scatter(lunch_tips, x="TotalBill", y="Tip", labels={"Tip": "Lunch Tips"}),
    dx.scatter(dinner_tips, x="TotalBill", y="Tip", labels={"Tip": "Dinner Tips"}),
    rows=2,
    shared_yaxes="all",
    shared_xaxes="all",
)
```

#### Share Y Axes

When `shared_yaxis` is set to `True`, all y axes are shared along the same row.
When one y-axis is adjusted, all axes along the same row are adjusted to match.

```python order=tipping_plots,lunch_tips,dinner_tips
import deephaven.plot.express as dx

tips = dx.data.tips()  # import a ticking version of the Tips dataset

# filter the tips dataset for separate lunch and dinner charts
lunch_tips = tips.where("Time = `Lunch`")
dinner_tips = tips.where("Time = `Dinner`")

# create chart that shares y axes along the row
tipping_plots = dx.make_subplots(
    dx.scatter(lunch_tips, x="TotalBill", y="Tip", labels={"Tip": "Lunch Tips"}),
    dx.scatter(dinner_tips, x="TotalBill", y="Tip", labels={"Tip": "Dinner Tips"}),
    cols=2,
    shared_yaxes=True,
)
```

To share the y axes along the same column, set `shared_yaxes` to `"columns"`.

```python order=tipping_plots,lunch_tips,dinner_tips
import deephaven.plot.express as dx

tips = dx.data.tips()  # import a ticking version of the Tips dataset

# filter the tips dataset for separate lunch and dinner charts
lunch_tips = tips.where("Time = `Lunch`")
dinner_tips = tips.where("Time = `Dinner`")

# create chart that shares y axes along the column
tipping_plots = dx.make_subplots(
    dx.scatter(lunch_tips, x="TotalBill", y="Tip", labels={"Tip": "Lunch Tips"}),
    dx.scatter(dinner_tips, x="TotalBill", y="Tip", labels={"Tip": "Dinner Tips"}),
    rows=2,
    shared_yaxes="columns",
)
```

#### Share X Axes

When `shared_xaxis` is set to `True`, all x axes are shared along the same column.
When one x-axis is adjusted, all axes along the same column are adjusted to match.

```python order=tipping_plots,lunch_tips,dinner_tips
import deephaven.plot.express as dx

tips = dx.data.tips()  # import a ticking version of the Tips dataset

# filter the tips dataset for separate lunch and dinner charts
lunch_tips = tips.where("Time = `Lunch`")
dinner_tips = tips.where("Time = `Dinner`")

# create chart that shares x axes along the column
tipping_plots = dx.make_subplots(
    dx.scatter(lunch_tips, x="TotalBill", y="Tip", labels={"Tip": "Lunch Tips"}),
    dx.scatter(dinner_tips, x="TotalBill", y="Tip", labels={"Tip": "Dinner Tips"}),
    rows=2,
    shared_xaxes=True,
)
```

To share the x axes along the same column, set `shared_yaxes` to `"columns"`.

```python order=tipping_plots,lunch_tips,dinner_tips
import deephaven.plot.express as dx

tips = dx.data.tips()  # import a ticking version of the Tips dataset

# filter the tips dataset for separate lunch and dinner charts
lunch_tips = tips.where("Time = `Lunch`")
dinner_tips = tips.where("Time = `Dinner`")

# create chart that shares x axes along the row
tipping_plots = dx.make_subplots(
    dx.scatter(lunch_tips, x="TotalBill", y="Tip", labels={"Tip": "Lunch Tips"}),
    dx.scatter(dinner_tips, x="TotalBill", y="Tip", labels={"Tip": "Dinner Tips"}),
    cols=2,
    shared_xaxes="rows",
)
```

## API Reference

Create subplots. Either figs and at least one of rows and cols or grid
should be passed.

**Returns:** `DeephavenFigure` The DeephavenFigure with subplots

<ParamTable param={{"module_name": "deephaven.plot.express.", "name": "make_subplots", "parameters": [{"name": "*figs", "type": "Figure | DeephavenFigure", "description": "Figures to use. Should be used with rows and/or cols."}, {"name": "rows", "type": "int", "description": "A list of rows in the resulting subplot grid. This is calculated from cols and number of figs provided if not passed but cols is. One of rows or cols should be provided if passing figs directly.", "default": "0"}, {"name": "cols", "type": "int", "description": "A list of cols in the resulting subplot grid. This is calculated from rows and number of figs provided if not passed but rows is. One of rows or cols should be provided if passing figs directly.", "default": "0"}, {"name": "shared_xaxes", "type": "str | bool | None", "description": "\"rows\", \"columns\"/True, \"all\" or None depending on what axes should be shared", "default": "None"}, {"name": "shared_yaxes", "type": "str | bool | None", "description": "\"rows\"/True, \"columns\", \"all\" or None depending on what axes should be shared", "default": "None"}, {"name": "grid", "type": "List[List[Figure | DeephavenFigure]] | None", "description": "A grid (list of lists) of figures to draw. None can be provided in a grid entry", "default": "None"}, {"name": "horizontal_spacing", "type": "float | None", "description": "Spacing between each column. Default 0.2 / cols", "default": "None"}, {"name": "vertical_spacing", "type": "float | None", "description": "Spacing between each row. Default 0.3 / rows", "default": "None"}, {"name": "column_widths", "type": "list[float] | None", "description": "The widths of each column. Should sum to 1.", "default": "None"}, {"name": "row_heights", "type": "list[float] | None", "description": "The heights of each row. Should sum to 1.", "default": "None"}, {"name": "specs", "type": "list[SubplotSpecDict] | List[List[SubplotSpecDict]] | None", "description": "A list or grid of dicts that contain specs. An empty dictionary represents no specs, and None represents no figure, either to leave a gap on the subplots on provide room for a figure spanning multiple columns. 'l' is a float that adds left padding 'r' is a float that adds right padding 't' is a float that adds top padding 'b' is a float that adds bottom padding 'rowspan' is an int to make this figure span multiple rows 'colspan' is an int to make this figure span multiple columns", "default": "None"}, {"name": "subplot_titles", "type": "list[str] | tuple[str, ...] | bool", "description": "True by default, which automatically extracts and uses titles from the input figures as subplot titles. If False or an empty list/tuple, one of the subplot titles ends up as the chart title. See the title parameter to override this behavior. If a list or tuple is provided, these are the titles for each subplot. Titles are filled left to right, top to bottom. Empty strings (\"\") can be included in the list if no subplot title is desired in that space.", "default": "True"}, {"name": "title", "type": "str | None", "description": "The overall title for the combined subplot figure. If an empty string, no overall title is shown.", "default": "None"}, {"name": "unsafe_update_figure", "type": "Callable", "description": "An update function that takes a plotly figure as an argument and optionally returns a plotly figure. If a figure is not returned, the plotly figure passed will be assumed to be the return value. Used to add any custom changes to the underlying plotly figure. Note that the existing data traces should not be removed. This may lead to unexpected behavior if traces are modified in a way that break data mappings.", "default": "<function default_callback>"}]}} />
