What is the best way to put a heatmap on a map?

We have a population of hundreds of thousands of companies with exact latlon coordinates for each company. Based on some search criteria, our users will be given the ability to filter the company list and be left with none, a few or thousands of companies. We’d like to visualize the location of these companies with a heatmap laid on top of a real map.

The easiest solution for us would be sending the exact coordinates for each company (possibly hundreds of thousands companies) in real time to some library to create an overlay dynamically. I guess that’s not really viable due to time constraints, but what would be a good strategy to deal with this?

Each company is situated in a county, we do have the latlon coordinate for the county center, and we can provide an aggregate number of companies in each county. The number of counties can very between 5 to 360, so we’re talking relatively small data at this point.

Also, we’d like for the user to be able to drill down in the map/results by clicking on the counties in the map. But it’s not an absolute requirement as we’ll provide other means of drilling down anyway.

Hi Remi,

I’ll try to break it down to topics:

Heat map

In Plotly terms, the heat map is a grid with the color channel representing a value in 2D. This is the description of the necessary data for a regular heatmap.
And here’s the most basic example with minimal data.

There are other examples here, showing the data needs.

If the heatmap is based on something physical e.g. geography, then you probably need square elements, which can currently be achieved by setting axis domains in sync with chart width/height, as in this example.

Heat map on a map

While there are choropleth trace types (https://plot.ly/python/choropleth-maps/) with which a heat map can be approximated, currently there’s no dedicated geo or Mapbox overlaid heat map. Map projections, especially those covering larger areas have distortions, causing that a heatmap grid that is of uniform pitch in screen space will have tiles that cover diverse land areas and shapes, so making the grid panels as a choropleth map might be better than just overlaying a map with a heatmap. If the places are discrete, point-like, then using scatter points is another alternative: The opacity of the scatter points can help tune the results such that it looks a bit more like density / heatmap rather than a scatterplot with very salient points, a bit like this.

Also, if a scatter plot is sufficient or preferred, Plotly has a Mapbox scatter integration, though the user needs to provide their own key.

Scalability, aggregation

Regarding the dynamic overlay creation based on larger datasets- with hundreds of thousands of points, the first bottleneck will be the network pipe, and the second bottleneck will be the scalability of the particular plot type. In fact, most of our current plots don’t support hundreds of thousands or millions of points, but some of them do, e.g. WebGL based scatter plots. Yet it’d be best to aggregate spatial distribution data into a heatmap (rectangular grid elements or county / municipality shapes) structure on the server side.

it’s also possible for the client side code (not Plotly.js code, just general userland code) to hold the entire dataset, as transmitting hundreds of thousands of data points on the network is resource intensive but feasible, and then filter this data on the client side. The result of the filtering is that the heatmap / choropleth data (per grid cell or per county / municipality shape) gets updated. The current version of plotly.js doesn’t do interactive multidimensional filtering on its own but we can suggest solutions.

Plotly also has filter and groupby options as well but in case of a crossfiltering solution external to the plotly.js charts itself, maybe it won’t be needed.

Events

It’s possible to register events on mouse action such as clicking, documented here. The event handler will have sufficient information to inform which county was clicked on, and appropriate action can be taken. The action, such as drilling down, including or excluding that county etc. needs to be developed - there’s a wide rage of possible things, for example, clicking on a chart causes a rerendering of another chart on the same page.

Thank you for the answer. To make this work with a heatmap, what I understand is that we’d have to aggregate data into a matrix to be rendered transparently on top of a map. That’s doable, but probably not very elegant.

While the original question was about heatmaps, I think the what best represents our needs is a choropleth map. Here is a working example with population; we’d want “number of companies” instead, so the change is minimal: http://bl.ocks.org/badosa/7856244

Yes indeed, if it meets your needs, a choropleth map is now a more idiomatic solution with plotly.js.
By mistake, I linked the Plotly Python choropleth examples above, but at least it shows an example for showing textual annotation over the choropleth. JavaScript choropleth examples

Is Plotly working on integrating Mapbox’s Heatmap layer type to plot proper heatmaps?
If so, what’s the status of that feature?

Thanks for your attention.

5 Likes

I’m also interested in how to use the Mapbox heatmap layer type.

Any hints on how to leverage plotly to do that would be great!