-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
I simply cannot figure out how to make plot not overflow in below example. Please make it easy for users to use dynamic plots.
"""Example 2: Data Explorer Pipeline — DataFrames flowing between nodes with an hvPlot scatter chart."""
import hvplot.pandas # noqa: F401
import numpy as np
import pandas as pd
import panel as pn
import param
from panel.viewable import Viewer
from panel_reactflow import EdgeSpec, NodeSpec, ReactFlow
pn.extension("jsoneditor")
# Generate sample datasets (no external dependencies needed)
DATASETS = {
"iris": pd.DataFrame(
{
"sepal_length": np.random.normal(5.8, 0.8, 150),
"sepal_width": np.random.normal(3.0, 0.4, 150),
"petal_length": np.random.normal(3.7, 1.8, 150),
"petal_width": np.random.normal(1.2, 0.8, 150),
}
),
"random": pd.DataFrame(
{
"x": np.random.randn(200),
"y": np.random.randn(200),
"size": np.random.uniform(1, 10, 200),
"value": np.random.uniform(0, 100, 200),
}
),
}
class DataLoaderNode(Viewer):
dataset = param.Selector(default="iris", objects=list(DATASETS.keys()))
data = param.DataFrame()
@param.depends("dataset", watch=True, on_init=True)
def _load(self):
self.data = DATASETS[self.dataset]
def __panel__(self):
info = pn.bind(
lambda d: f"**{len(d)} rows, {len(d.columns)} cols**" if d is not None else "",
self.param.data,
)
return pn.Column(
pn.widgets.Select.from_param(self.param.dataset, name="Dataset"),
info,
)
class ColumnFilterNode(Viewer):
data = param.DataFrame()
x_col = param.Selector(default="")
y_col = param.Selector(default="")
@param.depends("data", watch=True)
def _update_columns(self):
if self.data is not None:
cols = list(self.data.select_dtypes("number").columns)
self.param.x_col.objects = cols
self.param.y_col.objects = cols
if cols:
self.x_col = cols[0]
self.y_col = cols[min(1, len(cols) - 1)]
def __panel__(self):
return pn.Column(
pn.widgets.Select.from_param(self.param.x_col, name="X Column"),
pn.widgets.Select.from_param(self.param.y_col, name="Y Column"),
)
class ChartNode(Viewer):
data = param.DataFrame()
x_col = param.String(default="")
y_col = param.String(default="")
@param.depends("data", "x_col", "y_col")
def plot(self):
if self.data is None or not self.x_col or not self.y_col:
return pn.pane.Markdown("*Waiting for data...*")
return self.data.hvplot.scatter(x=self.x_col, y=self.y_col, responsive=True)
def __panel__(self):
return pn.panel(self.plot, width=500, height=400, sizing_mode="fixed", styles={"border": "1px solid #ddd", "padding": "10px", "box-sizing": "border-box"})
# Create instances and wire them
loader = DataLoaderNode()
filter_node = ColumnFilterNode()
chart = ChartNode()
loader.param.watch(lambda e: setattr(filter_node, "data", e.new), "data")
filter_node.param.watch(lambda e: setattr(chart, "x_col", e.new), "x_col")
filter_node.param.watch(lambda e: setattr(chart, "y_col", e.new), "y_col")
filter_node.param.watch(lambda e: setattr(chart, "data", e.new), "data")
# Build graph
flow = ReactFlow(
nodes=[
NodeSpec(id="loader", position={"x": 0, "y": 80}, label="Data Loader").to_dict() | {"view": loader.__panel__()},
NodeSpec(id="filter", position={"x": 400, "y": 50}, label="Column Filter").to_dict() | {"view": filter_node.__panel__()},
NodeSpec(id="chart", position={"x": 850, "y": 0}, label="Scatter Chart").to_dict() | {"view": chart.__panel__()},
],
edges=[
EdgeSpec(id="e1", source="loader", target="filter", label="DataFrame").to_dict(),
EdgeSpec(id="e2", source="filter", target="chart", label="columns + data").to_dict(),
],
sizing_mode="stretch_both",
)
flow.servable()In the dropdown select "random"
I've tried all imaginable combinations of width, height and sizing_mode in ChartNode.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels