{ "cells": [ { "cell_type": "markdown", "id": "68b4877a-d595-47b4-988f-b470eb4251e5", "metadata": {}, "source": [ "# North America Roads\n", "\n", "This example uses data from [Natural Earth](https://www.naturalearthdata.com/) to plot the road network in North America. Refer to the [data documentation](https://www.naturalearthdata.com/downloads/10m-cultural-vectors/roads/) for more information about this dataset." ] }, { "cell_type": "markdown", "id": "c4f33772-767a-4f79-ab31-b75ddb07089d", "metadata": {}, "source": [ "## Dependencies\n", "\n", "- lonboard\n", "- pyogrio" ] }, { "cell_type": "markdown", "id": "d404b794-1456-42ee-9161-c50b70c831ef", "metadata": {}, "source": [ "## Imports" ] }, { "cell_type": "code", "execution_count": 1, "id": "51abc06e-0d06-40ef-aea6-19130e88bce3", "metadata": {}, "outputs": [], "source": [ "import geopandas as gpd\n", "import palettable.colorbrewer.diverging\n", "\n", "from lonboard import Map, PathLayer\n", "from lonboard.colormap import apply_continuous_cmap" ] }, { "cell_type": "markdown", "id": "d4ddc6c3-7538-44cd-a082-912aa5aef1cc", "metadata": {}, "source": [ "The \"public\" URL for this dataset from the Natural Earth website is\n", "```\n", "https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_roads_north_america.zip\n", "```\n", "That doesn't appear to work directly inside a notebook, so we'll use the URL the above redirects to:\n", "\n", "```\n", "https://naciscdn.org/naturalearth/10m/cultural/ne_10m_roads_north_america.zip\n", "```\n", "\n", "It's possible this \"private\" URL will change in the future." ] }, { "cell_type": "code", "execution_count": 2, "id": "ce868022-f3e4-4db5-83d7-af65b5e2f959", "metadata": {}, "outputs": [], "source": [ "url = 'https://naciscdn.org/naturalearth/10m/cultural/ne_10m_roads_north_america.zip'" ] }, { "cell_type": "markdown", "id": "6d77aa88-6d94-4eac-a5c7-e52efcc93930", "metadata": {}, "source": [ "We'll use GeoPandas to fetch this data (45MB) over the internet and load it into a `GeoDataFrame`. This uses the [`pyogrio` engine](https://geopandas.org/en/stable/docs/reference/api/geopandas.read_file.html), which is faster. Ensure you have [`pyogrio`](https://github.com/geopandas/pyogrio) installed. " ] }, { "cell_type": "code", "execution_count": 3, "id": "c97da98c-cce8-4f66-b598-59eef05367de", "metadata": {}, "outputs": [], "source": [ "gdf = gpd.read_file(url, engine=\"pyogrio\")" ] }, { "cell_type": "markdown", "id": "f4a9b9a1-9d78-42a3-be88-60ac550a84de", "metadata": {}, "source": [ "This dataframe has a variety of attributes, plus a geometry column with a `LineString` type." ] }, { "cell_type": "code", "execution_count": 4, "id": "14d60ee4-4006-48b3-8ddb-52e3ae6002da", "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
prefixnumberclasstypedividedcountrystatenotescalerankuidentlengthrankcontinentgeometry
0NoneNoneOtherUnpavedNoneUnited StatesCaliforniaNone12010.3735000North AmericaLINESTRING (-119.63954 37.85634, -119.63954 37...
1NoneNoneOtherOther PavedNoneUnited StatesNevadaNone1212.3077600North AmericaLINESTRING (-119.76779 39.14514, -119.74707 39...
2NoneS2OtherOther PavedNoneMexicoNoneNone11292.178100-1North AmericaLINESTRING (-116.47485 33.09658, -116.46246 33...
3NoneS1OtherOther PavedNoneUnited StatesCaliforniaNone11346.1241000North AmericaLINESTRING (-116.56070 33.01205, -116.55359 33...
4NoneS1OtherSecondaryUndividedUnited StatesCaliforniaNone1040.3054630North AmericaLINESTRING (-116.50827 32.81225, -116.50820 32...
\n", "
" ], "text/plain": [ " prefix number class type divided country state \\\n", "0 None None Other Unpaved None United States California \n", "1 None None Other Other Paved None United States Nevada \n", "2 None S2 Other Other Paved None Mexico None \n", "3 None S1 Other Other Paved None United States California \n", "4 None S1 Other Secondary Undivided United States California \n", "\n", " note scalerank uident length rank continent \\\n", "0 None 12 0 10.373500 0 North America \n", "1 None 12 1 2.307760 0 North America \n", "2 None 11 2 92.178100 -1 North America \n", "3 None 11 3 46.124100 0 North America \n", "4 None 10 4 0.305463 0 North America \n", "\n", " geometry \n", "0 LINESTRING (-119.63954 37.85634, -119.63954 37... \n", "1 LINESTRING (-119.76779 39.14514, -119.74707 39... \n", "2 LINESTRING (-116.47485 33.09658, -116.46246 33... \n", "3 LINESTRING (-116.56070 33.01205, -116.55359 33... \n", "4 LINESTRING (-116.50827 32.81225, -116.50820 32... " ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gdf.head()" ] }, { "cell_type": "markdown", "id": "3d1caaa7-7d99-451c-a385-6aac276fd43c", "metadata": {}, "source": [ "To ensure that this demo is snappy on most computers, we'll filter to only the contiguous U.S. If you're on a recent computer, feel free to comment out this line." ] }, { "cell_type": "code", "execution_count": 5, "id": "0e690480-25fa-4f12-aba6-3477a0f86a27", "metadata": {}, "outputs": [], "source": [ "gdf = gdf[gdf[\"state\"] == \"California\"]" ] }, { "cell_type": "markdown", "id": "11f005c2-2cac-47d7-aec4-cd00057646f8", "metadata": {}, "source": [ "To render `LineString` data, first create a `PathLayer` and then add it to a `Map` object." ] }, { "cell_type": "code", "execution_count": 6, "id": "053eb025-6ddd-46c1-8159-061b9eb7c09e", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "03b5eb8c14764749a8f85cb9115d2c65", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Map(layers=[PathLayer(table=pyarrow.Table\n", "prefix: string\n", "number: string\n", "class: string\n", "type: string\n", "divided: st…" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "layer = PathLayer.from_geopandas(gdf, width_min_pixels=0.8)\n", "map_ = Map(layers=[layer])\n", "map_" ] }, { "cell_type": "markdown", "id": "a6bdfd6d-2689-42f6-a538-8f833c6d539a", "metadata": {}, "source": [ "We can look at the [documentation for `PathLayer`](https://developmentseed.org/lonboard/latest/api/layers/path-layer/) to see what other rendering options it allows. Let's set the path color to something other than black:" ] }, { "cell_type": "code", "execution_count": 7, "id": "75f67a77-062a-4043-9454-5b2b97b52288", "metadata": {}, "outputs": [], "source": [ "layer.get_color = [200, 0, 200]" ] }, { "cell_type": "markdown", "id": "9bac0f0b-7129-476c-8ea0-51c1bede0f4d", "metadata": {}, "source": [ "Ok, so we can see the data! That's great! But let's customize the rendering based on an attribute!\n", "\n", "The `scalerank` column tells how important the road is in the road network. Let's see what the distribution of values is for this column:" ] }, { "cell_type": "code", "execution_count": 8, "id": "5c33098b-0348-4b07-9ae4-5c56d5d50723", "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "scalerank\n", "3 19\n", "4 93\n", "5 35\n", "6 94\n", "7 178\n", "8 122\n", "9 1\n", "10 237\n", "11 541\n", "12 1562\n", "Name: count, dtype: int64" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gdf['scalerank'].value_counts().sort_index()" ] }, { "cell_type": "markdown", "id": "667e990e-5424-47fe-9847-c8be297cf425", "metadata": {}, "source": [ "Ok, so the values range from `3` to `12`. To assign a colormap to this column, we need \"normalized\" values that span between 0 and 1:" ] }, { "cell_type": "code", "execution_count": 9, "id": "c7d26678-418e-48f8-827d-050d9f2df1dd", "metadata": {}, "outputs": [], "source": [ "normalized_scale_rank = (gdf['scalerank'] - 3) / 9" ] }, { "cell_type": "markdown", "id": "00f628bc-34ff-4b95-9998-27e0d66b1b61", "metadata": {}, "source": [ "The values of this array now range from 0 to 1:" ] }, { "cell_type": "code", "execution_count": 10, "id": "12be09c8-0857-44d8-ad14-69b4c7277fbc", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0.0, 1.0)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "normalized_scale_rank.min(), normalized_scale_rank.max()" ] }, { "cell_type": "markdown", "id": "a5c4f17e-9465-44ee-b54e-26a351574a29", "metadata": {}, "source": [ "Let's select a colormap to apply to this data:" ] }, { "cell_type": "code", "execution_count": 11, "id": "1df9d2c9-6f10-49e6-aa4f-6718f3d2f765", "metadata": {}, "outputs": [], "source": [ "cmap = palettable.colorbrewer.diverging.PuOr_10" ] }, { "cell_type": "code", "execution_count": 12, "id": "6e0f48ab-0cbe-4ce9-b804-9a1a3330ff9f", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgAAAABACAYAAABsv8+/AAAAE3RFWHRUaXRsZQBQdU9yIGNvbG9ybWFw1Lg2NQAAABl0RVh0RGVzY3JpcHRpb24AUHVPciBjb2xvcm1hcF8Kpq0AAAAwdEVYdEF1dGhvcgBNYXRwbG90bGliIHYzLjcuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZ7rJ3hAAAAAydEVYdFNvZnR3YXJlAE1hdHBsb3RsaWIgdjMuNy4zLCBodHRwczovL21hdHBsb3RsaWIub3JnlG9BNwAAAgRJREFUeJzt1kFy2yAAhlFQNr1TD9eTS3QR5IyxsdEknS7+9zYMCIG8SOarf37/aqWUUmsrpZSy1bI01sV98/2v7/v++ZN92zmvS/NtO89/Pf9f5z3OP96M2/28Lu67+ryunrO2b+vj7Qf388ttfTL/9r439/30d5TP+44+tlL7OKy37fn68PwY3p+d8/B+Gd5fvm88pw739fOOz7//o7U+L5P1trheLu7/R+f094/j6GN7Om+T9a/nz9fP/W2y/tPnvP3Ova/vw/59eH7bfz6frQ/fvV98ftyfP65f/t52zve7+df663lr+2R99v7aPY/r1+45x/7fDQBIIgAAIJAAAIBAAgAAAgkAAAgkAAAgkAAAgEACAAACCQAACCQAACCQAACAQAIAAAIJAAAIJAAAIJAAAIBAAgAAAgkAAAgkAAAgkAAAgEACAAACCQAACCQAACCQAACAQAIAAAIJAAAIJAAAIJAAAIBAAgAAAgkAAAgkAAAgkAAAgEACAAACCQAACCQAACCQAACAQAIAAAIJAAAIJAAAIJAAAIBAAgAAAgkAAAgkAAAgkAAAgEACAAACCQAACCQAACCQAACAQAIAAAIJAAAIJAAAIJAAAIBAAgAAAgkAAAgkAAAgkAAAgEACAAACCQAACCQAACCQAACAQAIAAAIJAAAIJAAAIJAAAIBAfwF0sXUGDv0RXAAAAABJRU5ErkJggg==", "text/html": [ "
PuOr
\"PuOr
under
bad
over
" ], "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cmap.mpl_colormap" ] }, { "cell_type": "markdown", "id": "74d9d749-4222-4aa8-bf12-ded79187a616", "metadata": {}, "source": [ "Now we'll use `apply_continuous_cmap` onto this array to generate colors for our data. Just set this new array onto the existing layer, and you'll see the map update with the new colors!" ] }, { "cell_type": "code", "execution_count": 13, "id": "7288a2d7-3190-4f9e-b29e-bbba32109024", "metadata": {}, "outputs": [], "source": [ "layer.get_color = apply_continuous_cmap(normalized_scale_rank, palettable.colorbrewer.diverging.PuOr_10, alpha=0.8)" ] }, { "cell_type": "code", "execution_count": null, "id": "72807632-f5de-4dcc-9c8e-f4e0c8495e2b", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.4" } }, "nbformat": 4, "nbformat_minor": 5 }