I have been creating dashboards for exploring data, and finding relations between each other. I have been using Power BI, but it has a lot of limitations, gets very frustrating and there isn’t much flexibility in what you can make. I want to use Streamlit instead (else Panel), but a requirement I have is interactions between plots - so selecting an area of a scatter plot, or selecting a slice of a pie chart should be able to update tables and the rest of the plots. I already have plotly experience, in addition to a bank of plotly and streamlit functions, so I would prefer to use streamlit over Panel, but this interactivity isn’t currently easy to do with Streamlit.
However, plotly have recently released a FigureWidget class which can majorly help with this as it can output the indices of the selected points. However this doesn’t seem to be explicitly supported by Streamlit.
I have included the relevant links:
Question:
a) is there any plans on being able to input a FigureWidget into a streamlit.plotly_chart object or similar? As you can then add callbacks to this FigureWidget object, such as update the input dataframe on selection, using widget_object.data[0].on_selection(fn_to_cut_down_df).
b) I noticed that Streamlit Components has been launched, which seems like it may make this kind of thing possible, but currently you need to link it to a frontend file. Is there any way to add a streamlit component which is this FigureWidget object, which can then be used in the above way? Or would it be simple to create a component to pull out the df indices selected on the plot and send them to Python?
I don’t have any React or JS experience sadly, I’ve mainly used Python - but I’m happy to learn, I’m just a little stuck on where to start.
I am using Streamlit 0.63.0, with Python 3.7.7 with miniconda. Additionally I use Windows 10 and Google Chrome.
I’ve been thinkering too with the idea of a plotly scatterplot where you can select some points and return their indices to filter data for the next plot. I don’t have a definitive, “generic” solution for this, but if you’re building only for your specific needs it should be possible to use Components to control Plotly.js plots directly.
As an introduction, plotly.py is a Python client which generates a JSON spec that plotly.js consumes to render a plot. Actually streamlit.plotly_graph dumps the JSON spec from the Figure and passes it to react-plotly for rendering . You could easily replicate this using Streamlit components to train yourself !
Then there’s FigureWidget which is another Python class that renders Plotly graphs but in the ipywidgets model. At first glance, when rendering FigureWidget, a plotly.js graph is mounted and communication between the plotly.js plot and Python FigureWidget is done through ipywidgets’ event model.
There’s no “dump Python class in a JSON format to pass it to plotly.js for rendering”. FigureWidget is tightly coupled to ìpywidgets event model so that when you do widget_object.data[0].on_selection(fn_to_cut_down_df) it sends a custom event to plotly.js through ipywidgets, then the JS plot updates itself with this info.
You could try and extract all the callbacks events from FigureWidget to try and pass them to react-plotly with Streamlit Components but … I’m not sure, it looks time-consuming and demanding at first glance but that may be my ignorance of how ipywidgets work.
For now the faster but very specific approaches would be :
You can build a single specific Plotly.js component with a lasso selection event inside, have Python send a dataframe through Components to your lasso interactive plot and return indices out from the selection, as you suggest actually, and then use those indices to filter data for the next plot.
You could build one single component which contains all your plotly.js plots and any cross interactivity in JS, so you encapsulate everything in a single Component with multiple plots.
I don’t have an answer for integrating ipywidgets in Streamlit Components, because I don’t know much how we can capture their event system. We have opened a discussion on this here Ipywidgets (WIP) if you have info on this. If anyone has a better idea I’m interested too
You can follow the bidirectional tutorial from the docs.
You can install plotly.js through npm with npm add plotly.js when in the frontend folder, then import it in your js file. Hopefully the plotly.js doc is enough for you to render a JSON spec from plotly.py
Don’t hesitate to take a good look at all the examples from the components-template + source code from any component from the gallery
Oh this looks great, I’ll take a look now - thanks for all your links! I’ve taken a look through the bidirection tutorial, but it’s confused me a bit, mainly because I’m just not used to anything other than pure python or python + SQL, so I’ll look through the plotly.js doc and hopefully that may help!
This tutorial rocks! I like how you use react hooks to keep things simple and clean!
I’m not 100% sure but I think you could use fig.to_dict() to transmit data and drop that JSON.parse() on javascript-side, and you may also do that to_dict() call automatically inside your function wrapper to show that it simplifies the usage of the final function.
Other than that, I hope it’ll show that making components is not that hard, even with no javascript nor react experience! And I’m looking forward to reading your incoming frontend/React tutorial
Eheh I think that was my first try but I remember I got a numpy.ndarray not serializable so resorted to stringifying the json instead. Good idea for the to_dict in the wrapper I’ll edit that part
Anyway thanks y’all xD I wrote this on the fly without checking too much if it even made sense so I’m happy it’s actually helpful
Nice THanks @andfanilo!
For some reason, it doesn’t print the selected points on my machine(s). But that also concerns other components, so the issue might be elsewhere.
Thanks again @andfanilo you’re awesome!
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.