diff --git a/Manifest.toml b/Manifest.toml index f4bb2dd..38445cf 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -129,7 +129,31 @@ uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" version = "0.12.8" [[Compat]] -deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] +deps = [ + "Base64", + "Dates", + "DelimitedFiles", + "Distributed", + "InteractiveUtils", + "LibGit2", + "Libdl", + "LinearAlgebra", + "Markdown", + "Mmap", + "Pkg", + "Printf", + "REPL", + "Random", + "SHA", + "Serialization", + "SharedArrays", + "Sockets", + "SparseArrays", + "Statistics", + "Test", + "UUIDs", + "Unicode", +] git-tree-sha1 = "727e463cfebd0c7b999bbf3e9e7e16f254b94193" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" version = "3.34.0" @@ -139,7 +163,21 @@ deps = ["Artifacts", "Libdl"] uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" [[Compose]] -deps = ["Base64", "Colors", "DataStructures", "Dates", "IterTools", "JSON", "LinearAlgebra", "Measures", "Printf", "Random", "Requires", "Statistics", "UUIDs"] +deps = [ + "Base64", + "Colors", + "DataStructures", + "Dates", + "IterTools", + "JSON", + "LinearAlgebra", + "Measures", + "Printf", + "Random", + "Requires", + "Statistics", + "UUIDs", +] git-tree-sha1 = "c6461fc7c35a4bb8d00905df7adafcff1fe3a6bc" uuid = "a81c6b42-2e10-5240-aca2-a61377ecd94b" version = "0.9.2" @@ -166,7 +204,22 @@ uuid = "dc8bdbbb-1ca9-579f-8c36-e416f6a65cce" version = "1.0.2" [[Dash]] -deps = ["CodecZlib", "DashBase", "DashCoreComponents", "DashHtmlComponents", "DashTable", "DataStructures", "HTTP", "JSON", "JSON2", "MD5", "PlotlyBase", "Sockets", "Test", "UUIDs"] +deps = [ + "CodecZlib", + "DashBase", + "DashCoreComponents", + "DashHtmlComponents", + "DashTable", + "DataStructures", + "HTTP", + "JSON", + "JSON2", + "MD5", + "PlotlyBase", + "Sockets", + "Test", + "UUIDs", +] git-tree-sha1 = "d5afc7e1816c535b9023d3ae0154c6af3def6d7b" uuid = "1b08a953-4be3-4667-9a23-3db579824955" version = "0.1.6" @@ -207,7 +260,26 @@ uuid = "124859b0-ceae-595e-8997-d05f6a7a8dfe" version = "0.7.7" [[DataFrames]] -deps = ["Compat", "DataAPI", "Future", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrettyTables", "Printf", "REPL", "Reexport", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] +deps = [ + "Compat", + "DataAPI", + "Future", + "InvertedIndices", + "IteratorInterfaceExtensions", + "LinearAlgebra", + "Markdown", + "Missings", + "PooledArrays", + "PrettyTables", + "Printf", + "REPL", + "Reexport", + "SortingAlgorithms", + "Statistics", + "TableTraits", + "Tables", + "Unicode", +] git-tree-sha1 = "d785f42445b63fc86caa08bb9a9351008be9b765" uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" version = "1.2.2" @@ -248,7 +320,20 @@ deps = ["Random", "Serialization", "Sockets"] uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" [[Distributions]] -deps = ["ChainRulesCore", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns"] +deps = [ + "ChainRulesCore", + "FillArrays", + "LinearAlgebra", + "PDMats", + "Printf", + "QuadGK", + "Random", + "SparseArrays", + "SpecialFunctions", + "Statistics", + "StatsBase", + "StatsFuns", +] git-tree-sha1 = "f4efaa4b5157e0cdb8283ae0b5428bc9208436ed" uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" version = "0.25.16" @@ -383,13 +468,38 @@ uuid = "9fb69e20-1954-56bb-a84f-559cc56a8ff7" version = "0.2.2" [[ImageCore]] -deps = ["AbstractFFTs", "ColorVectorSpace", "Colors", "FixedPointNumbers", "Graphics", "MappedArrays", "MosaicViews", "OffsetArrays", "PaddedViews", "Reexport"] +deps = [ + "AbstractFFTs", + "ColorVectorSpace", + "Colors", + "FixedPointNumbers", + "Graphics", + "MappedArrays", + "MosaicViews", + "OffsetArrays", + "PaddedViews", + "Reexport", +] git-tree-sha1 = "595155739d361589b3d074386f77c107a8ada6f7" uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534" version = "0.9.2" [[ImageFiltering]] -deps = ["CatIndices", "ComputationalResources", "DataStructures", "FFTViews", "FFTW", "ImageCore", "LinearAlgebra", "OffsetArrays", "Requires", "SparseArrays", "StaticArrays", "Statistics", "TiledIteration"] +deps = [ + "CatIndices", + "ComputationalResources", + "DataStructures", + "FFTViews", + "FFTW", + "ImageCore", + "LinearAlgebra", + "OffsetArrays", + "Requires", + "SparseArrays", + "StaticArrays", + "Statistics", + "TiledIteration", +] git-tree-sha1 = "79dac52336910325a5675813053b1eee3eb5dcc6" uuid = "6a3955dd-da59-5b1f-98d4-e7296123deb5" version = "0.6.22" @@ -548,7 +658,18 @@ uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" version = "1.16.1+1" [[LightGraphs]] -deps = ["ArnoldiMethod", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] +deps = [ + "ArnoldiMethod", + "DataStructures", + "Distributed", + "Inflate", + "LinearAlgebra", + "Random", + "SharedArrays", + "SimpleTraits", + "SparseArrays", + "Statistics", +] git-tree-sha1 = "432428df5f360964040ed60418dd5601ecd240b6" uuid = "093fc24a-ae57-5d10-9952-331d41423f4d" version = "1.3.5" @@ -591,19 +712,73 @@ uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7" version = "2021.1.1+1" [[MLJ]] -deps = ["CategoricalArrays", "ComputationalResources", "Distributed", "Distributions", "LinearAlgebra", "MLJBase", "MLJEnsembles", "MLJIteration", "MLJModels", "MLJOpenML", "MLJSerialization", "MLJTuning", "Pkg", "ProgressMeter", "Random", "ScientificTypes", "Statistics", "StatsBase", "Tables"] +deps = [ + "CategoricalArrays", + "ComputationalResources", + "Distributed", + "Distributions", + "LinearAlgebra", + "MLJBase", + "MLJEnsembles", + "MLJIteration", + "MLJModels", + "MLJOpenML", + "MLJSerialization", + "MLJTuning", + "Pkg", + "ProgressMeter", + "Random", + "ScientificTypes", + "Statistics", + "StatsBase", + "Tables", +] git-tree-sha1 = "7cbd651e39fd3f3aa37e8a4d8beaccfa8d13b1cd" uuid = "add582a8-e3ab-11e8-2d5e-e98b27df1bc7" version = "0.16.7" [[MLJBase]] -deps = ["CategoricalArrays", "ComputationalResources", "Dates", "DelimitedFiles", "Distributed", "Distributions", "InteractiveUtils", "InvertedIndices", "LinearAlgebra", "LossFunctions", "MLJModelInterface", "Missings", "OrderedCollections", "Parameters", "PrettyTables", "ProgressMeter", "Random", "ScientificTypes", "StatisticalTraits", "Statistics", "StatsBase", "Tables"] +deps = [ + "CategoricalArrays", + "ComputationalResources", + "Dates", + "DelimitedFiles", + "Distributed", + "Distributions", + "InteractiveUtils", + "InvertedIndices", + "LinearAlgebra", + "LossFunctions", + "MLJModelInterface", + "Missings", + "OrderedCollections", + "Parameters", + "PrettyTables", + "ProgressMeter", + "Random", + "ScientificTypes", + "StatisticalTraits", + "Statistics", + "StatsBase", + "Tables", +] git-tree-sha1 = "c0e721c7ab80d37e9eb87ef69361e212a12e3f37" uuid = "a7f614a8-145f-11e9-1d2a-a57a1082229d" version = "0.18.19" [[MLJEnsembles]] -deps = ["CategoricalArrays", "ComputationalResources", "Distributed", "Distributions", "MLJBase", "MLJModelInterface", "ProgressMeter", "Random", "ScientificTypes", "StatsBase"] +deps = [ + "CategoricalArrays", + "ComputationalResources", + "Distributed", + "Distributions", + "MLJBase", + "MLJModelInterface", + "ProgressMeter", + "Random", + "ScientificTypes", + "StatsBase", +] git-tree-sha1 = "f8ca949d52432b81f621d9da641cf59829ad2c8c" uuid = "50ed68f4-41fd-4504-931a-ed422449fee0" version = "0.1.2" @@ -621,7 +796,26 @@ uuid = "e80e1ace-859a-464e-9ed9-23947d8ae3ea" version = "1.2.0" [[MLJModels]] -deps = ["CategoricalArrays", "Dates", "Distances", "Distributions", "InteractiveUtils", "LinearAlgebra", "MLJBase", "MLJModelInterface", "OrderedCollections", "Parameters", "Pkg", "REPL", "Random", "Requires", "ScientificTypes", "Statistics", "StatsBase", "Tables"] +deps = [ + "CategoricalArrays", + "Dates", + "Distances", + "Distributions", + "InteractiveUtils", + "LinearAlgebra", + "MLJBase", + "MLJModelInterface", + "OrderedCollections", + "Parameters", + "Pkg", + "REPL", + "Random", + "Requires", + "ScientificTypes", + "Statistics", + "StatsBase", + "Tables", +] git-tree-sha1 = "ced5223e0b8cecfab2cd0e688deec16984bd879c" uuid = "d491faf4-2d78-11e9-2867-c94bc002c0b7" version = "0.14.10" @@ -828,11 +1022,42 @@ uuid = "fa939f87-e72e-5be4-a000-7fc836dbe307" version = "1.2.0" [[Pkg]] -deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +deps = [ + "Artifacts", + "Dates", + "Downloads", + "LibGit2", + "Libdl", + "Logging", + "Markdown", + "Printf", + "REPL", + "Random", + "SHA", + "Serialization", + "TOML", + "Tar", + "UUIDs", + "p7zip_jll", +] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" [[PlotlyBase]] -deps = ["ColorSchemes", "Dates", "DelimitedFiles", "DocStringExtensions", "JSON", "LaTeXStrings", "Logging", "Parameters", "Pkg", "REPL", "Requires", "Statistics", "UUIDs"] +deps = [ + "ColorSchemes", + "Dates", + "DelimitedFiles", + "DocStringExtensions", + "JSON", + "LaTeXStrings", + "Logging", + "Parameters", + "Pkg", + "REPL", + "Requires", + "Statistics", + "UUIDs", +] path = "/home/tlyon3/.julia/dev/PlotlyBase" uuid = "a03496cd-edff-5a9b-9e67-9cda94a718b5" version = "0.8.15" @@ -914,7 +1139,20 @@ uuid = "ae029012-a4dd-5104-9daa-d747884805df" version = "1.1.3" [[Revise]] -deps = ["CodeTracking", "Distributed", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "Pkg", "REPL", "Requires", "UUIDs", "Unicode"] +deps = [ + "CodeTracking", + "Distributed", + "FileWatching", + "JuliaInterpreter", + "LibGit2", + "LoweredCodeUtils", + "OrderedCollections", + "Pkg", + "REPL", + "Requires", + "UUIDs", + "Unicode", +] git-tree-sha1 = "1947d2d75463bd86d87eaba7265b0721598dd803" uuid = "295af30f-e4ad-537b-8983-00126c2a3abe" version = "3.1.19" @@ -935,7 +1173,19 @@ version = "0.3.0+0" uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" [[ScientificTypes]] -deps = ["CategoricalArrays", "ColorTypes", "CorpusLoaders", "Dates", "Distributions", "PersistenceDiagramsBase", "PrettyTables", "Reexport", "ScientificTypesBase", "StatisticalTraits", "Tables"] +deps = [ + "CategoricalArrays", + "ColorTypes", + "CorpusLoaders", + "Dates", + "Distributions", + "PersistenceDiagramsBase", + "PrettyTables", + "Reexport", + "ScientificTypesBase", + "StatisticalTraits", + "Tables", +] git-tree-sha1 = "5af0e5c6c79d498ae40a9ae803875b845e2bad2f" uuid = "321657f4-b219-11e9-178b-2701a2544e81" version = "2.2.0" @@ -1140,7 +1390,18 @@ version = "1.0.2" uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" [[VegaDatasets]] -deps = ["DataStructures", "DataValues", "FilePaths", "IterableTables", "IteratorInterfaceExtensions", "JSON", "TableShowUtils", "TableTraits", "TableTraitsUtils", "TextParse"] +deps = [ + "DataStructures", + "DataValues", + "FilePaths", + "IterableTables", + "IteratorInterfaceExtensions", + "JSON", + "TableShowUtils", + "TableTraits", + "TableTraitsUtils", + "TextParse", +] git-tree-sha1 = "c997c7217f37205c5795de8c797f8f8531890f1d" uuid = "0ae4a718-28b7-58ec-9efb-cded64d6d5b4" version = "2.1.1" @@ -1152,7 +1413,22 @@ uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5" version = "1.1.0" [[WebIO]] -deps = ["AssetRegistry", "Base64", "Distributed", "FunctionalCollections", "JSON", "Logging", "Observables", "Pkg", "Random", "Requires", "Sockets", "UUIDs", "WebSockets", "Widgets"] +deps = [ + "AssetRegistry", + "Base64", + "Distributed", + "FunctionalCollections", + "JSON", + "Logging", + "Observables", + "Pkg", + "Random", + "Requires", + "Sockets", + "UUIDs", + "WebSockets", + "Widgets", +] git-tree-sha1 = "adc25e225bc334c7df6eec3b39496edfc451cc38" uuid = "0f1e0344-ec1d-5b48-a673-e5cf874b6c29" version = "0.8.15" diff --git a/julia/mapbox-county-choropleth.md b/julia/mapbox-county-choropleth.md new file mode 100644 index 0000000..97b0999 --- /dev/null +++ b/julia/mapbox-county-choropleth.md @@ -0,0 +1,298 @@ +--- +jupyter: + jupytext: + notebook_metadata_filter: all + text_representation: + extension: .md + format_name: markdown + format_version: "1.2" + jupytext_version: 1.4.2 + kernelspec: + display_name: Julia 1.6.0 + language: julia + name: julia-1.6 + plotly: + description: How to make a Mapbox Choropleth Map of US Counties in Julia with + Plotly. + display_as: maps + language: julia + layout: base + name: Mapbox Choropleth Maps + order: 1 + page_type: example_index + permalink: julia/mapbox-county-choropleth/ + thumbnail: thumbnail/mapbox-choropleth.png +--- + +A [Choropleth Map](https://en.wikipedia.org/wiki/Choropleth_map) is a map composed of colored polygons. +It is used to represent spatial variations of a quantity. This page documents how to build **tile-map** +choropleth maps, but you can also build [**outline** choropleth maps using our non-Mapbox trace types](/julia/choropleth-maps). + +Below we show how to create Choropleth Maps using `choroplethmapbox` + +#### Mapbox Access Tokens and Base Map Configuration + +To plot on Mapbox maps with Plotly you _may_ need a Mapbox account and a public [Mapbox Access Token](https://www.mapbox.com/studio). See our [Mapbox Map Layers](/julia/mapbox-layers/) documentation for more information. + +### Introduction: main parameters for choropleth tile maps + +Making choropleth Mapbox maps requires two main types of input: + +1. GeoJSON-formatted geometry information where each feature has either an `id` field or some identifying value in `properties`. +2. A list of values indexed by feature identifier. + +The GeoJSON data is passed to the `geojson` argument, and the data is passed into the `z` argument of `choroplethmapbox`, in the same order as the IDs are passed into the `location` argument. + +**Note** the `geojson` attribute can also be the URL to a GeoJSON file, which can speed up map rendering in certain cases. + +#### GeoJSON with `feature.id` + +Here we load a GeoJSON file containing the geometry information for US counties, where `feature.id` is a [FIPS code](https://en.wikipedia.org/wiki/FIPS_county_code). + +```julia +using PlotlyJS, JSON, HTTP + +response = HTTP.get("https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json") +counties = JSON.parse(String(response.body)) + +counties["features"][1] +``` + +#### Data indexed by `id` + +Here we load unemployment data by county, also indexed by [FIPS code](https://en.wikipedia.org/wiki/FIPS_county_code). + +```julia +using PlotlyJS, CSV, HTTP, DataFrames +df = CSV.File( + HTTP.get("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv").body +) |> DataFrame +``` + +### Choropleth map using carto base map (no token needed) + +With `choroplethmapbox`, each row of the DataFrame is represented as a region of the choropleth. + +```julia +using PlotlyJS, CSV, JSON, HTTP, DataFrames + +response = HTTP.get("https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json") +counties = JSON.parse(String(response.body)) + +df = CSV.File( + HTTP.get("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv").body, + types=Dict("fips" => String) +) |> DataFrame + +f = open("./.mapbox_token") # you will need your own +token = String(read(f)) +close(f) + +trace = choroplethmapbox( + geojson=counties, + locations=df.fips, + z=df.unemp, + featureidkey="id", + coloraxis="coloraxis", + range_color=[0,12], + marker_opacity=0.5, +) + +plot(trace, + Layout( + mapbox=attr( + accesstoken=token, + style="carto-positron", + center=attr(lat=37.0902, lon=-95.7129), + zoom=3, + ), + coloraxis_colorscale=colors.viridis, + margin=attr(r=0,t=0,l=0,b=0) + ) +) +``` + +### Indexing by GeoJSON Properties + +If the GeoJSON you are using either does not have an `id` field or you wish you use one of the keys in the `properties` field, you may use the `featureidkey` parameter to specify where to match the values of `locations`. + +In the following GeoJSON object/data-file pairing, the values of `properties.district` match the values of the `district` column: + +```julia +using PlotlyJS, CSV, JSON, DataFrames + +df = dataset(DataFrame, "election") +geojson = dataset("election_geo") + +df.district[3] +geojson["features"][1]["properties"] +``` + +To use them together, we set `locations` to `district` and `featureidkey` to `"properties.district"`. The `z` is set to the number of votes by the candidate named Bergeron. + +```julia +using PlotlyJS, CSV, JSON, DataFrames + +df = dataset(DataFrame, "election") +geojson = dataset("election_geo") + +trace = choroplethmapbox( + geojson=geojson, + z=df.Bergeron, + locations=df.district, + featureidkey="properties.district" +) + +plot(trace, + Layout( + mapbox=attr( + center=attr(lat=45.5517, lon=-73.7073), + style="carto-positron", + zoom=9 + ), + margin=attr(t=0,b=0,r=0,l=0) + ) +) +``` + + +### Discrete Colors + +In addition to [continuous colors](/julia/colorscales/), we can [discretely-color](/julia/discrete-color/) +our choropleth maps by setting `z` to a non-numerical column, like the name of the winner of an election. + + + +```julia +using PlotlyJS, CSV, JSON, DataFrames + +df = dataset(DataFrame, "election") +geojson = dataset("election_geo") + +trace = choroplethmapbox( + geojson=geojson, + z=df.winner, + locations=df.district, + featureidkey="properties.district" +) + +plot(trace, + Layout( + mapbox=attr( + center=attr(lat=45.5517, lon=-73.7073), + style="carto-positron", + zoom=9 + ), + margin=attr(t=0,b=0,r=0,l=0) + ) +) +``` + +TODO: Python specific? + + +#### Mapbox Light base map: free token needed + +```python +token = open(".mapbox_token").read() # you will need your own token + + +from urllib.request import urlopen +import json +with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response: + counties = json.load(response) + +import pandas as pd +df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv", + dtype={"fips": str}) + +import plotly.graph_objects as go + +fig = go.Figure(go.Choroplethmapbox(geojson=counties, locations=df.fips, z=df.unemp, + colorscale="Viridis", zmin=0, zmax=12, marker_line_width=0)) +fig.update_layout(mapbox_style="light", mapbox_accesstoken=token, + mapbox_zoom=3, mapbox_center = {"lat": 37.0902, "lon": -95.7129}) +fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0}) +fig.show() +``` + +```julia +using PlotlyJS, CSV, JSON, HTTP, DataFrames + +response = HTTP.get("https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json") +counties = JSON.parse(String(response.body)) + +df = CSV.File( + HTTP.get("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv").body, + types=Dict("fips" => String) +) |> DataFrame + +f = open("./.mapbox_token") # you will need your own +token = String(read(f)) +close(f) + +# TODO: Looks like zmin and zmax aren't doing anything +trace = choroplethmapbox( + geojson=counties, + locations=df.fips, + z=df.unemp, + zmin=0, + zmax=12, + featureidkey="id", + coloraxis="coloraxis", + range_color=[0,12], + marker_line_width=0, + marker_opacity=0.5, +) + +plot(trace, + Layout( + mapbox=attr( + accesstoken=token, + style="light", + center=attr(lat=37.0902, lon=-95.7129), + zoom=3, + ), + coloraxis_colorscale=colors.viridis, + margin=attr(r=0,t=0,l=0,b=0) + ) +) + +``` + +#### Reference + +See [function reference for `(choropleth_mapbox)`](https://plotly.com/python/reference/choroplethmapbox/) for more information about mapbox and their attribute options.