Tucan.Geo (tucan v0.7.0)

Copy Markdown View Source

Geographic plots.

All geographic plots project longitude and latitude coordinates on the plane with a cartographic projection, set by the :projection option. Common projections are :equal_earth or :natural_earth1 for world maps, :albers_usa for the United States and :mercator for small areas. Additional projection properties, like the :scale, the :center or the :rotate angles, can be set through the :projection_opts option.

Geographic data

Maps are drawn from geographic features in GeoJSON or TopoJSON format:

  • A TopoJSON file contains named objects, e.g. the states and the counties of the :us_10m dataset. Set the :feature option to the name of the object to draw its features, or the :mesh option to draw only the borders between them.
  • A GeoJSON file is expected to contain a feature collection, if neither :feature nor :mesh are set.

The :us_10m and :world_110m datasets default to their states and countries objects respectively.

The geographic features are loaded from a dataset or a URL, inline geographic data are not supported.

Combining maps

All plots of this module are single views with their own projection, so they can be combined with Tucan.layers/1, e.g. to draw some points on top of a base map. Use the same projection for all layers.

Tucan.layers([
  Tucan.Geo.basemap(:us_10m),
  Tucan.Geo.scatter(:airports, "longitude", "latitude", point_size: 4, point_color: "firebrick")
])
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","layer":[{"data":{"format":{"feature":"states","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/us-10m.json"},"height":300,"mark":{"fill":"#e3e3e3","stroke":"white","strokeWidth":0.5,"type":"geoshape"},"projection":{"type":"albersUsa"},"width":500},{"data":{"url":"https://vega.github.io/vega-datasets/data/airports.csv"},"encoding":{"latitude":{"field":"latitude","type":"quantitative"},"longitude":{"field":"longitude","type":"quantitative"}},"height":300,"mark":{"color":"firebrick","fillOpacity":0.7,"filled":true,"size":4,"type":"point"},"projection":{"type":"albersUsa"},"width":500}]}

Summary

Functions

Draws a base map of geographic features.

Draws lines between pairs of geographic locations, e.g. flight routes.

Draws paths connecting geographic locations, e.g. the track of a storm or the route of a trip.

Draws points at geographic locations.

Functions

basemap(geodata, opts \\ [])

@spec basemap(geodata :: atom() | String.t(), opts :: keyword()) :: VegaLite.t()

Draws a base map of geographic features.

geodata is a dataset, e.g. :us_10m or :world_110m, or the URL of a GeoJSON or TopoJSON file. See the module documentation for the supported formats.

Options

  • :feature (String.t/0) - The name of the TopoJSON object whose features are drawn. Defaults to "states" for the :us_10m dataset and to "countries" for the :world_110m dataset.
  • :mesh (String.t/0) - The name of the TopoJSON object whose borders are drawn. Set it instead of :feature to draw only the borders between the features.

Styling Options

  • :fill_color (String.t/0) - The fill color of the features. The default value is "#e3e3e3".
  • :graticule (boolean/0) - Whether a graticule, the grid of meridians and parallels, is drawn. The default value is false.
  • :height (pos_integer/0) - The height of the plot in pixels. The default value is 300.
  • :line_color (String.t/0) - The color of the borders of the features. The default value is "white".
  • :projection - The cartographic projection. One of :albers, :albers_usa, :azimuthal_equal_area, :azimuthal_equidistant, :conic_conformal, :conic_equal_area, :conic_equidistant, :equal_earth, :equirectangular, :gnomonic, :mercator, :natural_earth1, :orthographic, :stereographic, :transverse_mercator. Defaults to :albers_usa for the :us_10m and :airports datasets and to :equal_earth otherwise.
  • :projection_opts (keyword/0) - Additional properties of the projection, e.g. [scale: 300, center: [20, 50]]. Check the Vega-Lite docs for the supported properties. The default value is [].
  • :sphere (boolean/0) - Whether the outline of the globe is drawn, filled with the :sphere_color. The default value is false.
  • :sphere_color (String.t/0) - The fill color of the sphere, if :sphere is set. The default value is "#e8f1f8".
  • :stroke_width - The width of the borders in pixels. The default value is 0.5.
  • :title (String.t/0) - The title of the plot.
  • :width (pos_integer/0) - The width of the plot in pixels. The default value is 500.

Interactivity Options

  • :tooltip (boolean() | :data | :encoding) - The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from. Can be one of the following:

    • :encoding - all fields from encoding are used
    • :data - all fields of the highlighted data point are used
    • true - same as :encoding
    • false, nil - no tooltip is used

