mirror of
https://github.com/gradio-app/gradio.git
synced 2024-11-21 01:01:05 +08:00
Improve plot guide, add double clicking to plots (#9064)
* changes * add changeset * chages * changes * changes * changes * changes --------- Co-authored-by: Ali Abid <aliabid94@gmail.com> Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
parent
6778b8353d
commit
4ba7b238e2
6
.changeset/ripe-grapes-refuse.md
Normal file
6
.changeset/ripe-grapes-refuse.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"@gradio/nativeplot": minor
|
||||
"gradio": minor
|
||||
---
|
||||
|
||||
feat:Improve plot guide, add double clicking to plots
|
13
demo/plot_guide_filters_events/data.py
Normal file
13
demo/plot_guide_filters_events/data.py
Normal file
@ -0,0 +1,13 @@
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
now = datetime.now()
|
||||
|
||||
df = pd.DataFrame({
|
||||
'time': [now - timedelta(minutes=5*i) for i in range(25)],
|
||||
'price': np.random.randint(100, 1000, 25),
|
||||
'origin': [random.choice(["DFW", "DAL", "HOU"]) for _ in range(25)],
|
||||
'destination': [random.choice(["JFK", "LGA", "EWR"]) for _ in range(25)],
|
||||
})
|
1
demo/plot_guide_filters_events/run.ipynb
Normal file
1
demo/plot_guide_filters_events/run.ipynb
Normal file
@ -0,0 +1 @@
|
||||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: plot_guide_filters_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/plot_guide_filters_events/data.py"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from data import df\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " origin = gr.Dropdown([\"All\", \"DFW\", \"DAL\", \"HOU\"], value=\"All\", label=\"Origin\")\n", " destination = gr.Dropdown([\"All\", \"JFK\", \"LGA\", \"EWR\"], value=\"All\", label=\"Destination\")\n", " max_price = gr.Slider(0, 1000, value=1000, label=\"Max Price\")\n", "\n", " plt = gr.ScatterPlot(df, x=\"time\", y=\"price\", inputs=[origin, destination, max_price])\n", "\n", " @gr.on(inputs=[origin, destination, max_price], outputs=plt)\n", " def filtered_data(origin, destination, max_price):\n", " _df = df[df[\"price\"] <= max_price]\n", " if origin != \"All\":\n", " _df = _df[_df[\"origin\"] == origin]\n", " if destination != \"All\":\n", " _df = _df[_df[\"destination\"] == destination]\n", " return _df\n", "\n", " \n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
23
demo/plot_guide_filters_events/run.py
Normal file
23
demo/plot_guide_filters_events/run.py
Normal file
@ -0,0 +1,23 @@
|
||||
import gradio as gr
|
||||
from data import df
|
||||
|
||||
with gr.Blocks() as demo:
|
||||
with gr.Row():
|
||||
origin = gr.Dropdown(["All", "DFW", "DAL", "HOU"], value="All", label="Origin")
|
||||
destination = gr.Dropdown(["All", "JFK", "LGA", "EWR"], value="All", label="Destination")
|
||||
max_price = gr.Slider(0, 1000, value=1000, label="Max Price")
|
||||
|
||||
plt = gr.ScatterPlot(df, x="time", y="price", inputs=[origin, destination, max_price])
|
||||
|
||||
@gr.on(inputs=[origin, destination, max_price], outputs=plt)
|
||||
def filtered_data(origin, destination, max_price):
|
||||
_df = df[df["price"] <= max_price]
|
||||
if origin != "All":
|
||||
_df = _df[_df["origin"] == origin]
|
||||
if destination != "All":
|
||||
_df = _df[_df["destination"] == destination]
|
||||
return _df
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo.launch()
|
10
demo/plot_guide_selection/data.py
Normal file
10
demo/plot_guide_selection/data.py
Normal file
@ -0,0 +1,10 @@
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import random
|
||||
|
||||
df = pd.DataFrame({
|
||||
'height': np.random.randint(50, 70, 25),
|
||||
'weight': np.random.randint(120, 320, 25),
|
||||
'age': np.random.randint(18, 65, 25),
|
||||
'ethnicity': [random.choice(["white", "black", "asian"]) for _ in range(25)]
|
||||
})
|
1
demo/plot_guide_selection/run.ipynb
Normal file
1
demo/plot_guide_selection/run.ipynb
Normal file
@ -0,0 +1 @@
|
||||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: plot_guide_selection"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/plot_guide_selection/data.py"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from data import df\n", "\n", "with gr.Blocks() as demo:\n", " plt = gr.LinePlot(df, x=\"weight\", y=\"height\")\n", " selection_total = gr.Number(label=\"Total Weight of Selection\")\n", "\n", " def select_region(selection: gr.SelectData):\n", " min_w, max_w = selection.index\n", " return df[(df[\"weight\"] >= min_w) & (df[\"weight\"] <= max_w)][\"weight\"].sum()\n", "\n", " plt.select(select_region, None, selection_total)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
15
demo/plot_guide_selection/run.py
Normal file
15
demo/plot_guide_selection/run.py
Normal file
@ -0,0 +1,15 @@
|
||||
import gradio as gr
|
||||
from data import df
|
||||
|
||||
with gr.Blocks() as demo:
|
||||
plt = gr.LinePlot(df, x="weight", y="height")
|
||||
selection_total = gr.Number(label="Total Weight of Selection")
|
||||
|
||||
def select_region(selection: gr.SelectData):
|
||||
min_w, max_w = selection.index
|
||||
return df[(df["weight"] >= min_w) & (df["weight"] <= max_w)]["weight"].sum()
|
||||
|
||||
plt.select(select_region, None, selection_total)
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo.launch()
|
10
demo/plot_guide_zoom/data.py
Normal file
10
demo/plot_guide_zoom/data.py
Normal file
@ -0,0 +1,10 @@
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import random
|
||||
|
||||
df = pd.DataFrame({
|
||||
'height': np.random.randint(50, 70, 25),
|
||||
'weight': np.random.randint(120, 320, 25),
|
||||
'age': np.random.randint(18, 65, 25),
|
||||
'ethnicity': [random.choice(["white", "black", "asian"]) for _ in range(25)]
|
||||
})
|
1
demo/plot_guide_zoom/run.ipynb
Normal file
1
demo/plot_guide_zoom/run.ipynb
Normal file
@ -0,0 +1 @@
|
||||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: plot_guide_zoom"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/plot_guide_zoom/data.py"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from data import df\n", "\n", "with gr.Blocks() as demo:\n", " plt = gr.LinePlot(df, x=\"weight\", y=\"height\")\n", "\n", " def select_region(selection: gr.SelectData):\n", " min_w, max_w = selection.index\n", " return gr.LinePlot(x_lim=(min_w, max_w)) # type: ignore\n", "\n", " plt.select(select_region, None, plt)\n", " plt.double_click(lambda: gr.LinePlot(x_lim=None), None, plt)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
15
demo/plot_guide_zoom/run.py
Normal file
15
demo/plot_guide_zoom/run.py
Normal file
@ -0,0 +1,15 @@
|
||||
import gradio as gr
|
||||
from data import df
|
||||
|
||||
with gr.Blocks() as demo:
|
||||
plt = gr.LinePlot(df, x="weight", y="height")
|
||||
|
||||
def select_region(selection: gr.SelectData):
|
||||
min_w, max_w = selection.index
|
||||
return gr.LinePlot(x_lim=(min_w, max_w)) # type: ignore
|
||||
|
||||
plt.select(select_region, None, plt)
|
||||
plt.double_click(lambda: gr.LinePlot(x_lim=None), None, plt)
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo.launch()
|
10
demo/plot_guide_zoom_sync/data.py
Normal file
10
demo/plot_guide_zoom_sync/data.py
Normal file
@ -0,0 +1,10 @@
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import random
|
||||
|
||||
df = pd.DataFrame({
|
||||
'height': np.random.randint(50, 70, 25),
|
||||
'weight': np.random.randint(120, 320, 25),
|
||||
'age': np.random.randint(18, 65, 25),
|
||||
'ethnicity': [random.choice(["white", "black", "asian"]) for _ in range(25)]
|
||||
})
|
1
demo/plot_guide_zoom_sync/run.ipynb
Normal file
1
demo/plot_guide_zoom_sync/run.ipynb
Normal file
@ -0,0 +1 @@
|
||||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: plot_guide_zoom_sync"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/plot_guide_zoom_sync/data.py"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from data import df\n", "\n", "with gr.Blocks() as demo:\n", " plt1 = gr.LinePlot(df, x=\"weight\", y=\"height\")\n", " plt2 = gr.BarPlot(df, x=\"weight\", y=\"age\", x_bin=10)\n", " plots = [plt1, plt2]\n", "\n", " def select_region(selection: gr.SelectData):\n", " min_w, max_w = selection.index\n", " return [gr.LinePlot(x_lim=(min_w, max_w))] * len(plots) # type: ignore\n", "\n", " for plt in plots:\n", " plt.select(select_region, None, plots)\n", " plt.double_click(lambda: [gr.LinePlot(x_lim=None)] * len(plots), None, plots)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
18
demo/plot_guide_zoom_sync/run.py
Normal file
18
demo/plot_guide_zoom_sync/run.py
Normal file
@ -0,0 +1,18 @@
|
||||
import gradio as gr
|
||||
from data import df
|
||||
|
||||
with gr.Blocks() as demo:
|
||||
plt1 = gr.LinePlot(df, x="weight", y="height")
|
||||
plt2 = gr.BarPlot(df, x="weight", y="age", x_bin=10)
|
||||
plots = [plt1, plt2]
|
||||
|
||||
def select_region(selection: gr.SelectData):
|
||||
min_w, max_w = selection.index
|
||||
return [gr.LinePlot(x_lim=(min_w, max_w))] * len(plots) # type: ignore
|
||||
|
||||
for plt in plots:
|
||||
plt.select(select_region, None, plots)
|
||||
plt.double_click(lambda: [gr.LinePlot(x_lim=None)] * len(plots), None, plots)
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo.launch()
|
@ -38,7 +38,7 @@ class NativePlot(Component):
|
||||
Demos: native_plots
|
||||
"""
|
||||
|
||||
EVENTS = [Events.select]
|
||||
EVENTS = [Events.select, Events.double_click]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -725,6 +725,9 @@ class Events:
|
||||
doc="This listener is triggered when the user changes the value of the {{ component }}.",
|
||||
)
|
||||
click = EventListener("click", doc="Triggered when the {{ component }} is clicked.")
|
||||
double_click = EventListener(
|
||||
"double_click", doc="Triggered when the {{ component }} is double clicked."
|
||||
)
|
||||
submit = EventListener(
|
||||
"submit",
|
||||
doc="This listener is triggered when the user presses the Enter key while the {{ component }} is focused.",
|
||||
|
1
gradio/hash_seed.txt
Normal file
1
gradio/hash_seed.txt
Normal file
@ -0,0 +1 @@
|
||||
f7311342c5e04ba58dd320ef66cfecd0
|
@ -45,6 +45,23 @@ If your x-axis is a string type instead, they will act as the category bins auto
|
||||
$code_plot_guide_aggregate_nominal
|
||||
$demo_plot_guide_aggregate_nominal
|
||||
|
||||
## Selecting Regions
|
||||
|
||||
You can use the `.select` listener to select regions of a plot. Click and drag on the plot below to select part of the plot.
|
||||
|
||||
$code_plot_guide_selection
|
||||
$demo_plot_guide_selection
|
||||
|
||||
You can combine this and the `.double_click` listener to create some zoom in/out effects by changing `x_lim` which sets the bounds of the x-axis:
|
||||
|
||||
$code_plot_guide_zoom
|
||||
$demo_plot_guide_zoom
|
||||
|
||||
If you had multiple plots with the same x column, your event listeners could target the x limits of all other plots so that the x-axes stay in sync.
|
||||
|
||||
$code_plot_guide_zoom_sync
|
||||
$demo_plot_guide_zoom_sync
|
||||
|
||||
## Making an Interactive Dashboard
|
||||
|
||||
Take a look how you can have an interactive dashboard where the plots are functions of other Components.
|
||||
|
@ -18,7 +18,7 @@ $demo_plot_guide_aggregate_temporal
|
||||
|
||||
## DateTime Components
|
||||
|
||||
You can use `gr.DateTime` to accept input datetime data. This works well with plots for defining the x-axis range for the data. The `x_lim` attribute sets the x-axis bounds.
|
||||
You can use `gr.DateTime` to accept input datetime data. This works well with plots for defining the x-axis range for the data.
|
||||
|
||||
$code_plot_guide_datetime
|
||||
$demo_plot_guide_datetime
|
||||
@ -36,7 +36,7 @@ Try zooming around in the plots and see how DateTimeRange updates. All the plots
|
||||
|
||||
## RealTime Data
|
||||
|
||||
In many cases, you're working with live, realtime date, not a static dataframe. In this case, you'd the plot to update regularly with a `gr.Timer()`. Assuming there's a `get_data` method that gets the latest dataframe:
|
||||
In many cases, you're working with live, realtime date, not a static dataframe. In this case, you'd update the plot regularly with a `gr.Timer()`. Assuming there's a `get_data` method that gets the latest dataframe:
|
||||
|
||||
```python
|
||||
with gr.Blocks() as demo:
|
||||
@ -47,7 +47,7 @@ with gr.Blocks() as demo:
|
||||
timer.tick(lambda: [get_data(), get_data()], outputs=[plot1, plot2])
|
||||
```
|
||||
|
||||
You can use the `every` shorthand to attach a `Timer` to a component that has a function value:
|
||||
You can also use the `every` shorthand to attach a `Timer` to a component that has a function value:
|
||||
|
||||
```python
|
||||
with gr.Blocks() as demo:
|
||||
|
@ -4,10 +4,14 @@ Your dashboard will likely consist of more than just plots. Let's take a look at
|
||||
|
||||
## Filters
|
||||
|
||||
Use any of the standard Gradio form components to filter your data. Because the dataframe is not static, we'll use function-as-value format for the LinePlot value.
|
||||
Use any of the standard Gradio form components to filter your data. You can do this via event listeners or function-as-value syntax. Let's look at the event listener approach first:
|
||||
|
||||
$code_plot_guide_filters_events
|
||||
$demo_plot_guide_filters_events
|
||||
|
||||
And this would be the function-as-value approach for the same demo.
|
||||
|
||||
$code_plot_guide_filters
|
||||
$demo_plot_guide_filters
|
||||
|
||||
## Tables and Stats
|
||||
|
||||
|
@ -77,6 +77,7 @@
|
||||
}[];
|
||||
export let gradio: Gradio<{
|
||||
select: SelectData;
|
||||
double_click: undefined;
|
||||
clear_status: LoadingStatus;
|
||||
}>;
|
||||
|
||||
@ -159,6 +160,19 @@
|
||||
view = result.view;
|
||||
resizeObserver.observe(chart_element);
|
||||
var debounceTimeout: NodeJS.Timeout;
|
||||
view.addEventListener("dblclick", () => {
|
||||
gradio.dispatch("double_click");
|
||||
});
|
||||
// prevent double-clicks from highlighting text
|
||||
chart_element.addEventListener(
|
||||
"mousedown",
|
||||
function (e) {
|
||||
if (e.detail > 1) {
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
if (_selectable) {
|
||||
view.addSignalListener("brush", function (_, value) {
|
||||
if (Object.keys(value).length === 0) return;
|
||||
|
Loading…
Reference in New Issue
Block a user