{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Data Visualization\n", "\n", "As a data scientist, you likely perform data exploration on nearly every project. Exploratory data analysis can entail many things, from finding relevant data and cleaning it to running analysis and building models. The ability to visually analyze and interact with data is key during the exploratory process and the final presentation of insights.\n", "\n", "With that in mind, this guide introduces the basic building blocks for creating web-based, dynamic, and interactive map visualizations inside a Jupyter Notebook with CARTOframes. A Map can display one or several Layers. Each Layer can render local data or remote data from a CARTO account with a specific style and UI elements like legends, widgets or popups.\n", "\n", "In this guide you will be introduced to the Map and Layer classes. You will learn how to explore data with Widgets and Popups, how to use visualization styles to quickly symbolize thematic attributes and how to share your findings by publishing your visualizations. For further learning you can also check out the [Data Visualization examples](/developers/cartoframes/examples/#example-data-visualization)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Visualize data from a file\n", "\n", "CARTOframes allows creating maps directly with data from GeoJSON or CSV files (with geometric data)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from geopandas import read_file\n", "\n", "points_gdf = read_file('http://libs.cartocdn.com/cartoframes/samples/starbucks_brooklyn_geocoded.geojson')" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", " None\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", "\n", " Static map image\n", " \n", " \n", "
\n", "
\n", "
\n", " \n", " \n", "
\n", "
\n", "
\n", "\n", " \n", "\n", "
\n", "
\n", " :\n", "
\n", " \n", " \n", "
\n", "
\n", "\n", "
\n", " StackTrace\n", "
    \n", "
    \n", "
    \n", "\n", "\n", "\n", "\n", "\n", "\">\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cartoframes.viz import Layer\n", "\n", "Layer(points_gdf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the source, instead of a GeoJSON, is a CSV file with a column containing the geometry encoded in WKB/WKT, you can pass the name of the column as `geom_col` directly to the Layer and the geometry is automatically decoded." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from pandas import read_csv\n", "\n", "polygons_df = read_csv('http://libs.cartocdn.com/cartoframes/samples/starbucks_brooklyn_iso_enriched.csv')\n", "polygons_gdf = read_file('http://libs.cartocdn.com/cartoframes/samples/starbucks_brooklyn_iso_enriched.geojson')" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", " None\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", "\n", " Static map image\n", " \n", " \n", "
    \n", "
    \n", "
    \n", " \n", " \n", "
    \n", "
    \n", "
    \n", "\n", " \n", "\n", "
    \n", "
    \n", " :\n", "
    \n", " \n", " \n", "
    \n", "
    \n", "\n", "
    \n", " StackTrace\n", "
      \n", "
      \n", "
      \n", "\n", "\n", "\n", "\n", "\n", "\">\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cartoframes.viz import Map\n", "\n", "Map([\n", " Layer(polygons_df, geom_col='the_geom'),\n", " Layer(points_gdf)\n", "])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Visualize data from CARTO\n", "\n", "For big datasets visualization (>30MB), we recommend rendering layers directly from a CARTO account. This, in addition to improving the performance, allows you to apply SQL queries to the tables stored in CARTO.\n", "\n", "_Note: You'll need your [CARTO Account](https://carto.com/signup) credentials to perform this action._" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "from cartoframes.auth import set_default_credentials\n", "\n", "set_default_credentials('cartoframes')" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", " None\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", "\n", " Static map image\n", " \n", " \n", "
      \n", "
      \n", "
      \n", " \n", " \n", "
      \n", "
      \n", "
      \n", "\n", " \n", "\n", "
      \n", "
      \n", " :\n", "
      \n", " \n", " \n", "
      \n", "
      \n", "\n", "
      \n", " StackTrace\n", "
        \n", "
        \n", "
        \n", "\n", "\n", "\n", "\n", "\n", "\">\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Map([\n", " Layer('countries'),\n", " Layer('SELECT * FROM global_power_plants WHERE capacity_mw > 1000'),\n", " Layer('world_rivers')\n", "])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Map configuration\n", "\n", "The map basemap and initial viewport can be customized. CARTO provides out-of-the-box basemaps: `positron`, `voyager` and `darkmatter`, but it also supports any URL to load external basemaps." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", " None\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", "\n", " Static map image\n", " \n", " \n", "
        \n", "
        \n", "
        \n", " \n", " \n", "
        \n", "
        \n", "
        \n", "\n", " \n", "\n", "
        \n", "
        \n", " :\n", "
        \n", " \n", " \n", "
        \n", "
        \n", "\n", "
        \n", " StackTrace\n", "
          \n", "
          \n", "
          \n", "\n", "\n", "\n", "\n", "\n", "\">\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cartoframes.viz import basemaps\n", "\n", "Map(\n", " basemap=basemaps.voyager,\n", " viewport={'zoom': 13.5, 'lat': 40.4353, 'lng': -79.9916}\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Data-driven styling\n", "\n", "CARTOframes provides out of the box style helpers for different kinds of data-driven visualizations:\n", "- Basic\n", "- Color: bins, category, continuous\n", "- Size: bins, category, continuous\n", "- Animation\n", "\n", "Style helpers contain built-in cartography styling. However, each method provides lots of parameters to adjust your visualization to your needs (color, size, stroke, color palette, classification methods, etc.). There are also legends, popups, and widgets. By default, only the legend and popup hover are enabled." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", " None\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", "\n", " Static map image\n", " \n", " \n", "
          \n", "
          \n", "
          \n", " \n", " \n", "
          \n", "
          \n", " \n", "\n", "
          \n", " \n", " \n", " \n", " \n", " \n", "
          \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
          \n", " \n", " \n", "
          \n", "
          \n", "
          \n", "
          \n", " \n", "
          \n", "
          \n", "
          \n", "\n", " \n", "\n", "
          \n", "
          \n", " :\n", "
          \n", " \n", " \n", "
          \n", "
          \n", "\n", "
          \n", " StackTrace\n", "
            \n", "
            \n", "
            \n", "\n", "\n", "\n", "\n", "\n", "\">\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cartoframes.viz import size_continuous_style\n", "\n", "Layer(\n", " points_gdf,\n", " size_continuous_style('revenue')\n", ")" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", " None\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", "\n", " Static map image\n", " \n", " \n", " \n", "\n", "\n", " \n", "
            \n", "
            \n", "
            \n", " \n", " \n", "
            \n", "
            \n", " \n", "\n", "
            \n", " \n", " \n", " \n", " \n", " \n", "
            \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
            \n", " \n", " \n", "
            \n", "
            \n", "
            \n", "
            \n", " \n", "
            \n", "
            \n", "
            \n", "\n", " \n", "\n", "
            \n", "
            \n", " :\n", "
            \n", " \n", " \n", "
            \n", "
            \n", "\n", "
            \n", " StackTrace\n", "
              \n", "
              \n", "
              \n", "\n", "\n", "\n", "\n", "\n", "\">\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cartoframes.viz import Layer, color_bins_style\n", "\n", "Layer(\n", " 'eng_wales_pop',\n", " color_bins_style('pop_sq_km', palette='mint', bins=5, opacity=0.8),\n", " default_widget=True,\n", " default_popup_hover=False\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Legends\n", "\n", "Legends are aligned with style helpers. Each style helper contains what we call the \"default legend\" based on the style:\n", "- Basic\n", "- Color: bins, category, continuous\n", "- Size: bins, category, continuous\n", "\n", "Depending on the geometry of the visualization (points, lines, polygons), the legend will render the corresponding symbology. Legends are also customizable, you can edit the title or add a description or a footer.\n", "\n", "When having multiple layers in a map, legends will stack according to the order of the layers." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", " None\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", "\n", " Static map image\n", " \n", " \n", "
              \n", "
              \n", "
              \n", " \n", " \n", "
              \n", "
              \n", " \n", "\n", "
              \n", " \n", " \n", " \n", " \n", " \n", "
              \n", " \n", " \n", " \n", " \n", " \n", " Source: Starbucks\n", " \n", " \n", " \n", " \n", "
              \n", " \n", " \n", "
              \n", "
              \n", "
              \n", "
              \n", " \n", "
              \n", "
              \n", "
              \n", "\n", " \n", "\n", "
              \n", "
              \n", " :\n", "
              \n", " \n", " \n", "
              \n", "
              \n", "\n", "
              \n", " StackTrace\n", "
                \n", "
                \n", "
                \n", "\n", "\n", "\n", "\n", "\n", "\">\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cartoframes.viz import size_continuous_style, size_continuous_legend # or just default_legend\n", "\n", "Layer(\n", " points_gdf,\n", " size_continuous_style('revenue', size_range=[10,50], stroke_color='turquoise', stroke_width=2, opacity=0),\n", " legends=size_continuous_legend(\n", " title='Annual Revenue',\n", " description='Revenue in dollars ($)',\n", " footer='Source: Starbucks'\n", " )\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Interactive widgets\n", "\n", "There are several widgets:\n", "- Formula\n", "- Histogram\n", "- Category\n", "- Time-series\n", "- Animation\n", "\n", "Widgets interactivity is bidirectional: filtering the widgets affects the visualization and the other widgets, and when the viewport of the visualization changes, the widgets show the information filtered by viewport (unless the flag is_global is set)." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", " None\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", "\n", " Static map image\n", " \n", " \n", " \n", "\n", "\n", " \n", "
                \n", "
                \n", "
                \n", " \n", " \n", "
                \n", "
                \n", "
                \n", "\n", " \n", "\n", "
                \n", "
                \n", " :\n", "
                \n", " \n", " \n", "
                \n", "
                \n", "\n", "
                \n", " StackTrace\n", "
                  \n", "
                  \n", "
                  \n", "\n", "\n", "\n", "\n", "\n", "\">\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cartoframes.viz import formula_widget, category_widget, histogram_widget\n", "\n", "Layer(\n", " polygons_gdf,\n", " widgets=[\n", " formula_widget('popcy', 'sum', 'Population'),\n", " formula_widget('inccymedhh', 'sum', 'Median Income Average', is_global=True),\n", " histogram_widget('educybach', 'Education'),\n", " category_widget('id_store', 'Store ID')\n", " ]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Click and hover popups\n", "Popups are a nice tool to explore your data in a map. CARTOframes provides full customization to both click and hover popups. Using the helper `popup_element` you can display any property from your data.\n", "\n", "When there are multiple layers in a map, popups will stack according to the order of the layers." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", " None\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", "\n", " Static map image\n", " \n", " \n", "
                  \n", "
                  \n", "
                  \n", " \n", " \n", "
                  \n", "
                  \n", "
                  \n", "\n", " \n", "\n", "
                  \n", "
                  \n", " :\n", "
                  \n", " \n", " \n", "
                  \n", "
                  \n", "\n", "
                  \n", " StackTrace\n", "
                    \n", "
                    \n", "
                    \n", "\n", "\n", "\n", "\n", "\n", "\">\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cartoframes.viz import popup_element\n", "\n", "Layer(\n", " polygons_gdf,\n", " popup_hover=[\n", " popup_element('popcy', 'Population')\n", " ],\n", " popup_click=[\n", " popup_element('popcy', 'Population'),\n", " popup_element('id_store', 'Store ID'),\n", " popup_element('inccymedhh', 'Median Income'),\n", " popup_element('lbfcyempl', 'Employed Population'),\n", " ]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Grid layout\n", "\n", "Using the Layout class we can show different maps side-to-side, for example, to compare variables for the same visualization. These grid maps can also be rendered as static by setting the `is_static` parameter." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", " CARTOframes\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", "\n", "
                    \n", " \n", "
                    \n", " \n", " \n", " \n", " \n", " \n", " \n", "
                    \n", " \n", "\n", "
                    \n", " "Static\n", " \n", "
                    \n", "
                    \n", " \n", "
                    \n", " \n", "\n", "
                    \n", "
                    \n", "
                    \n", " \n", " \n", " \n", " \n", " \n", " \n", "
                    \n", " \n", "\n", "
                    \n", " "Static\n", " \n", "
                    \n", "
                    \n", " \n", "
                    \n", " \n", "\n", "
                    \n", "
                    \n", "
                    \n", " \n", "
                    \n", " \n", "
                    \n", "\n", " \n", "\n", "
                    \n", "
                    \n", " :\n", "
                    \n", " \n", " \n", "
                    \n", "
                    \n", "\n", "
                    \n", " StackTrace\n", "
                      \n", "
                      \n", "
                      \n", "\n", "\n", "\n", "\n", "\">\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cartoframes.viz import Layout\n", "\n", "Layout([\n", " Map(Layer(polygons_gdf, style=color_bins_style('inccymedhh', bins=7, palette='mint', stroke_width=0))),\n", " Map(Layer(polygons_gdf, style=color_bins_style('popcy', palette='pinkyl', stroke_width=0)))\n", "], 2, 1, map_height=400, is_static=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Publish and share\n", "\n", "CARTOframes allows to publish visualizations rendering local data (GeoDataFrame) and also public and private tables from CARTO accounts. The `Map` class provides a method to publish a map in a static URL to share it with others. Maps can be published also in \"protected\" mode using a password in case you don't want to make it public.\n", "\n", "_Note: You'll need your [CARTO Account](https://carto.com/signup) credentials to perform this action._" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "from cartoframes.auth import set_default_credentials\n", "\n", "set_default_credentials('creds.json')" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "map_viz = Map(Layer('countries'))" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'id': 'dcb4ebde-998c-4f98-b44d-ae790c59845e',\n", " 'url': 'https://cartoframes-org.carto.com/u/cartoframes/kuviz/dcb4ebde-998c-4f98-b44d-ae790c59845e',\n", " 'name': 'countries',\n", " 'privacy': 'password'}" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "map_viz.publish(\n", " name='countries',\n", " password='1234',\n", " if_exists='replace')" ] } ], "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.8.5" } }, "nbformat": 4, "nbformat_minor": 2 }