Examples

The countries of the world, with the outline of the globe and a graticule:

Tucan.Geo.basemap(:world_110m, sphere: true, graticule: true)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","height":300,"layer":[{"data":{"sphere":true},"mark":{"fill":"#e8f1f8","stroke":"#cccccc","strokeWidth":0.5,"type":"geoshape"},"projection":{"type":"equalEarth"}},{"data":{"graticule":{"step":[15,15]}},"mark":{"fill":null,"stroke":"#cccccc","strokeWidth":0.3,"type":"geoshape"},"projection":{"type":"equalEarth"}},{"data":{"format":{"feature":"countries","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/world-110m.json"},"mark":{"fill":"#e3e3e3","stroke":"white","strokeWidth":0.5,"type":"geoshape"},"projection":{"type":"equalEarth"}}],"projection":{"type":"equalEarth"},"width":500}

The states of the US:

Tucan.Geo.basemap(:us_10m, fill_color: "#dce9d5", line_color: "#7a9a6f")
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","data":{"format":{"feature":"states","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/us-10m.json"},"height":300,"mark":{"fill":"#dce9d5","stroke":"#7a9a6f","strokeWidth":0.5,"type":"geoshape"},"projection":{"type":"albersUsa"},"width":500}

Only the borders between the counties of the US, with a mesh:

Tucan.Geo.basemap(:us_10m, mesh: "counties", line_color: "gray", stroke_width: 0.3)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","data":{"format":{"mesh":"counties","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/us-10m.json"},"height":300,"mark":{"fill":null,"stroke":"gray","strokeWidth":0.3,"type":"geoshape"},"projection":{"type":"albersUsa"},"width":500}

Europe, with an orthographic projection centered on it:

Tucan.Geo.basemap(:world_110m,
  projection: :orthographic,
  projection_opts: [rotate: [-15, -50, 0], scale: 500],
  sphere: true,
  graticule: true,
  width: 400,
  height: 400
)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","height":400,"layer":[{"data":{"sphere":true},"mark":{"fill":"#e8f1f8","stroke":"#cccccc","strokeWidth":0.5,"type":"geoshape"},"projection":{"rotate":[-15,-50,0],"scale":500,"type":"orthographic"}},{"data":{"graticule":{"step":[15,15]}},"mark":{"fill":null,"stroke":"#cccccc","strokeWidth":0.3,"type":"geoshape"},"projection":{"rotate":[-15,-50,0],"scale":500,"type":"orthographic"}},{"data":{"format":{"feature":"countries","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/world-110m.json"},"mark":{"fill":"#e3e3e3","stroke":"white","strokeWidth":0.5,"type":"geoshape"},"projection":{"rotate":[-15,-50,0],"scale":500,"type":"orthographic"}}],"projection":{"rotate":[-15,-50,0],"scale":500,"type":"orthographic"},"width":400}

choropleth(geodata, data, key, value, opts \\ [])

@spec choropleth(
  geodata :: atom() | String.t(),
  data :: Tucan.plotdata(),
  key :: String.t(),
  value :: String.t(),
  opts :: keyword()
) :: VegaLite.t()

Draws a choropleth map.

A choropleth map colors each geographic feature, e.g. the states of a country, by a value. The features of geodata are matched with the rows of data, by their :feature_key and the key field of the data, and colored by the value field. Features without a matching row, or without a valid value, are drawn with the :missing_color.

geodata is a dataset or the URL of a GeoJSON or TopoJSON file, see the module documentation for details, and data any data supported by Tucan.new/2.

Options

  • :feature (String.t/0) - The name of the TopoJSON object whose features are drawn. Defaults to "states" for the :us_10m dataset and to "countries" for the :world_110m dataset.
  • :feature_key (String.t/0) - The field of the geographic features that is matched with the key field of the data, e.g. "properties.name". TopoJSON features usually have an "id". The default value is "id".
  • :fields (list of String.t/0) - Additional fields of the data that are joined to the features, e.g. to be shown in the tooltip. The default value is [].
  • :mesh (String.t/0) - The name of the TopoJSON object whose borders are drawn. Set it instead of :feature to draw only the borders between the features.

