{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Geographic Plots\n", "\n", "Altair 2.0 added the ability to plot geographic data.\n", "\n", "This funcitonality is still a bit incomplete (for example, not all interactions or selections work properly on projected data), but is relatively straightforward to use.\n", "\n", "We'll show a few examples here." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import altair as alt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Scatter-Plots in Geographic Coordinates\n", "\n", "First, we'll show an example of plotting Latitude/Longitude data using a map projection.\n", "We'll load the dataset consisting of the latitude/longitude of every US airport:" ] }, { "cell_type": "code", "execution_count": 2, "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", "
iatanamecitystatecountrylatitudelongitude
000MThigpenBay SpringsMSUSA31.953765-89.234505
100RLivingston MunicipalLivingstonTXUSA30.685861-95.017928
200VMeadow LakeColorado SpringsCOUSA38.945749-104.569893
301GPerry-WarsawPerryNYUSA42.741347-78.052081
401JHilliard AirparkHilliardFLUSA30.688012-81.905944
\n", "
" ], "text/plain": [ " iata name city state country latitude \\\n", "0 00M Thigpen Bay Springs MS USA 31.953765 \n", "1 00R Livingston Municipal Livingston TX USA 30.685861 \n", "2 00V Meadow Lake Colorado Springs CO USA 38.945749 \n", "3 01G Perry-Warsaw Perry NY USA 42.741347 \n", "4 01J Hilliard Airpark Hilliard FL USA 30.688012 \n", "\n", " longitude \n", "0 -89.234505 \n", "1 -95.017928 \n", "2 -104.569893 \n", "3 -78.052081 \n", "4 -81.905944 " ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from vega_datasets import data\n", "airports = data.airports()\n", "airports.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The plot is quite similar to a standard scatter plot, with a couple differences:\n", "\n", "- we specify the \"latitude\" and \"longitude\" encodings in place of \"x\" and \"y\"\n", "- we specify a projection to use for the data\n", "\n", "For data covering only the United States, the ``\"albersUsa\"`` projection is useful:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "" ], "text/plain": [ "alt.Chart(...)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "alt.Chart(airports).mark_circle().encode(\n", " longitude='longitude:Q',\n", " latitude='latitude:Q',\n", " size=alt.value(10),\n", " tooltip='name'\n", ").project(\n", " \"albersUsa\"\n", ").properties(\n", " width=500,\n", " height=400\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The available projections are listed in the [vega documentation](https://vega.github.io/vega/docs/projections/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Choropleth Maps\n", "\n", "If you would like to plot geographic boundaries, such as states and countries, you must load the geographic shape data to show in Altair.\n", "This takes a bit of boilerplate (we're thinking about how to streamline this kind of common construct in future releases) and uses the ``geoshape`` marker.\n", "\n", "For example, here are the state boundaries:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "" ], "text/plain": [ "alt.Chart(...)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "states = alt.topo_feature(data.us_10m.url, feature='states')\n", "\n", "alt.Chart(states).mark_geoshape(\n", " fill='lightgray',\n", " stroke='white'\n", ").project('albersUsa').properties(\n", " width=500,\n", " height=300\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And here are the world country boundaries:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "" ], "text/plain": [ "alt.Chart(...)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import altair as alt\n", "from vega_datasets import data\n", "\n", "countries = alt.topo_feature(data.world_110m.url, 'countries')\n", "\n", "alt.Chart(countries).mark_geoshape(\n", " fill='lightgray',\n", " stroke='white'\n", ").project(\n", " \"equirectangular\"\n", ").properties(\n", " width=500,\n", " height=300\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can see what happens if you try other projection types; for example, you might try \"mercator\", \"orthographic\", \"albers\", or \"gnomonic\"." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Points on Background\n", "\n", "If you'd like to plot data points on a map background, the easiest way to do so is to use the layering operators we saw in [04-Compound-charts](04-Compound-charts.ipynb).\n", "For example:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "" ], "text/plain": [ "alt.LayerChart(...)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "states = alt.topo_feature(data.us_10m.url, feature='states')\n", "airports = data.airports()\n", "\n", "background = alt.Chart(states).mark_geoshape(\n", " fill='lightgray',\n", " stroke='white'\n", ").project('albersUsa').properties(\n", " width=500,\n", " height=300\n", ")\n", "\n", "points = alt.Chart(airports).mark_circle().encode(\n", " longitude='longitude:Q',\n", " latitude='latitude:Q',\n", " size=alt.value(10),\n", " tooltip='name'\n", ")\n", "\n", "background + points" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that we need only specify the projection and the chart size once" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Colored Choropleths\n", "\n", "The most complicated type of chart to make is one where the map regions are colored to reflect underlying data; the reason this is complicated is because it often involves joining two different datasets using a *lookup transform*.\n", "\n", "Again, this is a piece of the API that we're hoping to improve in the future.\n", "\n", "As an example, here is a chart representing the total population of each state:" ] }, { "cell_type": "code", "execution_count": 7, "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", "
stateidpopulationengineershurricanes
0Alabama148633000.00342222
1Alaska27418940.0015910
2Arizona469310710.0047740
3Arkansas529882480.0024400
4California6392500170.0071260
\n", "
" ], "text/plain": [ " state id population engineers hurricanes\n", "0 Alabama 1 4863300 0.003422 22\n", "1 Alaska 2 741894 0.001591 0\n", "2 Arizona 4 6931071 0.004774 0\n", "3 Arkansas 5 2988248 0.002440 0\n", "4 California 6 39250017 0.007126 0" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pop = data.population_engineers_hurricanes()\n", "pop.head()" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "" ], "text/plain": [ "alt.Chart(...)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import altair as alt\n", "from vega_datasets import data\n", "\n", "states = alt.topo_feature(data.us_10m.url, 'states')\n", "\n", "variable_list = ['population', 'engineers', 'hurricanes']\n", "\n", "alt.Chart(states).mark_geoshape().encode(\n", " color='population:Q'\n", ").transform_lookup(\n", " lookup='id',\n", " from_=alt.LookupData(pop, 'id', list(pop.columns))\n", ").properties(\n", " width=500,\n", " height=300\n", ").project(\n", " type='albersUsa'\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice the key here: the choropleth data has an \"id\" column that corresponds to the id column in the population data; we use this as a lookup key to join the two datasets together and plot them appropriately.\n", "\n", "For more examples of geographic visualizations, see the [altair gallery](https://altair-viz.github.io/gallery/index.html#maps), and keep in mind that this is an area of Altair and Vega-Lite that is steadily improving!" ] } ], "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.7.6" } }, "nbformat": 4, "nbformat_minor": 4 }