Powered by AppSignal & Oban Pro

Choropleth Map of Florida Counties by Political Party

13_florida_counties_choropleth.livemd

Choropleth Map of Florida Counties by Political Party

Mix.install([
  {:plotly_ex, "~> 0.3"},
  {:kino, "~> 0.18"},
  {:req, "~> 0.5"}
])

Section

In Plotly.js v4, geo.fitbounds defaults to "locations". This example sets it explicitly to document that the projection fits the supplied counties.

County-level choropleth uses a custom GeoJSON file to define boundaries. geojson: accepts the decoded JSON map. featureidkey: "properties.FIPS" links GeoJSON features to locations: values by FIPS code. locations: must match the featureidkey property values in the GeoJSON.

alias Plotly.{Figure, Choropleth}

# County-level GeoJSON for Florida
geojson_url = "https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json"
geojson = Req.get!(geojson_url).body |> Jason.decode!()

# Filter to Florida (FIPS codes starting with "12")
fl_geojson = Map.update!(geojson, "features", fn features ->
  Enum.filter(features, fn f ->
    String.starts_with?(f["id"], "12")
  end)
end)

# Sample party affiliation data (illustrative)
# FIPS codes for Florida counties and party value: 1=Republican, 0=Democrat
party_data = [
  {"12001", 1}, {"12003", 1}, {"12005", 1}, {"12007", 1}, {"12009", 0},
  {"12011", 1}, {"12013", 1}, {"12015", 1}, {"12017", 0}, {"12019", 1},
  {"12021", 0}, {"12023", 1}, {"12027", 1}, {"12029", 1}, {"12031", 1},
  {"12033", 1}, {"12035", 0}, {"12037", 1}, {"12039", 1}, {"12041", 1},
  {"12043", 0}, {"12045", 1}, {"12047", 1}, {"12049", 0}, {"12051", 0},
  {"12053", 0}, {"12055", 1}, {"12057", 0}, {"12059", 1}, {"12061", 1},
  {"12063", 1}, {"12065", 1}, {"12067", 1}, {"12069", 0}, {"12071", 0},
  {"12073", 1}, {"12075", 1}, {"12077", 1}, {"12079", 1}, {"12081", 0},
  {"12083", 1}, {"12085", 1}, {"12086", 0}, {"12087", 0}, {"12089", 1},
  {"12091", 0}, {"12093", 1}, {"12095", 0}, {"12097", 0}, {"12099", 1},
  {"12101", 1}, {"12103", 1}, {"12105", 0}, {"12107", 1}, {"12109", 1},
  {"12111", 1}, {"12113", 1}, {"12115", 0}, {"12117", 1}, {"12119", 1},
  {"12121", 0}, {"12123", 1}, {"12125", 1}, {"12127", 0}, {"12129", 1},
  {"12131", 1}, {"12133", 1}
]

fips = Enum.map(party_data, &elem(&1, 0))
values = Enum.map(party_data, &elem(&1, 1))

Figure.new()
|> Figure.add_trace(
  Choropleth.new(
    geojson: fl_geojson,
    locations: fips,
    z: values,
    featureidkey: "id",
    colorscale: [[0, "blue"], [1, "red"]],
    zmin: 0,
    zmax: 1,
    showscale: false,
    hoverinfo: "location"
  )
)
|> Figure.update_layout(
  title: "Florida Counties — Political Party (Illustrative)",
  geo: %{
    scope: "usa",
    fitbounds: "locations",
    visible: false
  }
)
|> Plotly.show()