Styling Options

  • :color_scheme (atom/0) - The color scheme to use, for supported color schemes check Tucan.Scale.
  • :height (pos_integer/0) - The height of the plot in pixels. The default value is 300.
  • :line_color (String.t/0) - The color of the borders of the features. The default value is "white".
  • :missing_color (String.t/0) - The fill color of the features without a value. The default value is "#e3e3e3".
  • :projection - The cartographic projection. One of :albers, :albers_usa, :azimuthal_equal_area, :azimuthal_equidistant, :conic_conformal, :conic_equal_area, :conic_equidistant, :equal_earth, :equirectangular, :gnomonic, :mercator, :natural_earth1, :orthographic, :stereographic, :transverse_mercator. Defaults to :albers_usa for the :us_10m and :airports datasets and to :equal_earth otherwise.
  • :projection_opts (keyword/0) - Additional properties of the projection, e.g. [scale: 300, center: [20, 50]]. Check the Vega-Lite docs for the supported properties. The default value is [].
  • :stroke_width - The width of the borders in pixels. The default value is 0.3.
  • :title (String.t/0) - The title of the plot.
  • :width (pos_integer/0) - The width of the plot in pixels. The default value is 500.

Interactivity Options

  • :tooltip (boolean() | :data | :encoding) - The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from. Can be one of the following:

    • :encoding - all fields from encoding are used
    • :data - all fields of the highlighted data point are used
    • true - same as :encoding
    • false, nil - no tooltip is used

Examples

The unemployment rate of the US counties:

Tucan.Geo.choropleth(:us_10m, :us_county_unemployment, "id", "rate",
  feature: "counties",
  color_scheme: :reds
)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","height":300,"layer":[{"data":{"format":{"feature":"counties","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/us-10m.json"},"mark":{"fill":"#e3e3e3","stroke":"white","strokeWidth":0.3,"type":"geoshape"},"projection":{"type":"albersUsa"}},{"data":{"format":{"feature":"counties","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/us-10m.json"},"encoding":{"color":{"field":"rate","scale":{"reverse":false,"scheme":"reds"},"type":"quantitative"}},"mark":{"stroke":"white","strokeWidth":0.3,"type":"geoshape"},"projection":{"type":"albersUsa"},"transform":[{"from":{"data":{"url":"https://vega.github.io/vega-datasets/data/unemployment.tsv"},"fields":["rate"],"key":"id"},"lookup":"id"}]}],"projection":{"type":"albersUsa"},"width":500}

The population of the US states, with a tooltip:

Tucan.Geo.choropleth(:us_10m, :us_state_population, "id", "population",
  fields: ["state"],
  color_scheme: :blues,
  tooltip: true
)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","height":300,"layer":[{"data":{"format":{"feature":"states","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/us-10m.json"},"mark":{"fill":"#e3e3e3","stroke":"white","strokeWidth":0.3,"tooltip":true,"type":"geoshape"},"projection":{"type":"albersUsa"}},{"data":{"format":{"feature":"states","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/us-10m.json"},"encoding":{"color":{"field":"population","scale":{"reverse":false,"scheme":"blues"},"type":"quantitative"},"tooltip":[{"field":"population"},{"field":"state"}]},"mark":{"stroke":"white","strokeWidth":0.3,"tooltip":true,"type":"geoshape"},"projection":{"type":"albersUsa"},"transform":[{"from":{"data":{"url":"https://vega.github.io/vega-datasets/data/population_engineers_hurricanes.csv"},"fields":["population","state"],"key":"id"},"lookup":"id"}]}],"projection":{"type":"albersUsa"},"width":500}

With inline data, where the states without a value are drawn in gray. The states are identified by their FIPS codes, e.g. 6 for California:

data = [
  %{fips: 6, score: 9},
  %{fips: 53, score: 7},
  %{fips: 41, score: 6},
  %{fips: 32, score: 4},
  %{fips: 8, score: 5},
  %{fips: 36, score: 3},
  %{fips: 12, score: 2},
  %{fips: 48, score: 1}
]

Tucan.Geo.choropleth(:us_10m, data, "fips", "score", color_scheme: :greens)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","height":300,"layer":[{"data":{"format":{"feature":"states","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/us-10m.json"},"mark":{"fill":"#e3e3e3","stroke":"white","strokeWidth":0.3,"type":"geoshape"},"projection":{"type":"albersUsa"}},{"data":{"format":{"feature":"states","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/us-10m.json"},"encoding":{"color":{"field":"score","scale":{"reverse":false,"scheme":"greens"},"type":"quantitative"}},"mark":{"stroke":"white","strokeWidth":0.3,"type":"geoshape"},"projection":{"type":"albersUsa"},"transform":[{"from":{"data":{"values":[{"fips":6,"score":9},{"fips":53,"score":7},{"fips":41,"score":6},{"fips":32,"score":4},{"fips":8,"score":5},{"fips":36,"score":3},{"fips":12,"score":2},{"fips":48,"score":1}]},"fields":["score"],"key":"fips"},"lookup":"id"}]}],"projection":{"type":"albersUsa"},"width":500}

