Skip to content

Commit

Permalink
docs: improve the jupyter tutorial a bit after reading it again
Browse files Browse the repository at this point in the history
  • Loading branch information
maartenbreddels committed Nov 1, 2024
1 parent 069a205 commit 1e903b3
Showing 1 changed file with 23 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@
"source": [
"# Build your Jupyter dashboard using Solara\n",
"\n",
"Welcome to the first part of a series of tutorials that will show you how to create a dashboard in Jupyter and deploy it as a standalone web app. Importantly, there will be no need to rewrite your app in a different framework, no need to use a non-Python solution, and no need to use JavaScript or CSS.\n",
"Welcome to the first part of a series of tutorials showing you how to create a dashboard in Jupyter and deploy it as a standalone web app. Importantly, you won't need to rewrite your app in a different framework for deployment. We will use a pure Python solution with no JavaScript or CSS required.\n",
"\n",
"Jupyter notebooks are an incredible tool for data analysis, since they enable blending code, visualization and narrative into a single document.\n",
"However, if the insights need to be presented to a non-technical audience, we usually do not want to show the code.\n",
"Jupyter notebooks are an incredible data analysis tool since they blend code, visualization, and narrative into a single document. However, we do not want to show the code if the insights must be presented to a non-technical audience.\n",
"\n",
"\n",
"Built on top of ipywidgets, the Solara framework integrates well into the Jupyter notebook, Jupyter lab as well as other Jupyter environments, and as we will see in a later article, can be deployed efficiently using the Solara server. This, by itself, makes Solara a perfect solution for creating dashboards or data apps.\n",
"\n",
"In this tutorial, we will create a simple dashboard using Solara's UI components. The final product will allow an end-user to filter,\n",
"visualize and explore a dataset on a map.\n",
"\n",
"![image](https://dxhl76zpt6fap.cloudfront.net/public/docs/tutorial/jupyter-dashboard1.webp)\n",
"\n",
"## Pre-requisits \n",
"## Pre-requisites \n",
"\n",
"You need to install `pandas`, `matplotlib`, `folium` and `solara`. Assuming you are using pip, you can execute on your shell:\n",
"\n",
Expand All @@ -43,7 +45,7 @@
"id": "6cc6256a",
"metadata": {},
"source": [
"The first thing we do when we read in the data is to print it out, to see what the dataset contains."
"The first thing we do when we read in the data is to print it out to see what the dataset contains."
]
},
{
Expand Down Expand Up @@ -365,7 +367,7 @@
"id": "08a9644a",
"metadata": {},
"source": [
"The data looks clean but since we will work with the `Category` and `PdDistrict` column data, lets convert those columns to title case."
"The data looks clean, but since we will work with the `Category` and `PdDistrict` column data, let us convert those columns to title case."
]
},
{
Expand Down Expand Up @@ -700,7 +702,7 @@
"id": "b0e37cb4",
"metadata": {},
"source": [
"Now, with our filtered dataset, we create two barcharts. We use regular pandas and matplotlib, but seaborn or plotly would also have been appropriate choices."
"Now, with our filtered dataset, we create two bar charts. We use regular Pandas and Matplotlib, but Seaborn or Plotly would also be appropriate choices."
]
},
{
Expand Down Expand Up @@ -750,9 +752,9 @@
"id": "0e71ff2f",
"metadata": {},
"source": [
"Since we do not need bi-directional communication (e.g. we do not need to receive events or data from our map), we use folium to display the locations of the committed crimes on a map. If we do need bi-directional communication, we can also decide to use [ipyleaflet](https://ipyleaflet.readthedocs.io/en/latest/usage/index.html).\n",
"Since we do not need bidirectional communication (e.g., we do not need to receive events or data from our map), we use Folium to display the locations of the committed crimes on a map. If we do need bidirectional communication, we can also decide to use [ipyleaflet](https://ipyleaflet.readthedocs.io/).\n",
"\n",
"We cannot display all the data on the map without crashing your browser, so we limit to a maximum of a 50 points."
"Since we cannot display all the data on the map without crashing your browser, we limit it to a maximum of 50 points."
]
},
{
Expand Down Expand Up @@ -800,9 +802,9 @@
"source": [
"## Making our first reactive visualization\n",
"\n",
"The above code works nicely, but if we want to explore different types of crimes, we need to manually modify and run all cells that determine out output. Would it not be much better to have a UI with controls that determine the filtering, and a view that displays the filtered data interactively?\n",
"The above code works nicely, but if we want to explore different types of crimes, we need to modify and run all cells that determine our output manually. Would it not be much better to have a UI with controls determining the filtering and a view displaying the filtered data interactively?\n",
"\n",
"Lets start by importing the solara package, and create three reactive variables."
"Let's start by importing the solara package and creating three reactive variables."
]
},
{
Expand All @@ -814,9 +816,7 @@
"source": [
"import solara\n",
"\n",
"districts = solara.reactive(\n",
" [\"Bayview\", \"Northern\"],\n",
")\n",
"districts = solara.reactive([\"Bayview\", \"Northern\"])\n",
"categories = solara.reactive([\"Vandalism\", \"Assault\", \"Robbery\"])\n",
"limit = solara.reactive(100)"
]
Expand All @@ -826,9 +826,9 @@
"id": "28622c20",
"metadata": {},
"source": [
" A reactive variable is a container around a value (like a int, string or list) that allows the UI to automatically listen to changes. Any change to `your_reactive_variable.value` will be picked up by solara component that use them, so that they can automatically redraw or update itself.\n",
"A reactive variable is a container around a value (like an int, string, or list) that allows the UI to listen to changes automatically. Any change to your_reactive_variable.value will be picked up by Solara components that use them so that they can automatically redraw or update themselves.\n",
"\n",
" We now create our first component (`View`) which filters the data (based on the reactive variables), and shows the map and the charts. Solara supports the `display` mechanism of Jupyter, so we can simply use our previously defined functions."
"Let us now create our first component (View), which filters the data based on the reactive variables and shows the map and the charts. Solara supports the display mechanism of Jupyter so that we can use our previously defined functions."
]
},
{
Expand Down Expand Up @@ -859,7 +859,9 @@
"id": "0b05c1db",
"metadata": {},
"source": [
"Note that some of the code (like the warning and the charts) are conditional. Solara will automatically find out what to add, remove or update without you having to do this manually. Solara is declarative (similar to ReactJS), but also reactive. If we change the reactive variables, Solara sees that changes and notifies the component instances that use its value. After executing the next lines of code, our `View` will automatically update."
"Note that some UI parts (like the warning and the charts) are conditional. Solara will automatically find out what to add, remove, or update without you having to do this manually. Solara is declarative (similar to ReactJS) but also reactive. If we change the reactive variables, Solara will see those changes and notify the component instances that use its value.\n",
"\n",
"If we run the next lines of code in our notebook, our View will automatically update."
]
},
{
Expand All @@ -878,7 +880,9 @@
"id": "8822d100",
"metadata": {},
"source": [
"We can now explore out data much faster, since we don't need to re-run the cells that depended on it. "
"We can now explore our data much faster since we don't need to re-run the cells that depend on it.\n",
"\n",
"Solara's reactive and declarative nature makes it scalable to much larger applications than regular ipywidgets, where keeping the UI in sync and adding, removing, and updating widgets is a manual and bug-prone process."
]
},
{
Expand All @@ -888,7 +892,7 @@
"source": [
"## Adding controls\n",
"\n",
"We created a mini app in our notebook that is declarative *and* reactive, but we still need to manually modify the values by executing a code cell, while we promised a UI to control it. Luckily, all Solara input components supports reactive variables. This means that controlling a reactive variable using a UI element is often a one-liner."
"We created a declarative and reactive mini app in our notebook, but we still need to manually modify the values by executing a code cell in our Notebook. Now, let us create a UI to control it. All Solara input components support reactive variables. This means that controlling a reactive variable using a UI element is often a one-liner."
]
},
{
Expand Down

0 comments on commit 1e903b3

Please sign in to comment.