{ "cells": [ { "cell_type": "markdown", "id": "4eb729a6-3210-4e70-a896-e7d05795cde7", "metadata": {}, "source": [ "\n", "\n", "

## Exercise 3: Building Pipelines

Hint
\n", "\n", "You can use the `min()` and `max()` method on the `depth` `Series` of `most_severe` to check the range. To declare the slider, use a `pn.widgets.FloatSlider`.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "a8970ba8-e3ae-4ce0-a13a-ec8067134007", "metadata": {}, "outputs": [], "source": [ "depth_slider = ... \n", "depth_slider" ] }, { "cell_type": "markdown", "id": "76e765dd-feca-424d-b38d-b07a3b0494ff", "metadata": {}, "source": [ "
Solution
\n", "\n", "```python\n", "depth_slider = pn.widgets.FloatSlider(name='Minimum depth', start=0, end=700, value=350)\n", "depth_slider\n", "```\n", " \n", "```python\n", ">> most_severe.depth.min()\n", "4.2\n", ">> most_severe.depth.max()\n", "675.4\n", " \n", "```\n", "\n", "
" ] }, { "cell_type": "markdown", "id": "610e2e92-31bc-448f-95d7-7cee4261b1f3", "metadata": {}, "source": [ "#### Exploring a reactive `DataFrame`\n", "\n", "Now we will create a new reactive `DataFrame` called `rdf` with `sizing_mode='stretch_width'`.\n", "\n", "\n", "
Hint
\n", "\n", "Use `pn.rx` on `most_severe` to create the reactive `DataFrame` called `rdf`\n", "
\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "f95077d9-348a-49cb-803d-4bdd5ed7d134", "metadata": {}, "outputs": [], "source": [ "rdf = ... # reactive DataFrame version of most_severe" ] }, { "cell_type": "markdown", "id": "d1878e8a-e239-44d8-80fa-d14883534899", "metadata": {}, "source": [ "
Solution
\n", "\n", "```python\n", "rdf = pn.rx(most_severe)\n", "```" ] }, { "cell_type": "markdown", "id": "8b29de7d-2e2a-4c09-89f6-16e58186d438", "metadata": {}, "source": [ "Now use this reactive `Dataframe` to filter the earthquakes deeper than specified by the `depth_slider`. Call this filtered dataframe `depth_filtered` and to view it conveniently, use the `.head()` method to see the first few entries.\n", "\n", "\n", "
Hint
\n", "\n", "Use the the regular pandas idiom to filter a `DataFrame` with `df[mask]` where `mask` is a boolean mask. The only difference is instead of picking a fixed depth value to filter by, you can use the `depth_slider` widget instead.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "4d11234e-a63e-4c19-90fe-3a1b66cea112", "metadata": {}, "outputs": [], "source": [ "depth_filtered = ...\n", "# Now display the head of this reactive dataframe" ] }, { "cell_type": "markdown", "id": "d255266b-4549-4655-8ccb-a31d81d08992", "metadata": {}, "source": [ "
Solution
\n", "\n", "```python\n", "depth_slider = pn.widgets.FloatSlider(name='Minimum depth', start=0, end=700, value=350)\n", "\n", "rdf = pn.rx(most_severe)\n", "depth_filtered = rdf[rdf['depth'] < depth_slider]\n", "\n", "depth_filtered.head()\n", "```" ] }, { "cell_type": "markdown", "id": "7175bae1-5123-4052-8899-5a8bd95f81a4", "metadata": {}, "source": [ "#### Plotting the depth filtered data\n", "\n", "For an initial plot, try calling `.hvplot()` and seeing what happens (which is unlikely to be what you wanted by default!).\n" ] }, { "cell_type": "code", "execution_count": null, "id": "d66deb44-eccc-40f5-988b-a23cc3100892", "metadata": {}, "outputs": [], "source": [ "# depth_filtered.hvplot()" ] }, { "cell_type": "markdown", "id": "50906abc-3457-4047-9d34-69abaafbce0f", "metadata": {}, "source": [ "Now let's make a more meaningful plot, such as the magnitude of the filtered earthquakes as a scatter plot with (`x`) markers colored by depth.\n", "\n", "
Hint
\n", "\n", "The magnitude column is called `mag`, you can set `x` markers with `marker='x'`, and to get a scatter plot you can use `kind='scatter'`. `color` accepts not just a single color like `'red'`, but also the name of column to color by that column.\n", "
\n" ] }, { "cell_type": "code", "execution_count": null, "id": "5365b310-9e24-4c19-aa1c-85b9fe55e48a", "metadata": {}, "outputs": [], "source": [ "# Scatter plot of magnitude, filtered by depth with red cross markers" ] }, { "cell_type": "markdown", "id": "0edf6ced-5a87-4da7-8f86-7be0fbbc3e80", "metadata": {}, "source": [ "
Solution
\n", "\n", "```python\n", "depth_slider = pn.widgets.FloatSlider(name='Minimum depth', start=0, end=700, value=350)\n", "\n", "rdf = pn.rx(most_severe)\n", "depth_filtered = rdf[rdf['depth'] < depth_slider]\n", "depth_filtered.hvplot(y='mag', kind='scatter', color='red', marker='x')\n", "```" ] }, { "cell_type": "markdown", "id": "69318817-b18a-45b8-934c-e00b6654d7bc", "metadata": {}, "source": [ "### Using reactive xarrays\n", "\n", "The `.rx` interface applies not just to pandas `DataFrames`, but to essentially any Python object, including an Xarray dataset. Here we load our population raster and perform some simple cleanup:" ] }, { "cell_type": "code", "execution_count": null, "id": "9f44e342-9361-4d4f-9ee9-4f216c0f91b4", "metadata": {}, "outputs": [], "source": [ "raw_ds = xr.open_dataarray(pathlib.Path('../../data/raster/gpw_v4_population_density_rev11_2010_2pt5_min.nc'))\n", "cleaned_ds = raw_ds.where(raw_ds.values != raw_ds.nodatavals).sel(band=1)\n", "cleaned_ds = cleaned_ds.rename({'x': 'longitude','y': 'latitude'})\n", "cleaned_ds.name = 'population'\n", "cleaned_ds = cleaned_ds.fillna(0)" ] }, { "cell_type": "markdown", "id": "4898c8c6-d0bb-4a3f-97bd-f75b3dc7a88d", "metadata": {}, "source": [ "One operation we could do on this raster is to collapse one of the two dimensions. For instance, we could view the mean population over latitude (averaged over longitude) or conversely the mean population over longitude (averaged over latitude). To select between these options, we will want a dropdown widget called `collapsed_axis`.\n", "\n", "
Hint
\n", "\n", "A dropdown widget in panel can be made with a `pn.widgets.Select` object. The dropdown options are specified as a list of strings to the `options` argument.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "1cb9dd31-3646-47b7-99a0-ad3d2f149638", "metadata": {}, "outputs": [], "source": [ "collapsed_axis = ... # Declare a dropdown to select either 'latitude' or 'longitude' and display it" ] }, { "cell_type": "markdown", "id": "b12404dc-46bf-472d-9f45-4f1eb26f28e6", "metadata": {}, "source": [ "
Solution
\n", "\n", "```python\n", "collapsed_axis = pn.widgets.Select(options=['latitude', 'longitude'], name='Collapsed dimension')\n", "collapsed_axis\n", "```" ] }, { "cell_type": "markdown", "id": "177a9019-488d-4344-b529-92f1795a0865", "metadata": {}, "source": [ "Now create a reactive xarray `DataArray` called `rds` in the analogous fashion to the reactive `DataFrame` we created earlier. \n", "\n", "
Hint
\n", "\n", "As before, the reactive object is created by `pn.rx()`, but now on an xarray object instead of a pandas object.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "bb74010f-27f2-4876-b89e-484919b3db4e", "metadata": {}, "outputs": [], "source": [ "rds = ... # A reactive DataArray" ] }, { "cell_type": "markdown", "id": "088b1e87-43cd-479f-8fe9-05c34d37b8e6", "metadata": {}, "source": [ "
Solution
\n", "\n", "```python\n", "rds = pn.rx(cleaned_ds)\n", "```" ] }, { "cell_type": "markdown", "id": "2118a4e5-1c2a-4654-8e65-39a994231fc7", "metadata": {}, "source": [ "#### Plotting population averaged over either latitude or longitude\n", "\n", "Now we can use the xarray API to collapse either latitude or longitude by taking the mean. To do this, we can use the `.mean()` method of an xarray `DataArray` which accepts a `dim` argument specifying the dimension over which to apply the mean. After collapsing the dimensions specified by the widget, plot the population with a green curve.\n", "\n", "
Hint
\n", "\n", "First write and test a static version of your pipeline, where you supply `'latitude'` or `'longitude'` explicitly to the `dim` argument of the `mean` method and then call `.hvplot` to plot it while specifying `color='green'`. Then try passing your `collapsed_axis` widget instead of that fixed string. \n", "
\n" ] }, { "cell_type": "code", "execution_count": null, "id": "860fb8f7-c0d0-428b-a878-6ba72ae82da2", "metadata": {}, "outputs": [], "source": [ "# Using `rds` plot the population as a green curve where the collapsed dimension is selected by the widget" ] }, { "cell_type": "markdown", "id": "cf1d2474-32f5-4e6e-bbcd-c35105a0e73d", "metadata": {}, "source": [ "
Solution
\n", "\n", "```python\n", "rds = pn.rx(cleaned_ds)\n", "collapsed_axis = pn.widgets.Select(options=['latitude', 'longitude'], name='Collapsed dimension')\n", "rds.mean(dim=collapsed_axis).hvplot(color='green')\n", "```" ] } ], "metadata": { "language_info": { "name": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 5 }