connections(plotdata, longitude, latitude, longitude2, latitude2, opts \\ [])

@spec connections(
  plotdata :: Tucan.plotdata(),
  longitude :: String.t(),
  latitude :: String.t(),
  longitude2 :: String.t(),
  latitude2 :: String.t(),
  opts :: keyword()
) :: VegaLite.t()

Draws lines between pairs of geographic locations, e.g. flight routes.

longitude and latitude are the fields with the coordinates of the start of each line, and longitude2 and latitude2 the fields with the coordinates of its end.

The lines are straight lines on the projected map, and not great circles.

The lines are drawn without a map, combine them with a basemap/2 using Tucan.layers/1, see the module documentation.

Options

Data Grouping Options

  • :color_by (String.t/0) - If set a data field that will be used for coloring the data. It is considered :nominal by default.
  • :size_by (String.t/0) - If set a data field that will be used for controlling the size of the data points. It is considered :quantitative by default.

Styling Options

  • :height (pos_integer/0) - The height of the plot in pixels. The default value is 300.
  • :line_color (String.t/0) - The color of the line
  • :opacity (number/0) - The overall opacity of the mark The default value is 0.6.
  • :projection - The cartographic projection. One of :albers, :albers_usa, :azimuthal_equal_area, :azimuthal_equidistant, :conic_conformal, :conic_equal_area, :conic_equidistant, :equal_earth, :equirectangular, :gnomonic, :mercator, :natural_earth1, :orthographic, :stereographic, :transverse_mercator. Defaults to :albers_usa for the :us_10m and :airports datasets and to :equal_earth otherwise.
  • :projection_opts (keyword/0) - Additional properties of the projection, e.g. [scale: 300, center: [20, 50]]. Check the Vega-Lite docs for the supported properties. The default value is [].
  • :stroke_width - The width of the lines in pixels. Ignored if :size_by is set. The default value is 1.
  • :title (String.t/0) - The title of the plot.
  • :width (pos_integer/0) - The width of the plot in pixels. The default value is 500.

Interactivity Options

  • :tooltip (boolean() | :data | :encoding) - The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from. Can be one of the following:

    • :encoding - all fields from encoding are used
    • :data - all fields of the highlighted data point are used
    • true - same as :encoding
    • false, nil - no tooltip is used

Examples

Flights from London to some cities of the world, with made up weekly frequencies:

london = %{lon: -0.45, lat: 51.47}

routes =
  for {city, lon, lat, weekly} <- [
        {"New York", -73.78, 40.64, 140},
        {"Dubai", 55.36, 25.25, 90},
        {"Singapore", 103.99, 1.36, 35},
        {"Johannesburg", 28.24, -26.13, 21},
        {"São Paulo", -46.47, -23.43, 14},
        {"Tokyo", 139.78, 35.55, 28},
        {"Los Angeles", -118.41, 33.94, 50}
      ] do
    %{city: city, lon: london.lon, lat: london.lat, lon2: lon, lat2: lat, weekly: weekly}
  end

Tucan.layers([
  Tucan.Geo.basemap(:world_110m),
  Tucan.Geo.connections(routes, "lon", "lat", "lon2", "lat2",
    size_by: "weekly",
    line_color: "firebrick",
    tooltip: true
  )
])
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","layer":[{"data":{"format":{"feature":"countries","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/world-110m.json"},"height":300,"mark":{"fill":"#e3e3e3","stroke":"white","strokeWidth":0.5,"type":"geoshape"},"projection":{"type":"equalEarth"},"width":500},{"__tucan__":{"types":{"city":"nominal","lat":"quantitative","lat2":"quantitative","lon":"quantitative","lon2":"quantitative","weekly":"quantitative"}},"data":{"values":[{"city":"New York","lat":51.47,"lat2":40.64,"lon":-0.45,"lon2":-73.78,"weekly":140},{"city":"Dubai","lat":51.47,"lat2":25.25,"lon":-0.45,"lon2":55.36,"weekly":90},{"city":"Singapore","lat":51.47,"lat2":1.36,"lon":-0.45,"lon2":103.99,"weekly":35},{"city":"Johannesburg","lat":51.47,"lat2":-26.13,"lon":-0.45,"lon2":28.24,"weekly":21},{"city":"São Paulo","lat":51.47,"lat2":-23.43,"lon":-0.45,"lon2":-46.47,"weekly":14},{"city":"Tokyo","lat":51.47,"lat2":35.55,"lon":-0.45,"lon2":139.78,"weekly":28},{"city":"Los Angeles","lat":51.47,"lat2":33.94,"lon":-0.45,"lon2":-118.41,"weekly":50}]},"encoding":{"latitude":{"field":"lat","type":"quantitative"},"latitude2":{"field":"lat2"},"longitude":{"field":"lon","type":"quantitative"},"longitude2":{"field":"lon2"},"size":{"field":"weekly","type":"quantitative"}},"height":300,"mark":{"color":"firebrick","opacity":0.6,"strokeWidth":1,"tooltip":true,"type":"rule"},"projection":{"type":"equalEarth"},"width":500}]}

