diff --git a/guide/05-working-with-the-spatial-dataframe/visualizing-data-with-the-spatial-dataframe.ipynb b/guide/05-working-with-the-spatial-dataframe/visualizing-data-with-the-spatial-dataframe.ipynb deleted file mode 100644 index c9ecbe88db..0000000000 --- a/guide/05-working-with-the-spatial-dataframe/visualizing-data-with-the-spatial-dataframe.ipynb +++ /dev/null @@ -1,1367 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Visualizing Spatial Data\n", - "The Spatially Enabled Dataframe has a `plot()` method that uses a syntax and symbology similar to [`matplotlib`](https://matplotlib.org) for visualizing features on a map. With this functionality, you can easily visualize aspects of your data both on a map and on a matplotlib chart using the same symbology!\n", - "\n", - "Some unique characteristics of working with the visualization capabalities on the SDF:\n", - "- Uses Pythonic syntax\n", - "- Uses the same syntax as visualizing charts on Pandas DataFrames\n", - "- Uses symbology familiar to users of matplotlib\n", - "- Works on features and attributes simultaneously, eliminating to a great extent the need to iterate over all features (rows)\n", - "- Handles reading and writing to multiple formats aiding data conversion\n", - "\n", - "Checkout the [Introduction to Spatially Enabled DataFrame](/python/guide/features-module/introduction-to-spatial-dataframe) guide to learn how to create a Spatial DataFrame." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this guide, you will learn about:\n", - "\n", - " * [Quickstart](#Quickstart)\n", - " * [Plotting the `DataFarme`](#Plotting-the-SpatialDataFrame)\n", - " * [Understanding renderers](#Understanding-renderers)\n", - " * [Supported renderers](#Supported-renderers)\n", - " * [Visualizing unique values](#Visualizing-unique-values)\n", - " * [Visualizing classes with different colors](#Visualizing-classes-with-different-colors)\n", - " * [ColorMaps and Colors](#Colormaps-and-Colors)\n", - " * [Symbology for Simple Renderers](#Symbology-for-Simple-Renderers)\n", - " * [Getting the different symbol styles](#Getting-the-different-symbol-styles)\n", - " * [Visualizing line features suing simple renderers](#Visualizing-line-features-using-simple-symbols)\n", - " * [Visualizing area features using simple renderers](#Visualizing-area-features-using-different-symbols)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Quickstart\n", - "Let us read a census data on major cities and load that into a `Spatially Enabled DataFrame`" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "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", - " \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", - "
AGE_10_14AGE_15_19AGE_20_24AGE_25_34AGE_35_44AGE_45_54AGE_55_64AGE_5_9AGE_65_74AGE_75_84...PLACEFIPSPOP2010POPULATIONPOP_CLASSRENTER_OCCSHAPESTSTFIPSVACANTWHITE
01413138111062138181514119791557525307...0468080142871498061074nullAZ042619196
17277386771380118513331087740661444...060204299321023962056nullCA062678273
25935112323276774612734122942...0610561106161186962558nullCA062967530
3888988900172914791443959766514280...061356010866111956761nullCA06865898
41086122810131822175914781112925687477...0614974128231300961763nullCA06886930
\n", - "

5 rows × 51 columns

\n", - "
" - ], - "text/plain": [ - " AGE_10_14 AGE_15_19 AGE_20_24 AGE_25_34 AGE_35_44 AGE_45_54 \\\n", - "0 1413 1381 1106 2138 1815 1411 \n", - "1 727 738 677 1380 1185 1333 \n", - "2 593 511 2323 2767 746 127 \n", - "3 888 988 900 1729 1479 1443 \n", - "4 1086 1228 1013 1822 1759 1478 \n", - "\n", - " AGE_55_64 AGE_5_9 AGE_65_74 AGE_75_84 ... PLACEFIPS POP2010 \\\n", - "0 979 1557 525 307 ... 0468080 14287 \n", - "1 1087 740 661 444 ... 0602042 9932 \n", - "2 34 1229 4 2 ... 0610561 10616 \n", - "3 959 766 514 280 ... 0613560 10866 \n", - "4 1112 925 687 477 ... 0614974 12823 \n", - "\n", - " POPULATION POP_CLASS RENTER_OCC SHAPE ST STFIPS VACANT WHITE \n", - "0 14980 6 1074 null AZ 04 261 9196 \n", - "1 10239 6 2056 null CA 06 267 8273 \n", - "2 11869 6 2558 null CA 06 296 7530 \n", - "3 11195 6 761 null CA 06 86 5898 \n", - "4 13009 6 1763 null CA 06 88 6930 \n", - "\n", - "[5 rows x 51 columns]" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from arcgis import GIS\n", - "gis = GIS()\n", - "# create an anonymous connection to ArcGIS Online and get a public item\n", - "item = gis.content.get(\"85d0ca4ea1ca4b9abf0c51b9bd34de2e\")\n", - "flayer = item.layers[0]\n", - "\n", - "# Specify a SQL query and get a sub-set of the original data as a DataFrame\n", - "df = flayer.query(where=\"AGE_45_54 < 1500\").sdf\n", - "\n", - "# Visualize the top 5 records\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "> Note: If the above cell looks new to you, please checkout the [Introduction to Spatially Enabled DataFrame](/python/guide/features-module/introduction-to-spatial-dataframe) guide." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us create a map of the United States" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ea826a65070444b2b88a583b4bb8fb05", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "MapView(basemaps=['dark-gray', 'dark-gray-vector', 'gray', 'gray-vector', 'hybrid', 'national-geographic', 'oc…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "m1 = GIS().map('United States')\n", - "m1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![map of US diamonds](http://esri.github.io/arcgis-python-api/notebooks/nbimages/13_3_map_dfplot1a.png)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "m1.zoom = 4\n", - "m1.center = [39,-98]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plotting the DataFrame\n", - "You can quickly visualize the points by calling the `plot()` method off the dataframes `spatial` accessor and passing the map you created above." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df.spatial.plot(map_widget= m1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can customize the symbols, their color, shape, border etc. like you would in a typical matplotlib plot. The rest of this guide talks about such customizations and suggestions to visualize your spatial and non-spatial data.\n", - "\n", - "The code below plots the same set of points on a new map using a common structure used amongst many different Python packages for defining symbology. It is built off of the matplotlib libraries for simple, straightforward plotting. We'll explain some of the parameters below, and the [`plot()`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#arcgis.features.SpatialDataFrame.plot) API Reference outlines more options." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3349ead8306f425999f0013e8be36f66", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "MapView(basemaps=['dark-gray', 'dark-gray-vector', 'gray', 'gray-vector', 'hybrid', 'national-geographic', 'oc…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "m2= GIS().map('United States', zoomlevel=4)\n", - "m2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![map of US diamonds](http://esri.github.io/arcgis-python-api/notebooks/nbimages/13_3_map_dfplot1.png)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "m2.center=[39,-98]\n", - "df.spatial.plot(map_widget=m2,\n", - " symbol_type='simple',\n", - " symbol_style='d', # d - for diamonds\n", - " colors='Reds_r',\n", - " cstep=10,\n", - " outline_color='Blues',\n", - " marker_size=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If this type of plotting is new to you, this is a good time to checkout [`matplotlib.pyplot`](https://matplotlib.org/api/pyplot_summary.html) documentation and Pandas dataframe [`plot`](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.plot.html) documentation to get an idea." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Understanding renderers" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the snippets above, you visualized all the features with the same symbology. While this helps understand the geographic distribution of your data, your `Spatially Enabled DataFrame` object can do much more. For instance, you can group the features based on certain attributes that you choose and symbolize each group by a certain color or size or both. To help with this, let us understand the concept of **renderers**.\n", - "\n", - "[`Renderers`](https://developers.arcgis.com/documentation/common-data-types/renderer-objects.htm) define how to visually represent a `feature layer` by defining [`symbols`](https://developers.arcgis.com/documentation/common-data-types/symbol-objects.htm) to represent individual features. The `SeDF` provides you with functionality to control the way features appear by choosing the `symbol` the renderer uses.\n", - "\n", - "Previous versions of the ArcGIS API for Python provided a method to specify a renderer manually, but you had to know details about the renderer before you drew your data. The [`map.add_layer()`]() method did not provide access to all options avialble for rendering datasets. The new visualization capabilities provided by the SDF allow you to draw spatial data quickly and easily with access to more rendering options." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "heading_collapsed": true - }, - "source": [ - "### Supported renderers \n", - "\n", - "The renderering options below are documented in further detail in the [`DatFrame Reference`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html). At a high level, you have the following renderers:\n", - "\n", - "| Renderer \t| Syntax \t| Explanation \t|\n", - "|--------------\t|--------\t|---------------------------------------------------------------------------------------------\t|\n", - "| Simple \t| 's' \t| renders using one symbol only (the examples in [quickstart](#quickstart) above) \t|\n", - "| Unique \t| 'u' \t| renders each unique value with a different symbol. Suitable for categorical columns \t|\n", - "| Unique \t| 'u-a' \t| renders each unique value with a different symbol using arcade expressions. Suitable for categorical columns \t|\n", - "| Class breaks \t| 'c' \t| renders each group of values with a different color or size. Suitable for numerical columns \t|\n", - "| Heatmap \t| 'h' \t| renders density of point data as raster of varying colors \t|" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Visualizing unique values\n", - "Let us explore the major cities census data further and explore if there are any categorical columns" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Index(['AGE_10_14', 'AGE_15_19', 'AGE_20_24', 'AGE_25_34', 'AGE_35_44',\n", - " 'AGE_45_54', 'AGE_55_64', 'AGE_5_9', 'AGE_65_74', 'AGE_75_84',\n", - " 'AGE_85_UP', 'AGE_UNDER5', 'AMERI_ES', 'ASIAN', 'AVE_FAM_SZ',\n", - " 'AVE_HH_SZ', 'BLACK', 'CAPITAL', 'CLASS', 'FAMILIES', 'FEMALES',\n", - " 'FHH_CHILD', 'FID', 'HAWN_PI', 'HISPANIC', 'HOUSEHOLDS', 'HSEHLD_1_F',\n", - " 'HSEHLD_1_M', 'HSE_UNITS', 'MALES', 'MARHH_CHD', 'MARHH_NO_C',\n", - " 'MED_AGE', 'MED_AGE_F', 'MED_AGE_M', 'MHH_CHILD', 'MULT_RACE', 'NAME',\n", - " 'OBJECTID', 'OTHER', 'OWNER_OCC', 'PLACEFIPS', 'POP2010', 'POPULATION',\n", - " 'POP_CLASS', 'RENTER_OCC', 'SHAPE', 'ST', 'STFIPS', 'VACANT', 'WHITE'],\n", - " dtype='object')" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df.columns" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `ST` column contains state names in abbreviation is a good candidate. We could symbolize the points such that all which fall under the same state get the same symbol:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "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", - "
STNAME
0AZSomerton
1CAAnderson
2CACamp Pendleton South
3CACitrus
4CACommerce
\n", - "
" - ], - "text/plain": [ - " ST NAME\n", - "0 AZ Somerton\n", - "1 CA Anderson\n", - "2 CA Camp Pendleton South\n", - "3 CA Citrus\n", - "4 CA Commerce" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df[['ST', 'NAME']].head()" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "cf6bd3abe4ec4689828e9aa41c6dd070", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "MapView(basemaps=['dark-gray', 'dark-gray-vector', 'gray', 'gray-vector', 'hybrid', 'national-geographic', 'oc…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "gis = GIS()\n", - "m3 = gis.map('Reno, NV', zoomlevel=4)\n", - "m3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![unique value renderer](http://esri.github.io/arcgis-python-api/notebooks/nbimages/guide_sdf_unique_value_renderer_1.png)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df.spatial.plot(map_widget = m3,\n", - " renderer_type='u', # specify the unique value renderer using its notation 'u'\n", - " col='ST' # column to get unique values from\n", - " )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By default, the API picks a unique color from the [`jet`](https://matplotlib.org/tutorials/colors/colormaps.html) colormap for each category (US State names in this case) and assigns it. You can override this by choosing your own colormap (`prism` for instance) and customizing the symbol style, symbol type, outline color, thickness, transparency etc. Keep reading to learn more about these customizations.\n", - "\n", - "It is a good cartographic practice to not have too many unique values in your legend. Human eyes can only preceive so many colors and there are only a limited number of colors to choose from in a given color map before the colors become indistinguishable.\n", - "\n", - "As a safe practice, the Python API caps the maximum number of unique values to `256`, the remaining are generalized and plotted with a default color. If you have several unique values, you should consider picking a different column that better represents your data or consider using a different renderer." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Visualizing Unique Values with Arcade Expressions\n", - "\n", - "Arcade is an expression language that can be used across the ArcGIS Platform. Whether writing simple scripts to control how features are rendered, or expressions to control label text, Arcade provides a simple scripting syntax to deliver these capabilities.\n", - "\n", - "In the sense of visualization, Arcade expressions are used to create rich and dynamic symbology. This example will follow the [JavaScript guide](https://developers.arcgis.com/javascript/latest/guide/arcade/index.html#visualization).\n", - "\n", - "#### Obtain the Data\n", - "\n", - "Access the enterprise to gain access to the FeatureLayer information and query it into a `Spatially Enabled DataFrame`." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from arcgis.gis import GIS\n", - "gis = GIS()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "item = gis.content.get(\"8444e275037549c1acab02d2626daaee\")\n", - "flayer = item.layers[0]\n", - "df = flayer.query().sdf" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "fs = flayer.query()\n" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "from arcgis.geometry import Geometry\n", - "g = Geometry(fs.features[0].geometry)\n", - "g.as_arcpy\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Write out the Arcade Expressions and Stops\n", - "\n", - "Arcade expressions require the stops to be manually provided. In this case, we first create an opacity visual variable based on a percent of dominate parties in registered citizens." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "opacity_expression = (\"var republican = $feature.MP06025a_B;var democrat = $feature.MP06024a_B;\"\n", - " \"var independent = $feature.MP06026a_B;var parties = [republican, democrat, independent];\"\n", - " \"var total = Sum(parties);var max = Max(parties);return (max / total) * 100;\")\n", - "opacity_stops = [\n", - " { \"value\": 33, \"transparency\": 0.05 * 255, \"label\": \"< 33%\" },\n", - " { \"value\": 44, \"transparency\": 1.0 * 255, \"label\": \"> 44%\" }]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next we develop another Arcade expression to obtain the majority party in a given county." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "arcade_expression = (\"var republican = $feature.MP06025a_B;var democrat = $feature.MP06024a_B;\"\n", - " \"var independent = $feature.MP06026a_B;var parties = [republican, democrat, independent];\"\n", - " \"return Decode( Max(parties),republican, 'republican', democrat, 'democrat',independent, \"\n", - " \"'independent','n/a' );\")\n", - "uv = [{\"label\":\"Democrat\",\"symbol\":{\"type\":\"esriSFS\",\"color\":[0,195,255,255],\n", - " \"outline\":{\"type\":\"esriSLS\",\"color\":[0,0,0,51],\n", - " \"width\":0.5,\"style\":\"esriSLSSolid\"},\n", - " \"style\":\"esriSFSSolid\"},\"value\":\"democrat\"},\n", - " {\"label\":\"Republican\",\"symbol\":{\"type\":\"esriSFS\",\"color\":[255,0,46,255],\"outline\":{\n", - " \"type\":\"esriSLS\",\"color\":[0,0,0,51],\"width\":0.5,\"style\":\"esriSLSSolid\"},\n", - " \"style\":\"esriSFSSolid\"},\"value\":\"republican\"},\n", - " {\"label\":\"Independent/other party\",\"symbol\":{\"type\":\"esriSFS\",\"color\":[250,255,0,255],\n", - " \"outline\":{\"type\":\"esriSLS\",\"color\":[0,0,0,51],\n", - " \"width\":0.5,\"style\":\"esriSLSSolid\"},\n", - " \"style\":\"esriSFSSolid\"},\"value\":\"independent\"}]" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ff6f41f4452045c99400e39e91a879cb", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "MapView(basemaps=['dark-gray', 'dark-gray-vector', 'gray', 'gray-vector', 'hybrid', 'national-geographic', 'oc…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "gis = GIS()\n", - "m3_ua = gis.map('United States', zoomlevel=4)\n", - "m3_ua" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualize the Data\n", - "\n", - "Provide the color scheme, and the `arcade_expression` to render the data in a dynamic/rich form." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df.spatial.plot(colors='coolwarm',\n", - " map_widget=m3_ua,\n", - " renderer_type='u-a',\n", - " unique_values=uv,\n", - " opacity_stops=opacity_stops,\n", - " opacity_expression=opacity_expression,\n", - " arcade_expression=arcade_expression)" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'type': 'extent',\n", - " 'xmin': -16105138.185829269,\n", - " 'ymin': 2814150.199672489,\n", - " 'xmax': -6546229.176600808,\n", - " 'ymax': 6727726.047872473,\n", - " 'spatialReference': {'wkid': 102100, 'latestWkid': 3857}}" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "m3_ua.extent" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Visualizing classes with different colors\n", - "Often, you may want to classify the numerical values in your data into groups and visualize them on a map. You can accomplish this with a **class break renderer** which splits your data into specific number of groups and uses **color** to differentiate each group. You can choose the algorithm that performs the class splits or go with the defualt.\n", - "\n", - "Let us visualize the same major cities point dataset using its `POPULATION` column." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df[['ST', 'NAME', 'POPULATION']].head()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m4 = gis.map('Reno, NV', zoomlevel=4)\n", - "m4" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![class color renderer](http://esri.github.io/arcgis-python-api/notebooks/nbimages/guide_sdf_class_breaks_color_1.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df.spatial.plot(map_widget=m4,\n", - " renderer_type='c', # for class breaks renderer\n", - " method='esriClassifyNaturalBreaks', # classification algorithm\n", - " class_count=20, # choose the number of classes\n", - " col='POPULATION', # numeric column to classify\n", - " cmap='prism', # color map to pick colors from for each class\n", - " alpha=0.7 # specify opacity\n", - " )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can take this further by plotting a histogram of the same `POPULATION` column and try to match the colors. To get the class breaks for the above map, you can inspect the layer definition from `MapView` object as shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m4.layers" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dict(m4.layers[0].layer.layerDefinition.drawingInfo.renderer).keys()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "class_breaks = m4.layers[0].layer.layerDefinition.drawingInfo.renderer.classBreakInfos\n", - "print(len(class_breaks))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can loop through each of the class breaks and obtain the min, max values and the colors for each class." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cbs_list = []\n", - "cmap_list = []\n", - "for cb in class_breaks:\n", - " print(cb.description) # print the class break labels\n", - " cbs_list.append(cb.classMaxValue)\n", - " cmap_list.append([x/255.0 for x in cb.symbol.color])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that we have the individual class splits and the colors, we can plot a histogram using the same breaks and colors." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "# build a histogram for the same class breaks\n", - "n, bins, patches = plt.hist(df['POPULATION'], bins=cbs_list)\n", - "\n", - "# apply the same color for each class to match the map\n", - "idx = 0\n", - "for c, p in zip(bins, patches):\n", - " plt.setp(p, 'facecolor', cmap_list[idx])\n", - " idx+=1\n", - "\n", - "plt.title('Histogram of POPULATION column')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The shape and color of the bars in the histogram match with the number and color of major cities drawn on the map.\n", - "\n", - "Thus using the `Spatially Enabled DataFrame` we can easily visualize both the spatial and numeric distribution of data using the same symbology." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "heading_collapsed": true - }, - "source": [ - "## Colormaps and Colors\n", - "The examples above use the default colormap `jet`. However you can customize them by using the `colors` paramater. You can specify colors as:\n", - " * a string representing [named colors](https://matplotlib.org/examples/color/named_colors.html)\n", - " * an array of [RGB](http://www.tomjewett.com/colors/rgb.html) values\n", - " * a named [color ramp](https://matplotlib.org/examples/color/colormaps_reference.html). \n", - "\n", - "#### Color Array\n", - "\n", - "RGB + Alpha values can be used to create colors for symbols called in the `plot` method. RGB stands for red, green, and blue respectively. Each RGB value is a value between 0-255, and the alpha value is a number between 0-255.\n", - "\n", - "**Example to produce :**\n", - "\n", - " color = [255,0,100,1]\n", - "\n", - "The above example produces a purplish color. Many websites provide details about using colors. For example, see [here](https://www.rapidtables.com/web/color/RGB_Color.html) for a color codes chart.\n", - "\n", - "#### Color Maps\n", - "\n", - "A color map is a collection of string values that can be given to generate a series of related colors from a defined set.\n", - "\n", - "Color maps can be viewed here: https://matplotlib.org/examples/color/colormaps_reference.html\n", - "\n", - "#### Color Map Helpers\n", - "\n", - "To better understand the syntax for each input type, the ArcGIS API for Python provides some helper functions:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "hidden": true - }, - "outputs": [], - "source": [ - "from arcgis.mapping import display_colormaps" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "hidden": true - }, - "source": [ - "The **display_colormaps** function provides a quick, easy way to visualize the pre-defined set of colormaps you can use. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "hidden": true - }, - "outputs": [], - "source": [ - "display_colormaps()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "hidden": true - }, - "source": [ - "![colormap display](http://esri.github.io/arcgis-python-api/notebooks/nbimages/13_display_colormaps.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "hidden": true - }, - "source": [ - "You can retrieve a list of colormaps as well:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "hidden": true - }, - "outputs": [], - "source": [ - "from arcgis.mapping import symbol\n", - "\n", - "colormaps = symbol.ALLOWED_CMAPS\n", - "for a,b,c,d,e in zip(colormaps[::5], colormaps[1::5], colormaps[2::5], colormaps[3::5], colormaps[4::5]):\n", - " print(\"{:<20}{:<20}{:<20}{:<20}{:<}\".format(a,b,c,d,e))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "hidden": true - }, - "source": [ - "You can enter a list of color ramp names as input to the `display_colormaps` function to filter the output:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "hidden": true - }, - "outputs": [], - "source": [ - "display_colormaps(['Greens_r', 'PRGn', 'Dark2', 'Set1'])" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "hidden": true - }, - "source": [ - "![selected color ramps](http://esri.github.io/arcgis-python-api/notebooks/nbimages/13_selected_colormaps.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "hidden": true - }, - "source": [ - "The examples above used `jet` which is the default and some used `prism` both of which can be seen in the list above. You can customize your charts by using a different colormap of your choice." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Symbology for Simple Renderers\n", - "\n", - "The ArcGIS API for Python provides you the ability to set symbol types so you control data appearance. The [`show_styles`]() function in the `arcgis.mapping` module assists you with the syntax to define symbols.\n", - "\n", - "#### Getting the different symbol styles" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from arcgis.mapping import show_styles" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# get the styles that are relevant to the current geometry type (points)\n", - "show_styles(df.spatial.geometry_type[0]) # the DataFrame in this example is of Point type" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "show_styles('Polygon')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "show_styles('Line')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For instance, you can represent the same set of points using square symbols instead of default circle using the snippet shown below:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m7 = GIS().map('United States', 4)\n", - "m7" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![map of US squares](http://esri.github.io/arcgis-python-api/notebooks/nbimages/13_4_map_dfplot2.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m7.center = [39, -98]\n", - "df.spatial.plot(map_widget=m7,\n", - " symbol_type='simple',\n", - " symbol_style='s', # for square\n", - " cmap='Greens_r', # color map is Greens_r for green reversed\n", - " cstep=35, # the individual color in the colormap\n", - " outline_color='binary',\n", - " marker_size=5,\n", - " line_width=.5,)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Visualizing line features using simple symbols\n", - "Let us search for USA freeway layer and visualize it by looping through the different line symbols" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "search_result = gis.content.search('title:USA freeway system AND owner:esri', \n", - " item_type = 'Feature Layer')\n", - "freeway_item = search_result[0]\n", - "freeway_item" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "freeway_sdf = freeway_item.layers[0].query().sdf\n", - "freeway_sdf.head()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m8 = gis.map('USA', 10)\n", - "m8" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](http://esri.github.io/arcgis-python-api/notebooks/nbimages/guide_sdf_lines_animated_1.gif)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m8.center=[34.05,-118.2]\n", - "m8.zoom=12\n", - "m8.basemap='dark-gray'" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import time\n", - "for row, style in show_styles('Line').iterrows():\n", - " m8.remove_layers()\n", - " time.sleep(1) # sleep for 1 second so animation can finish\n", - " print(style['ESRI_STYLE'] + \" : \" + style['MARKER'])\n", - " freeway_sdf.spatial.plot(map_widget=m8,\n", - " cmap='Spectral', # user a different color map\n", - " symbol_type='simple',\n", - " symbol_style=style['MARKER']\n", - " )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Visualizing area features using different symbols" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from arcgis.features import FeatureLayer\n", - "fl = FeatureLayer(\"https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/2\")\n", - "county_sdf = fl.query(\"STATE_NAME='Washington'\", out_sr=4326).sdf\n", - "county_sdf.head()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m9 = gis.map('Seattle, WA', zoomlevel=6)\n", - "m9.basemap='gray'\n", - "m9" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](http://esri.github.io/arcgis-python-api/notebooks/nbimages/guide_sdf_animate_polygons_1.gif)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for idx, style in show_styles('Polygon').iterrows():\n", - " m9.remove_layers()\n", - " time.sleep(0.5)\n", - " \n", - " print(style['ESRI_STYLE'] + \" : \" + style['MARKER'])\n", - " county_sdf.spatial.plot(map_widget=m9,\n", - " cmap = 'RdPu', # use a red to purple color map\n", - " symbol_type='simple',\n", - " symbol_style=style['MARKER'],\n", - " outline_style='s',\n", - " outline_color=[0,0,0,255],\n", - " line_width=1.0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Conclusion**\n", - "\n", - "\n", - "The `Spatially Enabled DataFrame` gives you powerful visualization capabilities that allows you to plot your data on the interactive map widget. You specify colors and symbols using the same syntax that you would specify for a normal Pandas or a matplotlib plot." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.6.5" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/guide/05-working-with-the-spatial-dataframe/data.zip b/guide/05-working-with-the-spatially-enabled-dataframe/data.zip similarity index 100% rename from guide/05-working-with-the-spatial-dataframe/data.zip rename to guide/05-working-with-the-spatially-enabled-dataframe/data.zip diff --git a/guide/05-working-with-the-spatial-dataframe/introduction-to-the-spatial-dataframe.ipynb b/guide/05-working-with-the-spatially-enabled-dataframe/introduction-to-the-spatially-enabled-dataframe.ipynb similarity index 87% rename from guide/05-working-with-the-spatial-dataframe/introduction-to-the-spatial-dataframe.ipynb rename to guide/05-working-with-the-spatially-enabled-dataframe/introduction-to-the-spatially-enabled-dataframe.ipynb index 9a02af7f1c..76cbc94bbf 100644 --- a/guide/05-working-with-the-spatial-dataframe/introduction-to-the-spatial-dataframe.ipynb +++ b/guide/05-working-with-the-spatially-enabled-dataframe/introduction-to-the-spatially-enabled-dataframe.ipynb @@ -4,11 +4,22 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Introduction to the Spatial Enabled DataFrame\n", + "# Introduction to the Spatially Enabled DataFrame\n", "\n", - "The [`Spatially Enabled Dataframe`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#spatialdataframe) (SEDF) creates a simple, intutive object that can easily manipulate geometric and attribute data. The Spatially Enabled DataFrame is a custom namespace that is inserted into the popular [Pandas](https://pandas.pydata.org/) [DataFrame](http://pandas.pydata.org/pandas-docs/stable/dsintro.html#dataframe) structure with spatial abilities, allowing you to use intutive, pandorable operations on both the attribute and spatial columns. Thus the SEDF is based on data structures inherently suited to data analysis, with natural operations for the filtering and inspecting of subsets of values which are fundamental to statistical and geographic manipulations.\n", + "The [`Spatially Enabled DataFrame`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#spatialdataframe) (SEDF) creates a simple, intutive object that can easily manipulate geometric and attribute data.\n", "\n", - "The dataframe reads from many **sources**, including shapefiles, [Pandas](https://pandas.pydata.org/) [DataFrames](http://pandas.pydata.org/pandas-docs/stable/dsintro.html#dataframe), feature classes, GeoJSON, and Feature Layers.\n", + "
\n", + " New at version 1.5, the Spatially Enabled DataFrame is an evolution of the SpatialDataFrame object that you may be familiar with. While the SDF object is still avialable for use, the team has stopped active development of it and is promoting the use of this new Spatially Enabled DataFrame pattern. The SEDF provides you better memory management, ability to handle larger datasets and is the pattern that Pandas advocates as the path forward.
\n", + "\n", + "The Spatially Enabled DataFrame inserts a custom namespace called `spatial` into the popular [Pandas](https://pandas.pydata.org/) [DataFrame](http://pandas.pydata.org/pandas-docs/stable/dsintro.html#dataframe) structure to give it spatial abilities. This allows you to use intutive, pandorable operations on both the attribute and spatial columns. Thus, the SEDF is based on data structures inherently suited to data analysis, with natural operations for the filtering and inspecting of subsets of values which are fundamental to statistical and geographic manipulations.\n", + "\n", + "The dataframe reads from many **sources**, including shapefiles, [Pandas](https://pandas.pydata.org/) [DataFrames](http://pandas.pydata.org/pandas-docs/stable/dsintro.html#dataframe), feature classes, GeoJSON, and Feature Layers." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "\n", "This document outlines some fundamentals of using the `Spatially Enabled DataFrame` object for working with GIS data.\n", "\n", @@ -16,10 +27,10 @@ " * [Reading Web Layers](#Reading-Web-Layers)\n", " * [Reading Feature Layer Data](#Reading-Feature-Layer-Data)\n", " * [Examining Feature Layer Content](#Example:-Examining-Feature-Layer-content)\n", - " * [Example: Feature Layer Query Results to a Spatial DataFrame](#Example:-Feature-Layer-Query-Results-to-a-Spatial-DataFrame)\n", + " * [Example: Feature Layer Query Results to a Spatial DataFrame](#Example:-Feature-Layer-Query-Results-to-a-Spatially-Enabled-DataFrame)\n", "* [Accessing local GIS Data](#Accessing-local-GIS-data)\n", " * [Example: Reading a Shapefile](#Example:-Reading-a-Shapefile)\n", - "* [Saving Spatial DataFrames](#Saving-Spatial-DataFrames)\n", + "* [Saving Spatiall Enabled DataFrames](#Saving-Spatially-Enabled-DataFrames)\n", " * [Export Options](#Export-Options)\n", " * [Exporting to a Feature Class](#Export-to-Feature-Class)\n", " * [Example: Export a whole dataset to a Shapefile](#Example:-Export-a-whole-dataset-to-a-shapefile:)\n", @@ -43,22 +54,25 @@ "## Accessing GIS data\n", "GIS users need to work with both published layers on remote servers (web layers) and local data, but the ability to manipulate these datasets without permanentently copying the data is lacking. The `Spatial Enabled DataFrame` solves this problem because it is an in-memory object that can read, write and manipulate geospatial data.\n", "\n", - "The SEDF integrates with Esri's [`ArcPy site-package`](http://pro.arcgis.com/en/pro-app/arcpy/get-started/what-is-arcpy-.htm) as well as the open source [`pyshp`](https://github.com/GeospatialPython/pyshp/), [`shapely`](https://github.com/Toblerity/Shapely) and [`fiona`](https://github.com/Toblerity/Fiona) packages. This means the ArcGIS API for Python SEDF can use either of these geometry engines to provide you options for easily working with geospatial data regardless of your platform. The SEDF transforms data into the formats you desire so you can use Python functionality to analyze and visualize geographic information.\n", - "\n", - "Data can be read and scripted to automate workflows and just as easily visualized on maps in [`Jupyter notebooks`](../using-the-jupyter-notebook-environment/). The SEDF can export data as feature classes or publish them directly to servers for sharing according to your needs.\n", - "\n", - "Let's explore some of the different options available with the versatile `Spatial Enabled DataFrame` namespaces:\n", + "The SEDF integrates with Esri's [`ArcPy` site-package](http://pro.arcgis.com/en/pro-app/arcpy/get-started/what-is-arcpy-.htm) as well as the open source [`pyshp`](https://github.com/GeospatialPython/pyshp/), [`shapely`](https://github.com/Toblerity/Shapely) and [`fiona`](https://github.com/Toblerity/Fiona) packages. This means the ArcGIS API for Python SEDF can use either of these geometry engines to provide you options for easily working with geospatial data regardless of your platform. The SEDF transforms data into the formats you desire so you can use Python functionality to analyze and visualize geographic information.\n", "\n", + "Data can be read and scripted to automate workflows and just as easily visualized on maps in [`Jupyter notebooks`](../using-the-jupyter-notebook-environment/). The SEDF can export data as feature classes or publish them directly to servers for sharing according to your needs. Let's explore some of the different options available with the versatile `Spatial Enabled DataFrame` namespaces:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "### Reading Web Layers\n", "\n", - "[`Feature layers`](https://doc.arcgis.com/en/arcgis-online/share-maps/hosted-web-layers.htm) hosted on [**ArcGIS Online**](https://www.arcgis.com) or [**ArcGIS Enterprise**](http://enterprise.arcgis.com/en/) can be easily read into a Spatial DataFrame using the [`from_layer`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#arcgis.features.SpatialDataFrame.from_layer) method. Once you read it into a SEDF object, you can create reports, manipulate the data, or convert it to a form that is comfortable and makes sense for its intended purpose.\n", + "[`Feature layers`](https://doc.arcgis.com/en/arcgis-online/share-maps/hosted-web-layers.htm) hosted on [**ArcGIS Online**](https://www.arcgis.com) or [**ArcGIS Enterprise**](http://enterprise.arcgis.com/en/) can be easily read into a Spatially Enabled DataFrame using the [`from_layer`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html?highlight=from_layer#arcgis.features.GeoAccessor.from_layer) method. Once you read it into a SEDF object, you can create reports, manipulate the data, or convert it to a form that is comfortable and makes sense for its intended purpose.\n", "\n", "**Example: Retrieving an ArcGIS Online [`item`](https://developers.arcgis.com/rest/users-groups-and-items/publish-item.htm) and using the [`layers`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.gis.toc.html#layer) property to inspect the first 5 records of the layer**" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -263,7 +277,7 @@ "[5 rows x 51 columns]" ] }, - "execution_count": 2, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -273,18 +287,53 @@ "gis = GIS()\n", "item = gis.content.get(\"85d0ca4ea1ca4b9abf0c51b9bd34de2e\")\n", "flayer = item.layers[0]\n", + "\n", + "# create a Spatially Enabled DataFrame object\n", "sdf = pd.DataFrame.spatial.from_layer(flayer)\n", "sdf.head()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you inspect the `type` of the object, you get back a standard pandas `DataFrame` object. However, this object now has an additional `SHAPE` column that allows you to perform geometric operations. In other words, this `DataFrame` is now geo-aware." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "pandas.core.frame.DataFrame" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(sdf)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Further, the `DataFrame` has a new `spatial` property that provides a list of geoprocessing operations that can be performed on the object. The rest of the guides in this section go into details of how to use these functionalities. So, sit tight." + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Reading Feature Layer Data\n", "\n", - "As seen above, the SEDF can consume a `Feature Layer` service accessible on the ArcGIS Online platform. Let's take a step-by-step approach to break down the notebook cell above and then extract a subset of records from the feature layer.\n", - "\n", + "As seen above, the SEDF can consume a `Feature Layer` served from either ArcGIS Online or ArcGIS Enterprise orgs. Let's take a step-by-step approach to break down the notebook cell above and then extract a subset of records from the feature layer.\n", "\n", "#### Example: Examining Feature Layer content" ] @@ -298,7 +347,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -316,7 +365,7 @@ " \n", "
This layer presents the locations of cities within the United States with populations of approximately 10,000 or greater, all state capitals, and the national capital.Feature Layer Collection by esri_dm\n", "
Last Modified: December 21, 2017\n", - "
3 comments, 291,531 views\n", + "
3 comments, 331,873 views\n", " \n", " \n", " " @@ -325,7 +374,7 @@ "" ] }, - "execution_count": 3, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -338,7 +387,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -543,7 +592,7 @@ "[5 rows x 51 columns]" ] }, - "execution_count": 4, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -570,15 +619,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "You can also use sql queries to return a subset of records by leveraging the ArcGIS API for Python's [`Feature Layer`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#featurelayer) object itself. Instantiate a Pandas `DataFrame` directly from the [`FeatureLayer.query()`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#arcgis.features.FeatureLayer.query) method and use the data frame's [`head()`](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.core.groupby.GroupBy.head.html#pandas.core.groupby.GroupBy.head) method to return the first 5 records and a subset of columns from the DataFrame:\n", - "\n", - "#### Example: Feature Layer Query Results to a Spatial DataFrame" + "You can also use sql queries to return a subset of records by leveraging the ArcGIS API for Python's [`Feature Layer`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#featurelayer) object itself. When you run a [`query()`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#arcgis.features.FeatureLayer.query) on a `FeatureLayer`, you get back a `FeatureSet` object. Calling the `sdf` property of the `FeatureSet` returns a Spatially Enabled DataFrame object. We then use the data frame's [`head()`](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.core.groupby.GroupBy.head.html#pandas.core.groupby.GroupBy.head) method to return the first 5 records and a subset of columns from the DataFrame:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ + "#### Example: Feature Layer Query Results to a Spatially Enabled DataFrame\n", "We'll use the `AGE_45_54` column to query the dataframe and return a new `DataFrame` with a subset of records. We can use the built-in [`zip()`](https://docs.python.org/3/library/functions.html#zip) function to print the data frame attribute field names, and then use data frame syntax to view specific attribute fields in the output:" ] }, @@ -716,12 +764,12 @@ "\n", "The SEDF can also access local geospatial data. Depending upon what Python modules you have installed, you'll have access to a wide range of functionality: \n", "\n", - "* If the **`ArcPy`** module is installed, meaning you have installed [`ArcGIS Pro`](http://pro.arcgis.com/en/pro-app/) and have installed the ArcGIS API for Python in that same environment, the `SpatialDataFrame` has methods to read a subset of the ArcGIS Desktop [supported geographic formats](http://desktop.arcgis.com/en/arcmap/10.3/manage-data/datatypes/about-geographic-data-formats.htm#ESRI_SECTION1_4835793C55C0439593A46FD5BC9E64B9), most notably:\n", + "* If the **`ArcPy`** module is installed, meaning you have installed [`ArcGIS Pro`](http://pro.arcgis.com/en/pro-app/) and have installed the ArcGIS API for Python in that same environment, the `DataFrame` then has methods to read a subset of the ArcGIS Desktop [supported geographic formats](http://desktop.arcgis.com/en/arcmap/10.3/manage-data/datatypes/about-geographic-data-formats.htm#ESRI_SECTION1_4835793C55C0439593A46FD5BC9E64B9), most notably:\n", " * [`feature classes`](http://desktop.arcgis.com/en/arcmap/latest/manage-data/feature-classes/a-quick-tour-of-feature-classes.htm)\n", " * [`shapefiles`](http://desktop.arcgis.com/en/arcmap/latest/manage-data/shapefiles/what-is-a-shapefile.htm), \n", " * [`ArcGIS Server Web Services`](https://enterprise.arcgis.com/en/server/latest/publish-services/windows/what-types-of-services-can-you-publish.htm) and [`ArcGIS Online Hosted Feature Layers`](https://doc.arcgis.com/en/arcgis-online/share-maps/publish-features.htm) \n", " * [`OGC Services`](http://www.opengeospatial.org/standards) \n", - "* If the **ArcPy** module is not installed, the SEDF [`from_featureclass`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#arcgis.features.SpatialDataFrame.from_featureclass) method only supports consuming an Esri [`shapefile`](http://desktop.arcgis.com/en/arcmap/latest/manage-data/shapefiles/what-is-a-shapefile.htm)\n", + "* If the **ArcPy** module is not installed, the SEDF [`from_featureclass`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html?arcgis.features.GeoAccessor.from_featureclass#arcgis.features.GeoAccessor.from_featureclass) method only supports consuming an Esri [`shapefile`](http://desktop.arcgis.com/en/arcmap/latest/manage-data/shapefiles/what-is-a-shapefile.htm)\n", "> Please note that you must install the `pyshp` package to read shapefiles in environments that don't have access to `ArcPy`.\n", " \n", "### Example: Reading a Shapefile\n", @@ -882,9 +930,7 @@ } ], "source": [ - "sdf = (pd.DataFrame\n", - " .spatial\n", - " .from_featureclass(\"path\\to\\your\\data\\census_example\\cities.shp\"))\n", + "sdf = pd.DataFrame.spatial.from_featureclass(\"path\\to\\your\\data\\census_example\\cities.shp\")\n", "sdf.tail()" ] }, @@ -892,7 +938,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Saving Spatial DataFrames\n", + "## Saving Spatially Enabled DataFrames\n", "\n", "The SEDF can export data to various data formats for use in other applications.\n", "\n", @@ -931,9 +977,7 @@ } ], "source": [ - "(sdf\n", - " .spatial\n", - " .to_featureclass(location=r\"c:\\output_examples\\census.shp\"))" + "sdf.spatial.to_featureclass(location=r\"c:\\output_examples\\census.shp\")" ] }, { @@ -987,9 +1031,7 @@ ], "source": [ "columns = ['NAME', 'ST', 'CAPITAL', 'STFIPS', 'POP2000', 'POP2007', 'SHAPE']\n", - "(sdf[columns].head()\n", - " .spatial\n", - " .to_featureclass(location=r\"/path/to/your/data/directory/sdf_head_output.shp\"))" + "sdf[columns].head().spatial.to_featureclass(location=r\"/path/to/your/data/directory/sdf_head_output.shp\")" ] } ], @@ -1009,7 +1051,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.6" } }, "nbformat": 4, diff --git a/guide/05-working-with-the-spatial-dataframe/advanced-topics.ipynb b/guide/05-working-with-the-spatially-enabled-dataframe/spatially-enabled-dataframe-advanced-topics.ipynb similarity index 95% rename from guide/05-working-with-the-spatial-dataframe/advanced-topics.ipynb rename to guide/05-working-with-the-spatially-enabled-dataframe/spatially-enabled-dataframe-advanced-topics.ipynb index eed1c4c29d..098fa1e876 100644 --- a/guide/05-working-with-the-spatial-dataframe/advanced-topics.ipynb +++ b/guide/05-working-with-the-spatially-enabled-dataframe/spatially-enabled-dataframe-advanced-topics.ipynb @@ -4,15 +4,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Advanced Topics\n", + "# Spatially Enabled DataFrames - Advanced Topics\n", "\n", "The information in this section provides a brief introduction to advanced topics with the `Spatially Enabled DataFrame` structure. \n", "\n", "One of the most important tasks for software applications is to quickly retrieve and process information. Enterprise systems, whether storing GIS information or not, all utilize the concept of indexing to allow for quick searching through large data stores to locate and select specific information for subsequent processing. \n", "\n", - "This document will outline how row and column indexing work in the Spatial Dataframe and also demonstrate building a spatial index on dataframe geometries to allow for quick searching, accessing, and processing. The document will also demonstrate spatial joins to combine dataframes.\n", + "This document will outline how row and column indexing work in Spatially Enabled Dataframes and also demonstrate building a spatial index on dataframe geometries to allow for quick searching, accessing, and processing. The document will also demonstrate spatial joins to combine dataframes.\n", "\n", - " * [Dataframe Index](#Dataframe-Index)\n", + " * [DataFrame Index](#DataFrame-Index)\n", + " * [Slicing DataFrames](#Slicing-DataFrames)\n", " * [Spatial Index](#Spatial-Index)\n", " * [Intersection with the Spatial Index](#Intersection-with-the-Spatial-Index)\n", " * [Spatial Joins](#Spatial-Joins)\n", @@ -23,10 +24,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Dataframe Index\n", - "As mentioned in the [Introduction to the spatial dataframe guide](../introduction-to-the-spatial-dataframe), the Pandas [dataframe structure](https://pandas.pydata.org/pandas-docs/stable/dsintro.html#dataframe) underlies the ArcGIS API for Python Spatial Dataframe. Pandas dataframes are analagous to spreadsheets. They have a row axis and a column axis. Each of these axes are indexed and labeled for quick and easy identification, data alignment, and retrieval and updating of data subsets.\n", + "## DataFrame Index\n", + "As mentioned in the [Introduction to the Spatially Enabled DataFrame guide](../introduction-to-the-spatially-enabled-dataframe), the Pandas [DataFrame structure](https://pandas.pydata.org/pandas-docs/stable/dsintro.html#dataframe) underlies the ArcGIS API for Python's Spatially Enabled DataFrame. Pandas DataFrames are analagous to spreadsheets. They have a row axis and a column axis. Each of these axes are indexed and labeled for quick and easy identification, data alignment, and retrieval and updating of data subsets.\n", "\n", - "Lets explore the axis labels and indices and how they allow for data exploraation:" + "Let's explore the axes labels and indices and how they allow for data exploraation:" ] }, { @@ -43,7 +44,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "When working with an ArcGIS Online feature layer, the [`query()`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#arcgis.features.FeatureLayer.query) method returns a `FeatureSet` object which has a `df` method to instantiate a Spatial Dataframe." + "When working with an ArcGIS Online feature layer, the [`query()`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#arcgis.features.FeatureLayer.query) method returns a `FeatureSet` object which has a `sdf` method to instantiate a Spatially Enabled DataFrame." ] }, { @@ -551,6 +552,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "### Slicing DataFrames\n", "We can access rows, columns and subsets of rows and columns using Python slicing:" ] }, @@ -774,9 +776,9 @@ "metadata": {}, "source": [ "## Spatial Index\n", - "In addition to row and column indices to search a dataframe, we can use a spatial indexes quickly access information based on its location and relationship with other features. They are based on the concept of a minimum bounding rectangle - the smallest rectangle that contains an entire geometric shape. Each of these rectangles are then grouped into `leaf` nodes representing a single shape and `node` structures containing groups of shapes according to whatever algorithm the different types of spatial indexing use. Querying these rectangles requires magnitudes fewer computer resources for accessing and processing geometries relative to accessing the entire feature array of coordinate pairs that compose a shape. Access to points, complex lines and irregularly-shaped polygons becomes much quicker and easier through different flavors of spatial indexing.\n", + "In addition to row and column indices to search a DataFrame, we can use a spatial indexes to quickly access information based on its location and relationship with other features. They are based on the concept of a **minimum bounding rectangle** - the smallest rectangle that contains an entire geometric shape. Each of these rectangles are then grouped into `leaf` nodes representing a single shape and `node` structures containing groups of shapes according to whatever algorithm the different types of spatial indexing use. Querying these rectangles requires magnitudes fewer compute resources for accessing and processing geometries relative to accessing the entire feature array of coordinate pairs that compose a shape. Access to points, complex lines and irregularly-shaped polygons becomes much quicker and easier through different flavors of spatial indexing.\n", "\n", - "The Spatial DataFrame uses an implementation of spatial indexing known as [QuadTree indexing](https://en.wikipedia.org/wiki/Quadtree), which searches nodes when determining locations, relationships and attributes of specific features. QuadTree indexes are the default spatial index, but the SEDF also supports r-tree implementations. In the [**Dataframe Index**](#Datframe-index) section of this notebook, the USA Major Cities feature layer was queried and the `df` method was called on the results to create a data frame. The [`sindex`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.html?highlight=style#arcgis.features.SpatialDataFrame.sindex) method on the `df` creates a quad tree index:" + "The Spatially Enabled DataFrame uses an implementation of spatial indexing known as [QuadTree indexing](https://en.wikipedia.org/wiki/Quadtree), which searches nodes when determining locations, relationships and attributes of specific features. `QuadTree` indexes are the default spatial index, but the SEDF also supports `r-tree` implementations. In the [**DataFrame Index**](#DataFrame-index) section of this notebook, the USA Major Cities feature layer was queried and the `sdf` property was called on the results to create a DataFrame. The [`sindex`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#arcgis.features.GeoAccessor.sindex) method on the DataFrame creates a QuadTree index:" ] }, { @@ -792,7 +794,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's visually inspect the external frame of the Quadtree index. We'll then plot the spatial dataframe to ensure the spatial index encompasses all our features:" + "Let's visually inspect the external frame of the QuadTree index. We'll then plot the spatial dataframe to ensure the spatial index encompasses all our features:" ] }, { @@ -861,7 +863,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's use the feature we drew above to define a spatial reference variable for use throughout the rest of this guide." + "Let's use the feature we drew earlier to define a spatial reference variable for use throughout the rest of this guide." ] }, { @@ -1477,11 +1479,11 @@ "sym_poly = {\n", " \"type\": \"esriSFS\",\n", " \"style\": \"esriSFSSolid\",\n", - " \"color\": [0,0,0,0],\n", + " \"color\": [0,0,0,0], # hollow, no fill\n", " \"outline\": {\n", " \"type\": \"esriSLS\",\n", " \"style\": \"esriSLSSolid\",\n", - " \"color\": [255,0,0,255],\n", + " \"color\": [255,0,0,255], # red border\n", " \"width\": 3}\n", "}\n", "\n", @@ -1512,11 +1514,11 @@ "sym_poly_aoi = {\n", " \"type\": \"esriSFS\",\n", " \"style\": \"esriSFSSolid\",\n", - " \"color\": [0,0,0,0],\n", + " \"color\": [0,0,0,0], # hollow, no fill\n", " \"outline\": {\n", " \"type\": \"esriSLS\",\n", " \"style\": \"esriSLSSolid\",\n", - " \"color\": [0,255,0,255],\n", + " \"color\": [0,255,0,255], # green border\n", " \"width\": 3}\n", "}\n", "\n", @@ -1783,10 +1785,19 @@ "df.iloc[index_of_features]" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us plot these features that intersect on a map:" + ] + }, { "cell_type": "code", "execution_count": 27, - "metadata": {}, + "metadata": { + "scrolled": true + }, "outputs": [ { "data": { @@ -1842,7 +1853,7 @@ "pt_sym = {\n", " \"type\": \"esriSMS\",\n", " \"style\": \"esriSMSDiamond\",\n", - " \"color\": [255,140,0,255], \n", + " \"color\": [255,140,0,255], # yellowish\n", " \"size\": 8,\n", " \"angle\": 0,\n", " \"xoffset\": 0,\n", @@ -1856,18 +1867,25 @@ " m2.draw(shape = df.iloc[pt_index]['SHAPE'], symbol = pt_sym) " ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Thus we were able to use the spatial indexes to query features that fall within an extent." + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Spatial Joins\n", - "Dataframes are table-like structures comprised of rows and columns. In relational database, SQL `joins` are fundamental operations that combine columns from one or more tables using values that are common to each. They occur in almost all database queries.\n", + "DataFrames are table-like structures comprised of rows and columns. In relational database, SQL `joins` are fundamental operations that combine columns from one or more tables using values that are common to each. They occur in almost all database queries.\n", "\n", "A Spatial join is a table operation that affixes data from one feature layer’s attribute table to another based on a spatial relationship. The spatial join involves matching rows from the Join Features (data frame1) to the Target Features (data frame2) based on their spatial relationship.\n", "\n", - "Let's look at how joins work with dataframes by using subsets of our original dataframe and the pandas `merge` fucntionality. We'll then move onto examining a spatial join to combine features from one dataframe with another based on a common attribute value.\n", + "Let's look at how joins work with dataframes by using subsets of our original DataFrame and the pandas `merge` fucntionality. We'll then move onto examining a spatial join to combine features from one dataframe with another based on a common attribute value.\n", "\n", - "Query the dataframe to extract 3 attribute columns of information from 2 states, Ohio and Michigan:" + "Query the DataFrame to extract 3 attribute columns of information from 2 states, Ohio and Michigan:" ] }, { @@ -2507,7 +2525,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Notice how all the rows from the left dataframe appear in the result with all the attribute columns and values appended from the right dataframe where the column value of NAME matched. The `POP2010` attribute from the left dataframe is combined with all the attributes from the right dataframe." + "Notice how all the rows from the left `DataFrame` appear in the result with all the attribute columns and values appended from the right `DataFrame` where the column value of `NAME` matched. The `POP2010` attribute from the left `DataFrame` is combined with all the attributes from the right `DataFrame`." ] }, { @@ -2879,18 +2897,18 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The rows where the on parameter value is the same in both tables have all attributes from both dataframes in the result. The rows from the first dataframe that do not have a matching `NAME` value in the second dataframe have values filled in with NaN values." + "The rows where the on parameter value is the same in both tables have all attributes from both DataFrames in the result. The rows from the first DataFrame that do not have a matching `NAME` value in the second dataframe have values filled in with `NaN` values." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "A spatial join works similarly on matching attribute values.\n", + "A spatial join works similarly on matching attribute values. However, instead of joining on an attribue field (like you did earlier), you will join based on the spatial relationship between the records in the two tables.\n", "\n", "#### Example: Merging State Statistics Information with Cities\n", "\n", - "The goal is to get Wyoming's city locations and census data joined with Wymoing's state census data.\n", + "The goal is to get Wyoming's city locations and census data joined with Wyoming's state census data.\n", "> If you do not have access to the `ArcPy` site-package from the Python interpreter used to execute the following cells, you must authenticate to an ArcGIS Online Organization or ArcGIS Enterprise portal." ] }, @@ -2948,7 +2966,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We will use python's list comprehensions to create lists of the attribute columns in the dataframe, then print out the lists to see the names of all the attribute columns." + "We will use python's list comprehensions to create lists of the attribute columns in the DataFrame, then print out the lists to see the names of all the attribute columns." ] }, { @@ -3036,7 +3054,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Create a dataframe for the cities in Wyoming:" + "Create a DataFrame for the cities in Wyoming:" ] }, { @@ -3703,6 +3721,13 @@ "sdf2" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice, you retain the geometry type of your left DataFrame (points) in this case, however, you get all the attributes from both the left and right DataFrames. Let us plot the results of the spatial join on a map:" + ] + }, { "cell_type": "code", "execution_count": 47, @@ -3755,6 +3780,14 @@ "for idx, row in sdf2.iterrows():\n", " m3.draw(row['SHAPE'], symbol=pt_sym)" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Conclusion\n", + "Spatially Enabled DataFrame give you powerful data analysis and data wrangling capabilities. In addition to performing sql like operations on attribute data, you can perform geographic queries. This guide demonstrated some of these advanced capabilities of the SEDF." + ] } ], "metadata": { @@ -3773,7 +3806,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.6" } }, "nbformat": 4, diff --git a/guide/05-working-with-the-spatially-enabled-dataframe/visualizing-data-with-the-spatially-enabled-dataframe.ipynb b/guide/05-working-with-the-spatially-enabled-dataframe/visualizing-data-with-the-spatially-enabled-dataframe.ipynb new file mode 100644 index 0000000000..09942afb6f --- /dev/null +++ b/guide/05-working-with-the-spatially-enabled-dataframe/visualizing-data-with-the-spatially-enabled-dataframe.ipynb @@ -0,0 +1,1820 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Visualizing Spatial Data\n", + "The Spatially Enabled Dataframe has a [`plot()`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html?arcgis.features.GeoAccessor.from_featureclass#arcgis.features.GeoAccessor.plot) method that uses a syntax and symbology similar to [`matplotlib`](https://matplotlib.org) for visualizing features on a map. With this functionality, you can easily visualize aspects of your data both on a map and on a matplotlib chart using the same symbology!\n", + "\n", + "Some unique characteristics of working with the visualization capabalities on the SDF:\n", + "- Uses Pythonic syntax\n", + "- Uses the same syntax as visualizing charts on Pandas DataFrames\n", + "- Uses symbology familiar to users of matplotlib\n", + "- Works on features and attributes simultaneously, eliminating to a great extent the need to iterate over all features (rows)\n", + "- Handles reading and writing to multiple formats aiding data conversion\n", + "\n", + "Checkout the [Introduction to Spatially Enabled DataFrame](/python/guide/features-module/introduction-to-spatially-enabled-dataframe) guide to learn how to create a Spatially Enabled DataFrame." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this guide, you will learn about:\n", + "\n", + " * [Quickstart](#Quickstart)\n", + " * [Plotting the `DataFarme`](#Plotting-the-SpatialDataFrame)\n", + " * [Understanding renderers](#Understanding-renderers)\n", + " * [Supported renderers](#Supported-renderers)\n", + " * [Visualizing unique values](#Visualizing-unique-values)\n", + " * [Visualizing unique values with Arcade expressions](#Visualizing-Unique-Values-with-Arcade-Expressions)\n", + " * [Visualizing classes with different colors](#Visualizing-classes-with-different-colors)\n", + " * [ColorMaps and Colors](#Colormaps-and-Colors)\n", + " * [Symbology for Simple Renderers](#Symbology-for-Simple-Renderers)\n", + " * [Getting the different symbol styles](#Getting-the-different-symbol-styles)\n", + " * [Visualizing line features suing simple renderers](#Visualizing-line-features-using-simple-symbols)\n", + " * [Visualizing area features using simple renderers](#Visualizing-area-features-using-different-symbols)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Quickstart\n", + "Let us read a census data on major cities and load that into a `Spatially Enabled DataFrame`" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "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", + " \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", + "
AGE_10_14AGE_15_19AGE_20_24AGE_25_34AGE_35_44AGE_45_54AGE_55_64AGE_5_9AGE_65_74AGE_75_84...PLACEFIPSPOP2010POPULATIONPOP_CLASSRENTER_OCCSHAPESTSTFIPSVACANTWHITE
01413138111062138181514119791557525307...0468080142871498061074{\"x\": -12768343.256613126, \"y\": 3842463.708135...AZ042619196
17277386771380118513331087740661444...060204299321023962056{\"x\": -13613950.337588644, \"y\": 4931686.754090...CA062678273
25935112323276774612734122942...0610561106161186962558{\"x\": -13066582.116550362, \"y\": 3925650.676616...CA062967530
3888988900172914791443959766514280...061356010866111956761{\"x\": -13123874.446103057, \"y\": 4044249.710416...CA06865898
41086122810131822175914781112925687477...0614974128231300961763{\"x\": -13151212.145276317, \"y\": 4027601.332347...CA06886930
\n", + "

5 rows × 51 columns

\n", + "
" + ], + "text/plain": [ + " AGE_10_14 AGE_15_19 AGE_20_24 AGE_25_34 AGE_35_44 AGE_45_54 \\\n", + "0 1413 1381 1106 2138 1815 1411 \n", + "1 727 738 677 1380 1185 1333 \n", + "2 593 511 2323 2767 746 127 \n", + "3 888 988 900 1729 1479 1443 \n", + "4 1086 1228 1013 1822 1759 1478 \n", + "\n", + " AGE_55_64 AGE_5_9 AGE_65_74 AGE_75_84 ... PLACEFIPS POP2010 \\\n", + "0 979 1557 525 307 ... 0468080 14287 \n", + "1 1087 740 661 444 ... 0602042 9932 \n", + "2 34 1229 4 2 ... 0610561 10616 \n", + "3 959 766 514 280 ... 0613560 10866 \n", + "4 1112 925 687 477 ... 0614974 12823 \n", + "\n", + " POPULATION POP_CLASS RENTER_OCC \\\n", + "0 14980 6 1074 \n", + "1 10239 6 2056 \n", + "2 11869 6 2558 \n", + "3 11195 6 761 \n", + "4 13009 6 1763 \n", + "\n", + " SHAPE ST STFIPS VACANT WHITE \n", + "0 {\"x\": -12768343.256613126, \"y\": 3842463.708135... AZ 04 261 9196 \n", + "1 {\"x\": -13613950.337588644, \"y\": 4931686.754090... CA 06 267 8273 \n", + "2 {\"x\": -13066582.116550362, \"y\": 3925650.676616... CA 06 296 7530 \n", + "3 {\"x\": -13123874.446103057, \"y\": 4044249.710416... CA 06 86 5898 \n", + "4 {\"x\": -13151212.145276317, \"y\": 4027601.332347... CA 06 88 6930 \n", + "\n", + "[5 rows x 51 columns]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from arcgis import GIS\n", + "gis = GIS()\n", + "# create an anonymous connection to ArcGIS Online and get a public item\n", + "item = gis.content.get(\"85d0ca4ea1ca4b9abf0c51b9bd34de2e\")\n", + "flayer = item.layers[0]\n", + "\n", + "# Specify a SQL query and get a sub-set of the original data as a DataFrame\n", + "df = flayer.query(where=\"AGE_45_54 < 1500\").sdf\n", + "\n", + "# Visualize the top 5 records\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> Note: If the above cell looks new to you, please checkout the [Introduction to Spatially Enabled DataFrame](/python/guide/features-module/introduction-to-spatial-dataframe) guide." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us create a map of the United States" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ea826a65070444b2b88a583b4bb8fb05", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "MapView(basemaps=['dark-gray', 'dark-gray-vector', 'gray', 'gray-vector', 'hybrid', 'national-geographic', 'oc…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "m1 = GIS().map('United States')\n", + "m1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![map of US diamonds](http://esri.github.io/arcgis-python-api/notebooks/nbimages/13_3_map_dfplot1a.png)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "m1.zoom = 4\n", + "m1.center = [39,-98]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plotting the DataFrame\n", + "You can quickly visualize the points by calling the `plot()` method off the `DataFrame`'s `spatial` accessor and passing the map you created above." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.spatial.plot(map_widget= m1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can customize the symbols, their color, shape, border etc. like you would in a typical matplotlib plot. The rest of this guide talks about such customizations and suggestions to visualize your spatial and non-spatial data.\n", + "\n", + "The code below plots the same set of points on a new map using a common structure used amongst many different Python packages for defining symbology. It is built off of the matplotlib libraries for simple, straightforward plotting. We'll explain some of the parameters below, and the [`plot()`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html#arcgis.features.SpatialDataFrame.plot) API Reference outlines more options." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3349ead8306f425999f0013e8be36f66", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "MapView(basemaps=['dark-gray', 'dark-gray-vector', 'gray', 'gray-vector', 'hybrid', 'national-geographic', 'oc…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "m2= GIS().map('United States', zoomlevel=4)\n", + "m2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![map of US diamonds](http://esri.github.io/arcgis-python-api/notebooks/nbimages/13_3_map_dfplot1.png)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m2.center=[39,-98]\n", + "df.spatial.plot(map_widget=m2,\n", + " symbol_type='simple',\n", + " symbol_style='d', # d - for diamonds\n", + " colors='Reds_r',\n", + " cstep=10,\n", + " outline_color='Blues',\n", + " marker_size=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If this type of plotting is new to you, this is a good time to checkout [`matplotlib.pyplot`](https://matplotlib.org/api/pyplot_summary.html) documentation and Pandas dataframe [`plot`](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.plot.html) documentation to get an idea." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Understanding renderers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the snippets above, you visualized all the features with the same symbology. While this helps understand the geographic distribution of your data, your `Spatially Enabled DataFrame` object can do much more. For instance, you can group the features based on certain attributes that you choose and symbolize each group by a certain color or size or both. To help with this, let us understand the concept of **renderers**.\n", + "\n", + "[`Renderers`](https://developers.arcgis.com/documentation/common-data-types/renderer-objects.htm) define how to visually represent a `feature layer` by defining [`symbols`](https://developers.arcgis.com/documentation/common-data-types/symbol-objects.htm) to represent individual features. The `SeDF` provides you with functionality to control the way features appear by choosing the `symbol` the renderer uses.\n", + "\n", + "Previous versions of the ArcGIS API for Python provided a method to specify a renderer manually, but you had to know details about the renderer before you drew your data. The [`map.add_layer()`]() method did not provide access to all options avialble for rendering datasets. The new visualization capabilities provided by the SEDF allow you to draw spatial data quickly and easily with access to more rendering options." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "heading_collapsed": true + }, + "source": [ + "### Supported renderers \n", + "\n", + "The renderering options below are documented in further detail in the [`DatFrame Reference`](https://esri.github.io/arcgis-python-api/apidoc/html/arcgis.features.toc.html?highlight=from_layer#arcgis.features.GeoAccessor.plot). At a high level, you have the following renderers:\n", + "\n", + "| Renderer \t| Syntax \t| Explanation \t|\n", + "|--------------\t|--------\t|---------------------------------------------------------------------------------------------\t|\n", + "| Simple \t| 's' \t| renders using one symbol only (the examples in [quickstart](#quickstart) above) \t|\n", + "| Unique \t| 'u' \t| renders each unique value with a different symbol. Suitable for categorical columns \t|\n", + "| Unique \t| 'u-a' \t| renders each unique value with a different symbol using arcade expressions. Suitable for categorical columns \t|\n", + "| Class breaks \t| 'c' \t| renders each group of values with a different color or size. Suitable for numerical columns \t|\n", + "| Heatmap \t| 'h' \t| renders density of point data as raster of varying colors \t|" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Visualizing unique values\n", + "Let us explore the major cities census data further and explore if there are any categorical columns" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['AGE_10_14', 'AGE_15_19', 'AGE_20_24', 'AGE_25_34', 'AGE_35_44',\n", + " 'AGE_45_54', 'AGE_55_64', 'AGE_5_9', 'AGE_65_74', 'AGE_75_84',\n", + " 'AGE_85_UP', 'AGE_UNDER5', 'AMERI_ES', 'ASIAN', 'AVE_FAM_SZ',\n", + " 'AVE_HH_SZ', 'BLACK', 'CAPITAL', 'CLASS', 'FAMILIES', 'FEMALES',\n", + " 'FHH_CHILD', 'FID', 'HAWN_PI', 'HISPANIC', 'HOUSEHOLDS', 'HSEHLD_1_F',\n", + " 'HSEHLD_1_M', 'HSE_UNITS', 'MALES', 'MARHH_CHD', 'MARHH_NO_C',\n", + " 'MED_AGE', 'MED_AGE_F', 'MED_AGE_M', 'MHH_CHILD', 'MULT_RACE', 'NAME',\n", + " 'OBJECTID', 'OTHER', 'OWNER_OCC', 'PLACEFIPS', 'POP2010', 'POPULATION',\n", + " 'POP_CLASS', 'RENTER_OCC', 'SHAPE', 'ST', 'STFIPS', 'VACANT', 'WHITE'],\n", + " dtype='object')" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.columns" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `ST` column contains state names in abbreviation is a good candidate. We could symbolize the points such that all which fall under the same state get the same symbol:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "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", + "
STNAME
0AZSomerton
1CAAnderson
2CACamp Pendleton South
3CACitrus
4CACommerce
\n", + "
" + ], + "text/plain": [ + " ST NAME\n", + "0 AZ Somerton\n", + "1 CA Anderson\n", + "2 CA Camp Pendleton South\n", + "3 CA Citrus\n", + "4 CA Commerce" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[['ST', 'NAME']].head()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "cf6bd3abe4ec4689828e9aa41c6dd070", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "MapView(basemaps=['dark-gray', 'dark-gray-vector', 'gray', 'gray-vector', 'hybrid', 'national-geographic', 'oc…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "gis = GIS()\n", + "m3 = gis.map('Reno, NV', zoomlevel=4)\n", + "m3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![unique value renderer](http://esri.github.io/arcgis-python-api/notebooks/nbimages/guide_sdf_unique_value_renderer_1.png)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.spatial.plot(map_widget = m3,\n", + " renderer_type='u', # specify the unique value renderer using its notation 'u'\n", + " col='ST' # column to get unique values from\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By default, the API picks a unique color from the [`jet`](https://matplotlib.org/tutorials/colors/colormaps.html) colormap for each category (US State names in this case) and assigns it. You can override this by choosing your own colormap (`prism` for instance) and customizing the symbol style, symbol type, outline color, thickness, transparency etc. Keep reading to learn more about these customizations.\n", + "\n", + "It is a good cartographic practice to not have too many unique values in your legend. Human eyes can only preceive so many colors and there are only a limited number of colors to choose from in a given color map before the colors become indistinguishable.\n", + "\n", + "As a safe practice, the Python API caps the maximum number of unique values to `256`, the remaining are generalized and plotted with a default color. If you have several unique values, you should consider picking a different column that better represents your data or consider using a different renderer." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Visualizing Unique Values with Arcade Expressions\n", + "\n", + "Arcade is an expression language that can be used across the ArcGIS Platform. Whether writing simple scripts to control how features are rendered, or expressions to control label text, Arcade provides a simple scripting syntax to deliver these capabilities.\n", + "\n", + "In the sense of visualization, Arcade expressions are used to create rich and dynamic symbology. This example will follow the [JavaScript guide](https://developers.arcgis.com/javascript/latest/guide/arcade/index.html#visualization).\n", + "\n", + "#### Obtain the Data\n", + "\n", + "Access the enterprise to gain access to the FeatureLayer information and query it into a Spatially Enabled DataFrame." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "item = gis.content.get(\"8444e275037549c1acab02d2626daaee\")\n", + "flayer = item.layers[0]\n", + "df = flayer.query().sdf" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "fset = flayer.query()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from arcgis.geometry import Geometry\n", + "g = Geometry(fset.features[0].geometry)\n", + "g.as_arcpy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Write out the Arcade Expressions and Stops\n", + "\n", + "Arcade expressions require the stops to be manually provided. In this case, we first create an opacity visual variable based on a percent of dominant parties in registered citizens." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "opacity_expression = (\"var republican = $feature.MP06025a_B;var democrat = $feature.MP06024a_B;\"\n", + " \"var independent = $feature.MP06026a_B;var parties = [republican, democrat, independent];\"\n", + " \"var total = Sum(parties);var max = Max(parties);return (max / total) * 100;\")\n", + "opacity_stops = [\n", + " { \"value\": 33, \"transparency\": 0.05 * 255, \"label\": \"< 33%\" },\n", + " { \"value\": 44, \"transparency\": 1.0 * 255, \"label\": \"> 44%\" }]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next we develop another Arcade expression to obtain the majority party in a given county." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "arcade_expression = (\"var republican = $feature.MP06025a_B;var democrat = $feature.MP06024a_B;\"\n", + " \"var independent = $feature.MP06026a_B;var parties = [republican, democrat, independent];\"\n", + " \"return Decode( Max(parties),republican, 'republican', democrat, 'democrat',independent, \"\n", + " \"'independent','n/a' );\")\n", + "uv = [{\"label\":\"Democrat\",\"symbol\":{\"type\":\"esriSFS\",\"color\":[0,195,255,255],\n", + " \"outline\":{\"type\":\"esriSLS\",\"color\":[0,0,0,51],\n", + " \"width\":0.5,\"style\":\"esriSLSSolid\"},\n", + " \"style\":\"esriSFSSolid\"},\"value\":\"democrat\"},\n", + " {\"label\":\"Republican\",\"symbol\":{\"type\":\"esriSFS\",\"color\":[255,0,46,255],\"outline\":{\n", + " \"type\":\"esriSLS\",\"color\":[0,0,0,51],\"width\":0.5,\"style\":\"esriSLSSolid\"},\n", + " \"style\":\"esriSFSSolid\"},\"value\":\"republican\"},\n", + " {\"label\":\"Independent/other party\",\"symbol\":{\"type\":\"esriSFS\",\"color\":[250,255,0,255],\n", + " \"outline\":{\"type\":\"esriSLS\",\"color\":[0,0,0,51],\n", + " \"width\":0.5,\"style\":\"esriSLSSolid\"},\n", + " \"style\":\"esriSFSSolid\"},\"value\":\"independent\"}]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "520b0b29420f4bdaaae0516b03d1637d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "MapView(layout=Layout(height='400px', width='100%'), zoom=4.0)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "gis = GIS()\n", + "m3_ua = gis.map('United States', zoomlevel=4)\n", + "m3_ua" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](http://esri.github.io/arcgis-python-api/notebooks/nbimages/guide_sdf_unique_value_arcade.PNG)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualize the Data\n", + "\n", + "Provide the color scheme, and the `arcade_expression` to render the data in a dynamic/rich form." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.spatial.plot(colors='coolwarm',\n", + " map_widget=m3_ua,\n", + " renderer_type='u-a', # 'u-a' stands for uniqe value with arcade expression\n", + " unique_values=uv,\n", + " opacity_stops=opacity_stops,\n", + " opacity_expression=opacity_expression,\n", + " arcade_expression=arcade_expression)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Visualizing classes with different colors\n", + "Often, you may want to classify the numerical values in your data into groups and visualize them on a map. You can accomplish this with a **class break renderer** which splits your data into specific number of groups and uses **color** to differentiate each group. You can choose the algorithm that performs the class splits or go with the defualt.\n", + "\n", + "Let us visualize the same major cities point dataset using its `POPULATION` column." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "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", + "
STNAMEPOPULATION
0AZSomerton14980
1CAAnderson10239
2CACamp Pendleton South11869
3CACitrus11195
4CACommerce13009
\n", + "
" + ], + "text/plain": [ + " ST NAME POPULATION\n", + "0 AZ Somerton 14980\n", + "1 CA Anderson 10239\n", + "2 CA Camp Pendleton South 11869\n", + "3 CA Citrus 11195\n", + "4 CA Commerce 13009" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[['ST', 'NAME', 'POPULATION']].head()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fc7bb250ccf5447f867844ce227ff6b3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "MapView(layout=Layout(height='400px', width='100%'), zoom=4.0)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "m4 = gis.map('USA', zoomlevel=4)\n", + "m4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![class color renderer](http://esri.github.io/arcgis-python-api/notebooks/nbimages/guide_sdf_class_breaks_color_1.png)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.spatial.plot(map_widget=m4,\n", + " renderer_type='c', # for class breaks renderer\n", + " method='esriClassifyNaturalBreaks', # classification algorithm\n", + " class_count=20, # choose the number of classes\n", + " col='POPULATION', # numeric column to classify\n", + " cmap='prism', # color map to pick colors from for each class\n", + " alpha=0.7 # specify opacity\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can take this further by plotting a histogram of the same `POPULATION` column and try to match the colors. To get the class breaks for the above map, you can inspect the layer definition from `MapView` object as shown below:" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "dict_keys(['type', 'visualVariables', 'rotationType', 'minValue', 'field', 'defaultSymbol', 'defaultLabel', 'classificationMethod', 'classBreakInfos'])" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dict(m4.layers[0].layer.layerDefinition.drawingInfo.renderer).keys()" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "20\n" + ] + } + ], + "source": [ + "class_breaks = m4.layers[0].layer.layerDefinition.drawingInfo.renderer.classBreakInfos\n", + "print(len(class_breaks))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can loop through each of the class breaks and obtain the min, max values and the colors for each class." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "7809.0 - 10844.421052631578\n", + "10844.421052631578 - 13879.842105263157\n", + "13879.842105263157 - 16915.263157894737\n", + "16915.263157894737 - 19950.684210526313\n", + "19950.684210526313 - 22986.105263157893\n", + "22986.105263157893 - 26021.526315789473\n", + "26021.526315789473 - 29056.94736842105\n", + "29056.94736842105 - 32092.36842105263\n", + "32092.36842105263 - 35127.78947368421\n", + "35127.78947368421 - 38163.21052631579\n", + "38163.21052631579 - 41198.63157894737\n", + "41198.63157894737 - 44234.05263157895\n", + "44234.05263157895 - 47269.47368421053\n", + "47269.47368421053 - 50304.8947368421\n", + "50304.8947368421 - 53340.31578947368\n", + "53340.31578947368 - 56375.73684210526\n", + "56375.73684210526 - 59411.15789473684\n", + "59411.15789473684 - 62446.57894736842\n", + "62446.57894736842 - 65482.0\n", + "65482.0 - 65482.0\n" + ] + } + ], + "source": [ + "cbs_list = []\n", + "cmap_list = []\n", + "for cb in class_breaks:\n", + " print(cb.description) # print the class break labels\n", + " cbs_list.append(cb.classMaxValue)\n", + " cmap_list.append([x/255.0 for x in cb.symbol.color])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have the individual class splits and the colors, we can plot a histogram using the same breaks and colors." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5,1,'Histogram of POPULATION column')" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAEICAYAAABRSj9aAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvIxREBQAAGBlJREFUeJzt3XmYXFWdxvHva5pFCJhAGgxJMAEjCjwqsYd1hmGIS0Ag6KCGQQkaJ6Ms48omOuKjziPKo4ALGtniiDExoiyPW4wyyAiBDmvClhhC0iSQRgirIoHf/HFP602leqtbnU4f38/z1FP3nnvuvedUV7916tyqbkUEZmaWr5cNdgPMzGxgOejNzDLnoDczy5yD3swscw56M7PMOejNzDLnoB9iJC2VdNhgt2MwSXqHpNWSnpG032C3x0DSeEkhqWWw22KbctBvQSStlPTmmrKTJN3YtR4R+0TE9b0cJ/dfuvOBUyNieETcXrsx9f3Z9ELwsKSvShpW2n6SpLslPSfpEUkXSxpR2n6upBfS/usl/V7SQaVt3+/mnK9Oy9dL+mB3jZe0fTr2z2rKnyndXpL0p9L6CbXnVuF0SctS3VWSviRpm1KdK1Lb9i+VvVqSv0Dzd8RBb/22BbyAvApY2kudN0TEcGAy8G/AvwNI+gRwHnA68ArgwHS8BZK2Lu0/N+3fCtwIXCVJTWr/ccDzwFslje4qTC9cw9N5VwFHl8qurHOci4CZwInADsARwOHAvJp6jwNfaFLbbQhy0A8x5VG/pP0ltUt6StKjkr6aqt2Q7ten0eBBkl4m6dOSHpK0TtL3JL2idNwT07Y/SvpMzXnOlTRf0vclPQWclM59UxrxrpX0jXJQplHkyWm0+bSkz0vaM+3zlKR5NcFa7mPdtkraRtIzwDDgTkl/6O3xioj7gN8B+0raEfgccFpE/CIiXoiIlcC7KcL+vXX2fwGYDbwS2Lm38/XRdODbwF3ACY0cQNJE4GTghIi4KSI2RMRS4F+BKZIOL1WfDbxe0j/38djjJF0lqTM9H76Rynt8DtUcY6N3p+V3I/rbO873q5iCe0LShyT9g6S70nPqG6V9T5J0o6TzU90HJR3R38fs75mDfmi7ELgwInYE9uRvI7lD0/2INBq8CTgp3f4F2AMYDnT9Au8NfIsidEZTjHTH1JxrKjAfGAFcCbwIfAwYBRxEMXI+uWafKcCbKEbNZwCz0jnGAfsCx3fTr7ptjYjn02gXihH7nt0/NIXUt38CbgcOBrYFrirXiYhngJ8Db6mz/zapLR0R8Vhv5+tDe3YHDqN4DK+kGI03YnJq0y3lwohYDdzMxn15Dvhv4It9aN8w4DrgIWA8xfPgh2nzSXTzHGrQAcBE4D3ABcA5wJuBfYB317wwHQDcT/F8+zJwaRPfYWXPQb/l+Wka0ayXtJ4igLvzAvBqSaMi4pmIuLmHuicAX42IFSnYzgampWmY44BrI+LGiPgL8F9A7RzuTRHx04h4KSL+FBGLI+LmNJJcCXwHqB0xnhcRT6WR5hLgV+n8T1IEa3cXUntqa1/dJukJ4FrgEuByipB4LCI21Km/Nm3v8u70+K+meLE6th/n7smJwF0RcQ8wB9hHjV1QHkXR5npq+wLFz2f3PoyE9wd2A06PiGcj4s8R0XWNqBk/l7LPp+P/CngWmBMR6yLiYYp3YeXH5aGI+G5EvEjxDmU0sGuD5/2746Df8hwbESO6bmw6Si6bAbwGuE/SrZKO6qHubhSjtC4PAS0Uvyy7UQQaABHxHPDHmv1Xl1ckvUbSdSouZj5FMWKsDZdHS8t/qrM+nPp6amtfTYqIkRGxZ0R8OiJeAh4DRnUTTKPT9i7z0s9gl4g4PCIWp/INwFblHSV1rb/Qh3adSDGSJyLWAP9LMZXTX4+lNtdT2xci4nng8+nW00h4HEWo1nsxbMbPpaw/z49HuhbS8xO6f/5YDQf9EBYRyyLieGAXiguM8yVtz6ajcYA1FPPQXXanCK1HKUaAY7s2SHo5m85H1x7zYuA+YGKaOvoUPQdIf/TU1ipuorgI+s5yYXrMjgAW9uEYqyimNMomUExlPdzTjpIOppiqODu9QD5CMSVxfAOj4t8A41T6NE06xziKqbJ6fbmcYlruHT0cdzXFyL9ee/rzc3kW2K60/soezmkDzEE/hEl6r6TWNFpdn4pfBDqBlyjmUbvMAT4maYKk4RQj8Llp5DYfOFrSwekC6efoPbR3AJ4CnpH0WuDDTetYz21tWJoy+hzwdUlTJG0laTzwI6AD+J8+HOYXwF6S3pf23ym1b35N+1okbVu6bUUxcl8A7A28Md32pQjEfl1cjIgHKC7oXinpQEnDJO0D/Bj4dUT8us4+G4BzgTN7OPQtFC/8X1LxMdBtJR2StvXn53IHxbTOVpLaKKYHbZA46Ie2KcDS9EmUC4Fpac7zOYoLb/+X5voPBC6jCLIbgAeBPwOnAaQ59NMoLrqtBZ4G1lGMfrvzSYqPLT4NfBeY28R+ddvWqiLiyxTvPs6neKFaRDGKnZymN3rbfx1wJPAfFI/REuBJNn2hu5hi+qHrNofi0z1fj4hHSrcHKfrayPTNqRTXH74PPEPxInQ9xSdvujOH7uf2SXPgRwOvpnj30kFxsRT693P5DMUHBJ6geHH9QR/6YwNE/scjViuN1tZTTMs8ONjtMbNqPKI3ACQdLWm7NF99PnA3sHJwW2VmzeCgty5TKS62raG4YDgt/HbPLAueujEzy5xH9GZmmRvsP04FwKhRo2L8+PGD3QwzsyFl8eLFj0VEa2/1toigHz9+PO3t7YPdDDOzIUXSQ73X8tSNmVn2HPRmZplz0JuZZc5Bb2aWOQe9mVnmHPRmZplz0JuZZc5Bb2aWOQe9mVnmtohvxlZy9NHVj3HttdWPYWa2hfKI3swscw56M7PMOejNzDLnoDczy5yD3swsc70GvaTLJK2TtKTOtk9KCkmj0rokXSRpuaS7JE0aiEabmVnf9WVEfwUwpbZQ0jjgLcCqUvERFP9YeiIwE7i4ehPNzKyKXoM+Im4AHq+z6WvAGUD5v4tPBb4XhZuBEZJGN6WlZmbWkIbm6CUdAzwcEXfWbBoDrC6td6QyMzMbJP3+Zqyk7YBzgLfW21ynLOqUIWkmxfQOu+++e3+bYWZmfdTIiH5PYAJwp6SVwFjgNkmvpBjBjyvVHQusqXeQiJgVEW0R0dba2us/MTczswb1O+gj4u6I2CUixkfEeIpwnxQRjwDXACemT98cCDwZEWub22QzM+uPvny8cg5wE7CXpA5JM3qo/jNgBbAc+C5wclNaaWZmDet1jj4iju9l+/jScgCnVG+WmZk1i78Za2aWOQe9mVnmHPRmZplz0JuZZc5Bb2aWOQe9mVnmHPRmZplz0JuZZc5Bb2aWOQe9mVnmHPRmZplz0JuZZc5Bb2aWOQe9mVnmHPRmZplz0JuZZc5Bb2aWOQe9mVnmHPRmZplz0JuZZa7XoJd0maR1kpaUyr4i6T5Jd0n6iaQRpW1nS1ou6X5JbxuohpuZWd/0ZUR/BTClpmwBsG9EvB54ADgbQNLewDRgn7TPtyQNa1przcys33oN+oi4AXi8puxXEbEhrd4MjE3LU4EfRsTzEfEgsBzYv4ntNTOzfmrGHP0HgJ+n5THA6tK2jlS2CUkzJbVLau/s7GxCM8zMrJ5KQS/pHGADcGVXUZ1qUW/fiJgVEW0R0dba2lqlGWZm1oOWRneUNB04CpgcEV1h3gGMK1UbC6xpvHlmZlZVQyN6SVOAM4FjIuK50qZrgGmStpE0AZgI3FK9mWZm1qheR/SS5gCHAaMkdQCfpfiUzTbAAkkAN0fEhyJiqaR5wD0UUzqnRMSLA9V4MzPrXa9BHxHH1ym+tIf6XwS+WKVRZmbWPP5mrJlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWWu16CXdJmkdZKWlMp2krRA0rJ0PzKVS9JFkpZLukvSpIFsvJmZ9a4vI/orgCk1ZWcBCyNiIrAwrQMcAUxMt5nAxc1pppmZNarXoI+IG4DHa4qnArPT8mzg2FL596JwMzBC0uhmNdbMzPqv0Tn6XSNiLUC63yWVjwFWl+p1pLJNSJopqV1Se2dnZ4PNMDOz3jT7YqzqlEW9ihExKyLaIqKttbW1yc0wM7MujQb9o11TMul+XSrvAMaV6o0F1jTePDMzq6rRoL8GmJ6WpwNXl8pPTJ++ORB4smuKx8zMBkdLbxUkzQEOA0ZJ6gA+C3wJmCdpBrAKeFeq/jPgSGA58Bzw/gFos5mZ9UOvQR8Rx3ezaXKdugGcUrVRZmbWPP5mrJlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWWuUtBL+pikpZKWSJojaVtJEyQtkrRM0lxJWzersWZm1n8NB72kMcB/Am0RsS8wDJgGnAd8LSImAk8AM5rRUDMza0zVqZsW4OWSWoDtgLXA4cD8tH02cGzFc5iZWQUNB31EPAycD6yiCPgngcXA+ojYkKp1AGPq7S9ppqR2Se2dnZ2NNsPMzHpRZepmJDAVmADsBmwPHFGnatTbPyJmRURbRLS1trY22gwzM+tFlambNwMPRkRnRLwAXAUcDIxIUzkAY4E1FdtoZmYVVAn6VcCBkraTJGAycA/wW+C4VGc6cHW1JpqZWRVV5ugXUVx0vQ24Ox1rFnAm8HFJy4GdgUub0E4zM2tQS+9VuhcRnwU+W1O8Ati/ynHNzKx5/M1YM7PMOejNzDLnoDczy5yD3swscw56M7PMOejNzDLnoDczy5yD3swscw56M7PMOejNzDLnoDczy5yD3swscw56M7PMOejNzDLnoDczy5yD3swscw56M7PMOejNzDLnoDczy1yloJc0QtJ8SfdJulfSQZJ2krRA0rJ0P7JZjTUzs/6rOqK/EPhFRLwWeANwL3AWsDAiJgIL07qZmQ2ShoNe0o7AocClABHxl4hYD0wFZqdqs4FjqzbSzMwaV2VEvwfQCVwu6XZJl0jaHtg1ItYCpPtd6u0saaakdkntnZ2dFZphZmY9qRL0LcAk4OKI2A94ln5M00TErIhoi4i21tbWCs0wM7OeVAn6DqAjIhal9fkUwf+opNEA6X5dtSaamVkVDQd9RDwCrJa0VyqaDNwDXANMT2XTgasrtdDMzCppqbj/acCVkrYGVgDvp3jxmCdpBrAKeFfFc5iZWQWVgj4i7gDa6myaXOW4ZmbWPP5mrJlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWXOQW9mljkHvZlZ5hz0ZmaZc9CbmWWuctBLGibpdknXpfUJkhZJWiZpbvrH4WZmNkiaMaL/CHBvaf084GsRMRF4ApjRhHOYmVmDKgW9pLHA24FL0rqAw4H5qcps4Ngq5zAzs2qqjugvAM4AXkrrOwPrI2JDWu8AxtTbUdJMSe2S2js7Oys2w8zMutNw0Es6ClgXEYvLxXWqRr39I2JWRLRFRFtra2ujzTAzs160VNj3EOAYSUcC2wI7UozwR0hqSaP6scCa6s00M7NGNTyij4izI2JsRIwHpgG/iYgTgN8Cx6Vq04GrK7fSzMwaNhCfoz8T+Lik5RRz9pcOwDnMzKyPqkzd/FVEXA9cn5ZXAPs347hmZladvxlrZpY5B72ZWeYc9GZmmWvKHP1Qd9ydp1c+xvw3fKUJLTEzaz6P6M3MMuegNzPLnIPezCxzDnozs8w56M3MMuegNzPLnIPezCxzDnozs8w56M3MMuegNzPLnIPezCxzDnozs8w56M3MMuegNzPLnIPezCxzDQe9pHGSfivpXklLJX0kle8kaYGkZel+ZPOaa2Zm/VVlRL8B+EREvA44EDhF0t7AWcDCiJgILEzrZmY2SBoO+ohYGxG3peWngXuBMcBUYHaqNhs4tmojzcyscU2Zo5c0HtgPWATsGhFroXgxAHZpxjnMzKwxlYNe0nDgx8BHI+Kpfuw3U1K7pPbOzs6qzTAzs25UCnpJW1GE/JURcVUqflTS6LR9NLCu3r4RMSsi2iKirbW1tUozzMysB1U+dSPgUuDeiPhqadM1wPS0PB24uvHmmZlZVS0V9j0EeB9wt6Q7UtmngC8B8yTNAFYB76rWRDMzq6LhoI+IGwF1s3lyo8c1M7Pm8jdjzcwy56A3M8ucg97MLHMOejOzzDnozcwy56A3M8ucg97MLHNVvjBlZe85uvox5l5b/RhmZjU8ojczy5yD3swscw56M7PMOejNzDLnoDczy5yD3swsc/545Rbk6E+vrnyMa78wrgktMbOceERvZpY5j+hzc1UTvrj1Tn9xyywnHtGbmWXOQW9mljkHvZlZ5gYs6CVNkXS/pOWSzhqo85iZWc8G5GKspGHAN4G3AB3ArZKuiYh7BuJ81lwzmnA999K5TTjIdtUvCv+a6u14M9XbcUpntXZ8s9UXyK1xAzWi3x9YHhErIuIvwA+BqQN0LjMz64EiovkHlY4DpkTEB9P6+4ADIuLUUp2ZwMy0uhdwfx8PPwp4rInN3ZLk3Ddw/4a6nPs3VPv2qoho7a3SQH2OXnXKNnpFiYhZwKx+H1hqj4i2Rhu2Jcu5b+D+DXU59y/nvsHATd10AOXv4o8F1gzQuczMrAcDFfS3AhMlTZC0NTANuGaAzmVmZj0YkKmbiNgg6VTgl8Aw4LKIWNqkw/d7umcIyblv4P4NdTn3L+e+DczFWDMz23L4m7FmZplz0JuZZW5Qgl7SZZLWSVpSKttJ0gJJy9L9yFQuSRelP6Vwl6RJpX2mp/rLJE0vlb9J0t1pn4sk1fu450D1bZyk30q6V9JSSR/JrH/bSrpF0p2pf59L5RMkLUptnZsuwiNpm7S+PG0fXzrW2an8fklvK5UP+p/PkDRM0u2Srkvr2fRP0sr0/LlDUnsqy+X5OULSfEn3pd/Bg3LpWyURsdlvwKHAJGBJqezLwFlp+SzgvLR8JPBzis/mHwgsSuU7ASvS/ci0PDJtuwU4KO3zc+CIzdi30cCktLwD8ACwd0b9EzA8LW8FLErtngdMS+XfBj6clk8Gvp2WpwFz0/LewJ3ANsAE4A8UF+6HpeU9gK1Tnb0H4Tn6ceAHwHVpPZv+ASuBUTVluTw/ZwMfTMtbAyNy6Vulx2XQTgzj2Tjo7wdGp+XRwP1p+TvA8bX1gOOB75TKv5PKRgP3lco3qjcI/bya4m/+ZNc/YDvgNuAAim8VtqTyg4BfpuVfAgel5ZZUT8DZwNmlY/0y7ffXfVP5RvU2U7/GAguBw4HrUntz6t9KNg36If/8BHYEHiR9yCSnvlW9bUlz9LtGxFqAdL9LKh8DlP+Zakcq66m8o075Zpfexu9HMerNpn9pWuMOYB2wgGKEuj4iNtRp01/7kbY/CexM//u9OV0AnAG8lNZ3Jq/+BfArSYtV/CkSyOP5uQfQCVyept0ukbQ9efStki0p6LvT3Z9T6G/5ZiVpOPBj4KMR8VRPVeuUbdH9i4gXI+KNFCPf/YHX9dCmIdU/SUcB6yJicbm4TtUh2b/kkIiYBBwBnCLp0B7qDqX+tVBMCV8cEfsBz1JM1XRnKPWtki0p6B+VNBog3a9L5d39OYWeysfWKd9sJG1FEfJXRsRVqTib/nWJiPXA9RTzmyMkdX0Br9ymv/YjbX8F8Dj97/fmcghwjKSVFH919XCKEX4u/SMi1qT7dcBPKF6sc3h+dgAdEbEorc+nCP4c+lbNYM0Zsekc/VfY+ILJl9Py29n4gsktqXwnivm4ken2ILBT2nZrqtt1weTIzdgvAd8DLqgpz6V/rcCItPxy4HfAUcCP2Phi5clp+RQ2vlg5Ly3vw8YXK1dQXKhsScsT+NvFyn0G6Tl6GH+7GJtF/4DtgR1Ky78HpmT0/PwdsFdaPjf1K4u+VXpcBuWkMAdYC7xA8So5g2JecyGwLN13PbCi+CcmfwDuBtpKx/kAsDzd3l8qbwOWpH2+Qc3FmQHu2z9SvJ27C7gj3Y7MqH+vB25P/VsC/Fcq34PiEwnLKUJxm1S+bVpfnrbvUTrWOakP91P69EJ6vB5I284ZtF+OjYM+i/6lftyZbku7zp/R8/ONQHt6fv6UIqiz6FuVm/8EgplZ5rakOXozMxsADnozs8w56M3MMuegNzPLnIPezCxzDnozs8w56M3MMvf/c8IxYD/Bh8cAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "# build a histogram for the same class breaks\n", + "n, bins, patches = plt.hist(df['POPULATION'], bins=cbs_list)\n", + "\n", + "# apply the same color for each class to match the map\n", + "idx = 0\n", + "for c, p in zip(bins, patches):\n", + " plt.setp(p, 'facecolor', cmap_list[idx])\n", + " idx+=1\n", + "\n", + "plt.title('Histogram of POPULATION column')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The shape and color of the bars in the histogram match with the number and color of major cities drawn on the map.\n", + "\n", + "Thus using the `Spatially Enabled DataFrame` we can easily visualize both the spatial and numeric distribution of data using the same symbology." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "heading_collapsed": true + }, + "source": [ + "## Colormaps and Colors\n", + "The examples above use the default colormap `jet`. However you can customize them by using the `colors` paramater. You can specify colors as:\n", + " * a string representing [named colors](https://matplotlib.org/examples/color/named_colors.html)\n", + " * an array of [RGB](http://www.tomjewett.com/colors/rgb.html) values\n", + " * a named [color ramp](https://matplotlib.org/examples/color/colormaps_reference.html). \n", + "\n", + "#### Color Array\n", + "\n", + "RGB + Alpha values can be used to create colors for symbols called in the `plot` method. RGB stands for red, green, and blue respectively. Each RGB value is a value between 0-255, and the alpha value is a number between 0-255.\n", + "\n", + "**Example to produce :**\n", + "\n", + " color = [255,0,100,1]\n", + "\n", + "The above example produces a purplish color. Many websites provide details about using colors. For example, see [here](https://www.rapidtables.com/web/color/RGB_Color.html) for a color codes chart.\n", + "\n", + "#### Color Maps\n", + "\n", + "A color map is a collection of string values that can be given to generate a series of related colors from a defined set.\n", + "\n", + "Color maps can be viewed here: https://matplotlib.org/examples/color/colormaps_reference.html\n", + "\n", + "#### Color Map Helpers\n", + "\n", + "To better understand the syntax for each input type, the ArcGIS API for Python provides some helper functions:" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "hidden": true + }, + "outputs": [], + "source": [ + "from arcgis.mapping import display_colormaps" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "The **display_colormaps** function provides a quick, easy way to visualize the pre-defined set of colormaps you can use. " + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "hidden": true, + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display_colormaps()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "You can retrieve a list of colormaps as well:" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accent Accent_r Blues Blues_r BrBG\n", + "BrBG_r BuGn BuGn_r BuPu BuPu_r\n", + "CMRmap CMRmap_r Dark2 Dark2_r GnBu\n", + "GnBu_r Greens Greens_r Greys Greys_r\n", + "OrRd OrRd_r Oranges Oranges_r PRGn\n", + "PRGn_r Paired Paired_r Pastel1 Pastel1_r\n", + "Pastel2 Pastel2_r PiYG PiYG_r PuBu\n", + "PuBuGn PuBuGn_r PuBu_r PuOr PuOr_r\n", + "PuRd PuRd_r Purples Purples_r RdBu\n", + "RdBu_r RdGy RdGy_r RdPu RdPu_r\n", + "RdYlBu RdYlBu_r RdYlGn RdYlGn_r Reds\n", + "Reds_r Set1 Set1_r Set2 Set2_r\n", + "Set3 Set3_r Spectral Spectral_r Wistia\n", + "Wistia_r YlGn YlGnBu YlGnBu_r YlGn_r\n", + "YlOrBr YlOrBr_r YlOrRd YlOrRd_r afmhot\n", + "afmhot_r autumn autumn_r binary binary_r\n", + "bone bone_r brg brg_r bwr\n", + "bwr_r cool cool_r coolwarm coolwarm_r\n", + "copper copper_r cubehelix cubehelix_r flag\n", + "flag_r gist_earth gist_earth_r gist_gray gist_gray_r\n", + "gist_heat gist_heat_r gist_ncar gist_ncar_r gist_rainbow\n", + "gist_rainbow_r gist_stern gist_stern_r gist_yarg gist_yarg_r\n", + "gnuplot gnuplot2 gnuplot2_r gnuplot_r gray\n", + "gray_r hot hot_r hsv hsv_r\n", + "inferno inferno_r jet jet_r magma\n", + "magma_r nipy_spectral nipy_spectral_r ocean ocean_r\n", + "pink pink_r plasma plasma_r prism\n", + "prism_r rainbow rainbow_r seismic seismic_r\n", + "spring spring_r summer summer_r terrain\n", + "terrain_r viridis viridis_r winter winter_r\n" + ] + } + ], + "source": [ + "from arcgis.mapping import symbol\n", + "\n", + "colormaps = symbol.ALLOWED_CMAPS\n", + "for a,b,c,d,e in zip(colormaps[::5], colormaps[1::5], colormaps[2::5], colormaps[3::5], colormaps[4::5]):\n", + " print(\"{:<20}{:<20}{:<20}{:<20}{:<}\".format(a,b,c,d,e))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "You can enter a list of color ramp names as input to the `display_colormaps` function to filter the output:" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "hidden": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display_colormaps(['Greens_r', 'PRGn', 'Dark2', 'Set1'])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "hidden": true + }, + "source": [ + "The examples above used `jet` which is the default and some used `prism` both of which can be seen in the list above. You can customize your charts by using a different colormap of your choice." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Symbology for Simple Renderers\n", + "\n", + "The ArcGIS API for Python provides you the ability to set symbol types so you control data appearance. The [`show_styles`]() function in the `arcgis.mapping` module assists you with the syntax to define symbols.\n", + "\n", + "#### Getting the different symbol styles" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "from arcgis.mapping import show_styles" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "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", + "
MARKERESRI_STYLE
0oCircle (default)
1+Cross
2dDiamond
3sSquare
4xX
\n", + "
" + ], + "text/plain": [ + " MARKER ESRI_STYLE\n", + "0 o Circle (default)\n", + "1 + Cross\n", + "2 d Diamond\n", + "3 s Square\n", + "4 x X" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# get the styles that are relevant to the current geometry type (points)\n", + "show_styles(df.spatial.geometry_type[0]) # the DataFrame in this example is of Point type" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "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", + "
MARKERESRI_STYLE
0\\Backward Diagonal
1/Forward Diagonal
2|Vertical Bar
3-Horizontal Bar
4xDiagonal Cross
5+Cross
6sSolid Fill (default)
\n", + "
" + ], + "text/plain": [ + " MARKER ESRI_STYLE\n", + "0 \\ Backward Diagonal\n", + "1 / Forward Diagonal\n", + "2 | Vertical Bar\n", + "3 - Horizontal Bar\n", + "4 x Diagonal Cross\n", + "5 + Cross\n", + "6 s Solid Fill (default)" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "show_styles('Polygon')" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "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", + "
MARKERESRI_STYLE
0sSolid (default)
1-Dash
2-.Dash Dot
3-..Dash Dot Dot
4.Dot
5--Long Dash
6--.Long Dash Dot
7nNull
8s-Short Dash
9s-.Short Dash Dot
10s-..Short Dash Dot Dot
11s.Short Dot
\n", + "
" + ], + "text/plain": [ + " MARKER ESRI_STYLE\n", + "0 s Solid (default)\n", + "1 - Dash\n", + "2 -. Dash Dot\n", + "3 -.. Dash Dot Dot\n", + "4 . Dot\n", + "5 -- Long Dash\n", + "6 --. Long Dash Dot\n", + "7 n Null\n", + "8 s- Short Dash\n", + "9 s-. Short Dash Dot\n", + "10 s-.. Short Dash Dot Dot\n", + "11 s. Short Dot" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "show_styles('Line')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For instance, you can represent the same set of points using square symbols instead of default circle using the snippet shown below:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m7 = GIS().map('United States', 4)\n", + "m7" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![map of US squares](http://esri.github.io/arcgis-python-api/notebooks/nbimages/13_4_map_dfplot2.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m7.center = [39, -98]\n", + "df.spatial.plot(map_widget=m7,\n", + " symbol_type='simple',\n", + " symbol_style='s', # for square\n", + " cmap='Greens_r', # color map is Greens_r for green reversed\n", + " cstep=35, # the individual color in the colormap\n", + " outline_color='binary',\n", + " marker_size=5,\n", + " line_width=.5,)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Visualizing line features using simple symbols\n", + "Let us search for USA freeway layer and visualize it by looping through the different line symbols" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "search_result = gis.content.search('title:USA freeway system AND owner:esri', \n", + " item_type = 'Feature Layer')\n", + "freeway_item = search_result[0]\n", + "freeway_item" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "freeway_sdf = freeway_item.layers[0].query().sdf\n", + "freeway_sdf.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m8 = gis.map('USA', 10)\n", + "m8" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](http://esri.github.io/arcgis-python-api/notebooks/nbimages/guide_sdf_lines_animated_1.gif)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m8.center=[34.05,-118.2]\n", + "m8.zoom=12\n", + "m8.basemap='dark-gray'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "for row, style in show_styles('Line').iterrows():\n", + " m8.remove_layers()\n", + " time.sleep(1) # sleep for 1 second so animation can finish\n", + " print(style['ESRI_STYLE'] + \" : \" + style['MARKER'])\n", + " freeway_sdf.spatial.plot(map_widget=m8,\n", + " cmap='Spectral', # user a different color map\n", + " symbol_type='simple',\n", + " symbol_style=style['MARKER']\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Visualizing area features using different symbols" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from arcgis.features import FeatureLayer\n", + "fl = FeatureLayer(\"https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/2\")\n", + "county_sdf = fl.query(\"STATE_NAME='Washington'\", out_sr=4326).sdf\n", + "county_sdf.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m9 = gis.map('Seattle, WA', zoomlevel=6)\n", + "m9.basemap='gray'\n", + "m9" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](http://esri.github.io/arcgis-python-api/notebooks/nbimages/guide_sdf_animate_polygons_1.gif)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for idx, style in show_styles('Polygon').iterrows():\n", + " m9.remove_layers()\n", + " time.sleep(0.5)\n", + " \n", + " print(style['ESRI_STYLE'] + \" : \" + style['MARKER'])\n", + " county_sdf.spatial.plot(map_widget=m9,\n", + " cmap = 'RdPu', # use a red to purple color map\n", + " symbol_type='simple',\n", + " symbol_style=style['MARKER'],\n", + " outline_style='s',\n", + " outline_color=[0,0,0,255],\n", + " line_width=1.0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Conclusion**\n", + "\n", + "\n", + "The `Spatially Enabled DataFrame` gives you powerful visualization capabilities that allows you to plot your data on the interactive map widget. You specify colors and symbols using the same syntax that you would specify for a normal Pandas or a matplotlib plot." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/labs/find_places.ipynb b/labs/find_places.ipynb new file mode 100644 index 0000000000..835d04c548 --- /dev/null +++ b/labs/find_places.ipynb @@ -0,0 +1,222 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Find Places ArcGIS DevLab\n", + "This is a completed solution for the [Find Places](https://developers.arcgis.com/labs/python/find-places/) ArcGIS DevLab. [ArcGIS DevLabs](https://developers.arcgis.com/labs/) are short, introductory tutorials to developing with the [ArcGIS platform](https://developers.arcgis.com/labs/what-is-arcgis/)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**1.** Model a GIS portal and import the geocode function from the ArcGIS API for Python" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from arcgis.gis import GIS\n", + "from arcgis.geocoding import geocode" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**2.** Create an anonymous connection to ArcGIS Online. Since the results are not stored, you do not need credentials to call the geocoding service" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "gis = GIS()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**3.** Pass the relevant parameters into the geocode function and get the results" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "geocode_fs = geocode(address=None,\n", + " location=[-118.71511, 34.09042],\n", + " category=\"Coffee shop\",\n", + " out_fields=\"Place_addr, PlaceName\",\n", + " max_locations=25,\n", + " as_featureset=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**4.** Convert the results to a dataframe and show the first two locations" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "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", + "
OBJECTIDPlaceNamePlace_addrSHAPE
01Starbucks26531 Agoura Rd, Calabasas, California, 91302{'x': -118.70030999999994, 'y': 34.14383000000...
12Starbucks26521 Agoura Rd, Calabasas, California, 91302{'x': -118.70023995051699, 'y': 34.14425002668...
\n", + "
" + ], + "text/plain": [ + " OBJECTID PlaceName Place_addr \\\n", + "0 1 Starbucks 26531 Agoura Rd, Calabasas, California, 91302 \n", + "1 2 Starbucks 26521 Agoura Rd, Calabasas, California, 91302 \n", + "\n", + " SHAPE \n", + "0 {'x': -118.70030999999994, 'y': 34.14383000000... \n", + "1 {'x': -118.70023995051699, 'y': 34.14425002668... " + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "g_df = geocode_fs.df\n", + "g_df.head(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**5.** Create a map to display the results" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "35aa51740ad646aca0cba4233d028205", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "MapView(basemaps=['dark-gray', 'dark-gray-vector', 'gray', 'gray-vector', 'hybrid', 'national-geographic', 'oc…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "g_map = gis.map([34.09042, -118.71511], zoomlevel=11)\n", + "g_map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**6.** Once the map has loaded, draw the results" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "g_map.draw(geocode_fs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}