Skip to content

Commit

Permalink
Allow plot tooltip to show extra columns (#9800)
Browse files Browse the repository at this point in the history
* changes

* add changeset

* changes

* changes

* chanes

* changes

---------

Co-authored-by: Ali Abid <aliabid94@gmail.com>
Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
  • Loading branch information
4 people authored Nov 2, 2024
1 parent 120198f commit d1cfe1e
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 26 deletions.
6 changes: 6 additions & 0 deletions .changeset/moody-crews-pull.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@gradio/nativeplot": minor
"gradio": minor
---

feat:Allow plot tooltip to show extra columns
2 changes: 1 addition & 1 deletion demo/scatter_plot/run.ipynb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: scatter_plot"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets pandas"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "cars = data.cars()\n", "iris = data.iris()\n", "\n", "# # Or generate your own fake data\n", "\n", "# import pandas as pd\n", "# import random\n", "\n", "# cars_data = {\n", "# \"Name\": [\"car name \" + f\" {int(i/10)}\" for i in range(400)],\n", "# \"Miles_per_Gallon\": [random.randint(10, 30) for _ in range(400)],\n", "# \"Origin\": [random.choice([\"USA\", \"Europe\", \"Japan\"]) for _ in range(400)],\n", "# \"Horsepower\": [random.randint(50, 250) for _ in range(400)],\n", "# }\n", "\n", "# iris_data = {\n", "# \"petalWidth\": [round(random.uniform(0, 2.5), 2) for _ in range(150)],\n", "# \"petalLength\": [round(random.uniform(0, 7), 2) for _ in range(150)],\n", "# \"species\": [\n", "# random.choice([\"setosa\", \"versicolor\", \"virginica\"]) for _ in range(150)\n", "# ],\n", "# }\n", "\n", "# cars = pd.DataFrame(cars_data)\n", "# iris = pd.DataFrame(iris_data)\n", "\n", "def scatter_plot_fn(dataset):\n", " if dataset == \"iris\":\n", " return gr.ScatterPlot(\n", " value=iris,\n", " x=\"petalWidth\",\n", " y=\"petalLength\",\n", " color=\"species\",\n", " title=\"Iris Dataset\",\n", " color_legend_title=\"Species\",\n", " x_title=\"Petal Width\",\n", " y_title=\"Petal Length\",\n", " tooltip=[\"petalWidth\", \"petalLength\", \"species\"],\n", " caption=\"\",\n", " )\n", " else:\n", " return gr.ScatterPlot(\n", " value=cars,\n", " x=\"Horsepower\",\n", " y=\"Miles_per_Gallon\",\n", " color=\"Origin\",\n", " tooltip=\"Name\",\n", " title=\"Car Data\",\n", " y_title=\"Miles per Gallon\",\n", " color_legend_title=\"Origin of Car\",\n", " caption=\"MPG vs Horsepower of various cars\",\n", " )\n", "\n", "with gr.Blocks() as scatter_plot:\n", " with gr.Row():\n", " with gr.Column():\n", " dataset = gr.Dropdown(choices=[\"cars\", \"iris\"], value=\"cars\")\n", " with gr.Column():\n", " plot = gr.ScatterPlot()\n", " dataset.change(scatter_plot_fn, inputs=dataset, outputs=plot)\n", " scatter_plot.load(fn=scatter_plot_fn, inputs=dataset, outputs=plot)\n", "\n", "if __name__ == \"__main__\":\n", " scatter_plot.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: scatter_plot"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets pandas"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "cars = data.cars()\n", "iris = data.iris()\n", "\n", "# # Or generate your own fake data\n", "\n", "# import pandas as pd\n", "# import random\n", "\n", "# cars_data = {\n", "# \"Name\": [\"car name \" + f\" {int(i/10)}\" for i in range(400)],\n", "# \"Miles_per_Gallon\": [random.randint(10, 30) for _ in range(400)],\n", "# \"Origin\": [random.choice([\"USA\", \"Europe\", \"Japan\"]) for _ in range(400)],\n", "# \"Horsepower\": [random.randint(50, 250) for _ in range(400)],\n", "# }\n", "\n", "# iris_data = {\n", "# \"petalWidth\": [round(random.uniform(0, 2.5), 2) for _ in range(150)],\n", "# \"petalLength\": [round(random.uniform(0, 7), 2) for _ in range(150)],\n", "# \"species\": [\n", "# random.choice([\"setosa\", \"versicolor\", \"virginica\"]) for _ in range(150)\n", "# ],\n", "# }\n", "\n", "# cars = pd.DataFrame(cars_data)\n", "# iris = pd.DataFrame(iris_data)\n", "\n", "def scatter_plot_fn(dataset):\n", " if dataset == \"iris\":\n", " return gr.ScatterPlot(\n", " value=iris,\n", " x=\"petalWidth\",\n", " y=\"petalLength\",\n", " color=\"species\",\n", " title=\"Iris Dataset\",\n", " color_legend_title=\"Species\",\n", " x_title=\"Petal Width\",\n", " y_title=\"Petal Length\",\n", " tooltip=[\"petalWidth\", \"petalLength\", \"species\"],\n", " caption=\"\",\n", " )\n", " else:\n", " return gr.ScatterPlot(\n", " value=cars,\n", " x=\"Horsepower\",\n", " y=\"Miles_per_Gallon\",\n", " color=\"Origin\",\n", " tooltip=[\"Name\"],\n", " title=\"Car Data\",\n", " y_title=\"Miles per Gallon\",\n", " color_legend_title=\"Origin of Car\",\n", " caption=\"MPG vs Horsepower of various cars\",\n", " )\n", "\n", "with gr.Blocks() as scatter_plot:\n", " with gr.Row():\n", " with gr.Column():\n", " dataset = gr.Dropdown(choices=[\"cars\", \"iris\"], value=\"cars\")\n", " with gr.Column():\n", " plot = gr.ScatterPlot()\n", " dataset.change(scatter_plot_fn, inputs=dataset, outputs=plot)\n", " scatter_plot.load(fn=scatter_plot_fn, inputs=dataset, outputs=plot)\n", "\n", "if __name__ == \"__main__\":\n", " scatter_plot.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
2 changes: 1 addition & 1 deletion demo/scatter_plot/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def scatter_plot_fn(dataset):
x="Horsepower",
y="Miles_per_Gallon",
color="Origin",
tooltip="Name",
tooltip=["Name"],
title="Car Data",
y_title="Miles per Gallon",
color_legend_title="Origin of Car",
Expand Down
2 changes: 1 addition & 1 deletion demo/scatterplot_component/run.ipynb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: scatterplot_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "cars = data.cars()\n", "\n", "with gr.Blocks() as demo:\n", " gr.ScatterPlot(\n", " value=cars,\n", " x=\"Horsepower\",\n", " y=\"Miles_per_Gallon\",\n", " color=\"Origin\",\n", " tooltip=\"Name\",\n", " title=\"Car Data\",\n", " y_title=\"Miles per Gallon\",\n", " color_legend_title=\"Origin of Car\",\n", " container=False,\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: scatterplot_component"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets"]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "cars = data.cars()\n", "\n", "with gr.Blocks() as demo:\n", " gr.ScatterPlot(\n", " value=cars,\n", " x=\"Horsepower\",\n", " y=\"Miles_per_Gallon\",\n", " color=\"Origin\",\n", " tooltip=[\"Name\"],\n", " title=\"Car Data\",\n", " y_title=\"Miles per Gallon\",\n", " color_legend_title=\"Origin of Car\",\n", " container=False,\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
2 changes: 1 addition & 1 deletion demo/scatterplot_component/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
x="Horsepower",
y="Miles_per_Gallon",
color="Origin",
tooltip="Name",
tooltip=["Name"],
title="Car Data",
y_title="Miles per Gallon",
color_legend_title="Origin of Car",
Expand Down
4 changes: 3 additions & 1 deletion gradio/components/native_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def __init__(
x_axis_labels_visible: bool = True,
caption: str | None = None,
sort: Literal["x", "y", "-x", "-y"] | list[str] | None = None,
tooltip: Literal["axis", "none", "all"] | list[str] = "axis",
height: int | None = None,
label: str | None = None,
show_label: bool | None = None,
Expand Down Expand Up @@ -94,6 +95,7 @@ def __init__(
x_axis_labels_visible: Whether the x-axis labels should be visible. Can be hidden when many x-axis labels are present.
caption: The (optional) caption to display below the plot.
sort: The sorting order of the x values, if x column is type string/category. Can be "x", "y", "-x", "-y", or list of strings that represent the order of the categories.
tooltip: The tooltip to display when hovering on a point. "axis" shows the values for the axis columns, "all" shows all column values, and "none" shows no tooltips. Can also provide a list of strings representing columns to show in the tooltip, which will be displayed along with axis values.
height: The height of the plot in pixels.
label: The (optional) label to display on the top left corner of the plot.
show_label: Whether the label should be displayed.
Expand Down Expand Up @@ -125,6 +127,7 @@ def __init__(
self.x_axis_labels_visible = x_axis_labels_visible
self.caption = caption
self.sort = sort
self.tooltip = tooltip
self.height = height

if label is None and show_label is None:
Expand All @@ -150,7 +153,6 @@ def __init__(
if key in [
"stroke_dash",
"overlay_point",
"tooltip",
"x_label_angle",
"y_label_angle",
"interactive",
Expand Down
69 changes: 48 additions & 21 deletions js/nativeplot/Index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
export let x_axis_labels_visible = true;
export let caption: string | null = null;
export let sort: "x" | "y" | "-x" | "-y" | string[] | null = null;
export let tooltip: "axis" | "none" | "all" | string[] = "axis";
function reformat_sort(
_sort: typeof sort
):
Expand Down Expand Up @@ -114,6 +115,15 @@
function reformat_data(data: PlotData): {
[x: string]: string | number;
}[] {
if (tooltip == "all" || Array.isArray(tooltip)) {
return data.data.map((row) => {
const obj: { [x: string]: string | number } = {};
data.columns.forEach((col, i) => {
obj[col] = row[i];
});
return obj;
});
}
let x_index = data.columns.indexOf(x);
let y_index = data.columns.indexOf(y);
let color_index = color ? data.columns.indexOf(color) : null;
Expand Down Expand Up @@ -411,29 +421,46 @@
type: value.datatypes[color]
}
: undefined,
tooltip: [
{
field: y,
type: value.datatypes[y],
aggregate: aggregating ? _y_aggregate : undefined,
title: y_title || y
},
{
field: x,
type: value.datatypes[x],
title: x_title || x,
format: x_temporal ? "%Y-%m-%d %H:%M:%S" : undefined,
bin: _x_bin ? { step: _x_bin } : undefined
},
...(color
? [
tooltip:
tooltip == "none"
? undefined
: [
{
field: color,
type: value.datatypes[color]
}
field: y,
type: value.datatypes[y],
aggregate: aggregating ? _y_aggregate : undefined,
title: y_title || y
},
{
field: x,
type: value.datatypes[x],
title: x_title || x,
format: x_temporal ? "%Y-%m-%d %H:%M:%S" : undefined,
bin: _x_bin ? { step: _x_bin } : undefined
},
...(color
? [
{
field: color,
type: value.datatypes[color]
}
]
: []),
...(tooltip === "axis"
? []
: value?.columns
.filter(
(col) =>
col !== x &&
col !== y &&
col !== color &&
(tooltip === "all" || tooltip.includes(col))
)
.map((column) => ({
field: column,
type: value.datatypes[column]
})))
]
: [])
]
},
strokeDash: {},
mark: { clip: true, type: mode === "hover" ? "point" : value.mark },
Expand Down

0 comments on commit d1cfe1e

Please sign in to comment.