The flights from Seattle to other US airports. The coordinates of the airports are joined to the flights with lookup transforms:

airports = Tucan.Datasets.dataset(:airports)

lookup = fn vl, field, as ->
  VegaLite.transform(vl,
    lookup: field,
    from: [data: [url: airports], key: "iata", fields: ["longitude", "latitude"]],
    as: as
  )
end

flights =
  Tucan.new(:flights_airport)
  |> VegaLite.transform(filter: "datum.origin == 'SEA'")
  |> lookup.("origin", ["origin_lon", "origin_lat"])
  |> lookup.("destination", ["dest_lon", "dest_lat"])
  |> Tucan.Geo.connections("origin_lon", "origin_lat", "dest_lon", "dest_lat",
    projection: :albers_usa,
    size_by: "count",
    line_color: "steelblue"
  )

Tucan.layers([Tucan.Geo.basemap(:us_10m), flights])
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","layer":[{"data":{"format":{"feature":"states","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/us-10m.json"},"height":300,"mark":{"fill":"#e3e3e3","stroke":"white","strokeWidth":0.5,"type":"geoshape"},"projection":{"type":"albersUsa"},"width":500},{"data":{"url":"https://vega.github.io/vega-datasets/data/flights-airport.csv"},"encoding":{"latitude":{"field":"origin_lat","type":"quantitative"},"latitude2":{"field":"dest_lat"},"longitude":{"field":"origin_lon","type":"quantitative"},"longitude2":{"field":"dest_lon"},"size":{"field":"count","type":"quantitative"}},"height":300,"mark":{"color":"steelblue","opacity":0.6,"strokeWidth":1,"type":"rule"},"projection":{"type":"albersUsa"},"transform":[{"filter":"datum.origin == 'SEA'"},{"as":["origin_lon","origin_lat"],"from":{"data":{"url":"https://vega.github.io/vega-datasets/data/airports.csv"},"fields":["longitude","latitude"],"key":"iata"},"lookup":"origin"},{"as":["dest_lon","dest_lat"],"from":{"data":{"url":"https://vega.github.io/vega-datasets/data/airports.csv"},"fields":["longitude","latitude"],"key":"iata"},"lookup":"destination"}],"width":500}]}

path(plotdata, longitude, latitude, opts \\ [])

@spec path(
  plotdata :: Tucan.plotdata(),
  longitude :: String.t(),
  latitude :: String.t(),
  opts :: keyword()
) :: VegaLite.t()

Draws paths connecting geographic locations, e.g. the track of a storm or the route of a trip.

longitude and latitude are the fields with the coordinates of the points of each path.

The paths are drawn without a map, combine them with a basemap/2 using Tucan.layers/1, see the module documentation.

Options

  • :order_by (String.t/0) - A field used for ordering the points of each path, e.g. a timestamp. If not set the points are connected in the order of the data.

Data Grouping Options

  • :color_by (String.t/0) - A field used for coloring the paths. A separate path is drawn per color.
  • :group_by (String.t/0) - A field used for drawing a separate path for each group.

Styling Options

  • :height (pos_integer/0) - The height of the plot in pixels. The default value is 300.
  • :line_color (String.t/0) - The color of the line
  • :points (boolean/0) - Whether a point is drawn at each location. The default value is false.
  • :projection - The cartographic projection. One of :albers, :albers_usa, :azimuthal_equal_area, :azimuthal_equidistant, :conic_conformal, :conic_equal_area, :conic_equidistant, :equal_earth, :equirectangular, :gnomonic, :mercator, :natural_earth1, :orthographic, :stereographic, :transverse_mercator. Defaults to :albers_usa for the :us_10m and :airports datasets and to :equal_earth otherwise.
  • :projection_opts (keyword/0) - Additional properties of the projection, e.g. [scale: 300, center: [20, 50]]. Check the Vega-Lite docs for the supported properties. The default value is [].
  • :stroke_width - The width of the paths in pixels. The default value is 2.
  • :title (String.t/0) - The title of the plot.
  • :width (pos_integer/0) - The width of the plot in pixels. The default value is 500.

Interactivity Options

  • :tooltip (boolean() | :data | :encoding) - The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from. Can be one of the following:

    • :encoding - all fields from encoding are used
    • :data - all fields of the highlighted data point are used
    • true - same as :encoding
    • false, nil - no tooltip is used

Examples

The (approximate) tracks of two Atlantic hurricanes:

tracks =
  for {storm, points} <- [
        {"Katrina",
         [
           {-75.1, 23.1},
           {-77.6, 24.8},
           {-80.1, 26.0},
           {-82.6, 25.1},
           {-85.3, 25.2},
           {-87.8, 26.2},
           {-89.6, 28.2},
           {-89.6, 30.8},
           {-88.6, 34.0},
           {-86.0, 37.0}
         ]},
        {"Ike",
         [
           {-37.0, 17.2},
           {-50.0, 21.0},
           {-60.2, 22.8},
           {-68.0, 21.4},
           {-74.3, 21.1},
           {-79.0, 21.8},
           {-84.6, 23.1},
           {-89.4, 25.6},
           {-94.7, 29.3},
           {-93.0, 35.4}
         ]}
      ],
      {{lon, lat}, step} <- Enum.with_index(points) do
    %{storm: storm, lon: lon, lat: lat, step: step}
  end

projection = [projection: :mercator, projection_opts: [scale: 420, center: [-66, 27]]]

Tucan.layers([
  Tucan.Geo.basemap(:world_110m, projection),
  Tucan.Geo.path(
    tracks,
    "lon",
    "lat",
    [order_by: "step", color_by: "storm", points: true] ++ projection
  )
])
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","layer":[{"data":{"format":{"feature":"countries","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/world-110m.json"},"height":300,"mark":{"fill":"#e3e3e3","stroke":"white","strokeWidth":0.5,"type":"geoshape"},"projection":{"center":[-66,27],"scale":420,"type":"mercator"},"width":500},{"__tucan__":{"types":{"lat":"quantitative","lon":"quantitative","step":"quantitative","storm":"nominal"}},"data":{"values":[{"lat":23.1,"lon":-75.1,"step":0,"storm":"Katrina"},{"lat":24.8,"lon":-77.6,"step":1,"storm":"Katrina"},{"lat":26.0,"lon":-80.1,"step":2,"storm":"Katrina"},{"lat":25.1,"lon":-82.6,"step":3,"storm":"Katrina"},{"lat":25.2,"lon":-85.3,"step":4,"storm":"Katrina"},{"lat":26.2,"lon":-87.8,"step":5,"storm":"Katrina"},{"lat":28.2,"lon":-89.6,"step":6,"storm":"Katrina"},{"lat":30.8,"lon":-89.6,"step":7,"storm":"Katrina"},{"lat":34.0,"lon":-88.6,"step":8,"storm":"Katrina"},{"lat":37.0,"lon":-86.0,"step":9,"storm":"Katrina"},{"lat":17.2,"lon":-37.0,"step":0,"storm":"Ike"},{"lat":21.0,"lon":-50.0,"step":1,"storm":"Ike"},{"lat":22.8,"lon":-60.2,"step":2,"storm":"Ike"},{"lat":21.4,"lon":-68.0,"step":3,"storm":"Ike"},{"lat":21.1,"lon":-74.3,"step":4,"storm":"Ike"},{"lat":21.8,"lon":-79.0,"step":5,"storm":"Ike"},{"lat":23.1,"lon":-84.6,"step":6,"storm":"Ike"},{"lat":25.6,"lon":-89.4,"step":7,"storm":"Ike"},{"lat":29.3,"lon":-94.7,"step":8,"storm":"Ike"},{"lat":35.4,"lon":-93.0,"step":9,"storm":"Ike"}]},"encoding":{"color":{"field":"storm","type":"nominal"},"latitude":{"field":"lat","type":"quantitative"},"longitude":{"field":"lon","type":"quantitative"},"order":{"field":"step","type":"quantitative"}},"mark":{"strokeWidth":2,"type":"line"},"projection":{"center":[-66,27],"scale":420,"type":"mercator"}},{"__tucan__":{"types":{"lat":"quantitative","lon":"quantitative","step":"quantitative","storm":"nominal"}},"data":{"values":[{"lat":23.1,"lon":-75.1,"step":0,"storm":"Katrina"},{"lat":24.8,"lon":-77.6,"step":1,"storm":"Katrina"},{"lat":26.0,"lon":-80.1,"step":2,"storm":"Katrina"},{"lat":25.1,"lon":-82.6,"step":3,"storm":"Katrina"},{"lat":25.2,"lon":-85.3,"step":4,"storm":"Katrina"},{"lat":26.2,"lon":-87.8,"step":5,"storm":"Katrina"},{"lat":28.2,"lon":-89.6,"step":6,"storm":"Katrina"},{"lat":30.8,"lon":-89.6,"step":7,"storm":"Katrina"},{"lat":34.0,"lon":-88.6,"step":8,"storm":"Katrina"},{"lat":37.0,"lon":-86.0,"step":9,"storm":"Katrina"},{"lat":17.2,"lon":-37.0,"step":0,"storm":"Ike"},{"lat":21.0,"lon":-50.0,"step":1,"storm":"Ike"},{"lat":22.8,"lon":-60.2,"step":2,"storm":"Ike"},{"lat":21.4,"lon":-68.0,"step":3,"storm":"Ike"},{"lat":21.1,"lon":-74.3,"step":4,"storm":"Ike"},{"lat":21.8,"lon":-79.0,"step":5,"storm":"Ike"},{"lat":23.1,"lon":-84.6,"step":6,"storm":"Ike"},{"lat":25.6,"lon":-89.4,"step":7,"storm":"Ike"},{"lat":29.3,"lon":-94.7,"step":8,"storm":"Ike"},{"lat":35.4,"lon":-93.0,"step":9,"storm":"Ike"}]},"encoding":{"color":{"field":"storm","type":"nominal"},"latitude":{"field":"lat","type":"quantitative"},"longitude":{"field":"lon","type":"quantitative"},"order":{"field":"step","type":"quantitative"}},"mark":{"opacity":1,"type":"circle"},"projection":{"center":[-66,27],"scale":420,"type":"mercator"}}]}

scatter(plotdata, longitude, latitude, opts \\ [])

@spec scatter(
  plotdata :: Tucan.plotdata(),
  longitude :: String.t(),
  latitude :: String.t(),
  opts :: keyword()
) :: VegaLite.t()

Draws points at geographic locations.

longitude and latitude are the fields with the coordinates of each point in degrees. The points can be colored and sized by data fields, e.g. for a bubble map.

The points are drawn without a map, combine them with a basemap/2 using Tucan.layers/1, see the module documentation.

Points outside the projection

Points that the projection cannot place are drawn at the top left corner of the plot, e.g. the airports of Guam with the :albers_usa projection, which covers only the 50 states. Filter them out of the data if needed.

Options

Data Grouping Options

  • :color_by (String.t/0) - If set a data field that will be used for coloring the data. It is considered :nominal by default.
  • :size_by (String.t/0) - If set a data field that will be used for controlling the size of the data points. It is considered :quantitative by default.

Styling Options

  • :fill_opacity (number/0) - The fill opacity of the plotted elements. The default value is 0.7.
  • :filled (boolean/0) - Whether the mark will be filled or not The default value is true.
  • :height (pos_integer/0) - The height of the plot in pixels. The default value is 300.
  • :point_color (String.t/0) - The color of the points
  • :point_shape - Shape of the point marks. Circle by default.
  • :point_size (pos_integer/0) - The pixel area of the marks. Note that this value sets the area of the symbol; the side lengths will increase with the square root of this value.
  • :projection - The cartographic projection. One of :albers, :albers_usa, :azimuthal_equal_area, :azimuthal_equidistant, :conic_conformal, :conic_equal_area, :conic_equidistant, :equal_earth, :equirectangular, :gnomonic, :mercator, :natural_earth1, :orthographic, :stereographic, :transverse_mercator. Defaults to :albers_usa for the :us_10m and :airports datasets and to :equal_earth otherwise.
  • :projection_opts (keyword/0) - Additional properties of the projection, e.g. [scale: 300, center: [20, 50]]. Check the Vega-Lite docs for the supported properties. The default value is [].
  • :title (String.t/0) - The title of the plot.
  • :width (pos_integer/0) - The width of the plot in pixels. The default value is 500.

Interactivity Options

  • :tooltip (boolean() | :data | :encoding) - The tooltip text string to show upon mouse hover or an object defining which fields should the tooltip be derived from. Can be one of the following:

    • :encoding - all fields from encoding are used
    • :data - all fields of the highlighted data point are used
    • true - same as :encoding
    • false, nil - no tooltip is used

Examples

The airports of the United States:

Tucan.Geo.scatter(:airports, "longitude", "latitude", point_size: 4)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","data":{"url":"https://vega.github.io/vega-datasets/data/airports.csv"},"encoding":{"latitude":{"field":"latitude","type":"quantitative"},"longitude":{"field":"longitude","type":"quantitative"}},"height":300,"mark":{"fillOpacity":0.7,"filled":true,"size":4,"type":"point"},"projection":{"type":"albersUsa"},"width":500}

A bubble map of some of the largest cities of the world, sized by their approximate metropolitan population in millions, on top of a world map:

cities = [
  %{city: "Tokyo", lon: 139.69, lat: 35.69, population: 37.4, continent: "Asia"},
  %{city: "Delhi", lon: 77.21, lat: 28.61, population: 31.0, continent: "Asia"},
  %{city: "Shanghai", lon: 121.47, lat: 31.23, population: 27.1, continent: "Asia"},
  %{city: "São Paulo", lon: -46.63, lat: -23.55, population: 22.0, continent: "South America"},
  %{city: "Mexico City", lon: -99.13, lat: 19.43, population: 21.8, continent: "North America"},
  %{city: "Cairo", lon: 31.24, lat: 30.04, population: 21.3, continent: "Africa"},
  %{city: "Mumbai", lon: 72.88, lat: 19.08, population: 20.7, continent: "Asia"},
  %{city: "New York", lon: -74.01, lat: 40.71, population: 18.8, continent: "North America"},
  %{city: "Lagos", lon: 3.38, lat: 6.52, population: 14.9, continent: "Africa"},
  %{city: "Moscow", lon: 37.62, lat: 55.76, population: 12.6, continent: "Europe"},
  %{city: "Paris", lon: 2.35, lat: 48.86, population: 11.1, continent: "Europe"},
  %{city: "Sydney", lon: 151.21, lat: -33.87, population: 5.0, continent: "Oceania"}
]

Tucan.layers([
  Tucan.Geo.basemap(:world_110m),
  Tucan.Geo.scatter(cities, "lon", "lat",
    size_by: "population",
    color_by: "continent",
    tooltip: true
  )
])
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","layer":[{"data":{"format":{"feature":"countries","type":"topojson"},"url":"https://vega.github.io/vega-datasets/data/world-110m.json"},"height":300,"mark":{"fill":"#e3e3e3","stroke":"white","strokeWidth":0.5,"type":"geoshape"},"projection":{"type":"equalEarth"},"width":500},{"__tucan__":{"types":{"city":"nominal","continent":"nominal","lat":"quantitative","lon":"quantitative","population":"quantitative"}},"data":{"values":[{"city":"Tokyo","continent":"Asia","lat":35.69,"lon":139.69,"population":37.4},{"city":"Delhi","continent":"Asia","lat":28.61,"lon":77.21,"population":31.0},{"city":"Shanghai","continent":"Asia","lat":31.23,"lon":121.47,"population":27.1},{"city":"São Paulo","continent":"South America","lat":-23.55,"lon":-46.63,"population":22.0},{"city":"Mexico City","continent":"North America","lat":19.43,"lon":-99.13,"population":21.8},{"city":"Cairo","continent":"Africa","lat":30.04,"lon":31.24,"population":21.3},{"city":"Mumbai","continent":"Asia","lat":19.08,"lon":72.88,"population":20.7},{"city":"New York","continent":"North America","lat":40.71,"lon":-74.01,"population":18.8},{"city":"Lagos","continent":"Africa","lat":6.52,"lon":3.38,"population":14.9},{"city":"Moscow","continent":"Europe","lat":55.76,"lon":37.62,"population":12.6},{"city":"Paris","continent":"Europe","lat":48.86,"lon":2.35,"population":11.1},{"city":"Sydney","continent":"Oceania","lat":-33.87,"lon":151.21,"population":5.0}]},"encoding":{"color":{"field":"continent","type":"nominal"},"latitude":{"field":"lat","type":"quantitative"},"longitude":{"field":"lon","type":"quantitative"},"size":{"field":"population","type":"quantitative"}},"height":300,"mark":{"fillOpacity":0.7,"filled":true,"tooltip":true,"type":"point"},"projection":{"type":"equalEarth"},"width":500}]}