Summarize and explore point clusters in web apps

Table of Contents

Summarize and explore point clusters in web apps

https://www.esri.com/arcgis-blog/products/js-api-arcgis/mapping/summarize-and-explore-point-clusters-in-web-apps/


The ArcGIS API for JavaScript (JS API) version 4.18 added support for querying point clusters. This allows you to summarize and explore the features of a cluster in more detail, including the following scenarios:

  • Display the extent or convex hull of clustered features
  • Display all features belonging to a cluster
  • Display summary statistics for a cluster in a popup
  • Allow users to browse clustered features in a popup or view

The Point clustering -- query clusters sample app demonstrates each of these scenarios using popup actions.

[

Using popup actions, you can allow users to query clusters in a variety of ways.

Using popup actions, you can allow users to query clusters in a variety of ways.

](https://developers.arcgis.com/javascript/latest/sample-code/featurereduction-cluster-query/index.html)

The examples in this post leverage the the ArcGIS JS API's client-side query engine. This query engine operates completely within the browser, allowing you to execute fast and complex spatial, attribute, and statistical queries. Rapid browser-based computation makes data exploration fast and more engaging for users. For more information and examples related to the client-side query engine, read the Turbo charge your web apps with client-side queries blog post and the Query and filter guide page.

Before diving into some examples, let's take a quick tour of what clustering is and the clustering capabilities the JS API provides you out of the box.

If you are already familiar with clustering and how it works in the ArcGIS JS API, then feel free to skip to the Query cluster features section below.

Clustering overview

Clustering is a method of merging nearby and overlapping features into a single symbol to declutter the view. The size of the cluster icon indicates the number of features in each cluster relative to other clusters. Clustering is configured with the FeatureReductionCluster class, which is set on the featureReduction property of the layer.

layer.featureReduction = {
  type: "cluster"
}

For example, check out this map of earthquakes that occurred along the Aleutian Islands in June 2020.

[

Earthquakes clustered.

Earthquakes that occurred along the Aleutian Islands in June 2020. The points are clustered so you can easily see where more earthquakes occur.

](https://developers.arcgis.com/javascript/latest/sample-code/featurereduction-cluster/index.html)

Clustering helps you immediately see the relative density of features. When clustering is not enabled, it's difficult to discern areas with a lot of overlapping points.

Notice how the cluster of 1,000+ earthquakes in the previous image is not noticeable when the same layer is not clustered.

[

Earthquakes along the Aleutian Islands from the last 30 days. Not clustered.

Earthquakes that occurred along the Aleutian Islands in June 2020. In this visualization, each earthquake is represented with one point. When points aren't clustered, overlapping points make it difficult to see areas with a high number of earthquakes.

](https://developers.arcgis.com/javascript/latest/sample-code/featurereduction-cluster/index.html)

You can define cluster labels and popups to provide users with additional information about the cluster.

Click to view code snippet

Alternatively, you can use smart mapping methods to generate suggested popup templates and labels to apply to the layer.

Click to view code snippet

[

Clustered places of worship in India. The color of each graphic indicates the predominant religion of the cluster.

Clustered places of worship in India. The color of each graphic indicates the predominant religion of the cluster.

](https://developers.arcgis.com/javascript/latest/sample-code/featurereduction-cluster-query/index.html)

Clusters are styled so they match the layer's renderer. For example, in the image above, the layer is styled with a UniqueValueRenderer, which colors each place of worship based on its religion. Each cluster's color (and shape) is determined by the predominant religion contained within the cluster.

If the renderer styles the layer with a color, size, rotation, or opacity visual variable, the average value of the attribute among features in the cluster is used to render the cluster.

[

This layer visualizes the mW capacity of power plants using color. When clustering is enabled, the average capacity of the power plants in the cluster determines the color of the cluster graphic.

This layer visualizes the MW capacity of power plants using color. When clustering is enabled, the average capacity of the power plants in the cluster determines the color of the cluster graphic.

](https://jsapi.maps.arcgis.com/apps/mapviewer/index.html?webmap=ffe3baf032ec43c9afa7dd434791cfb6)

Query cluster features

Version 4.18 of the ArcGIS JS API adds support for querying cluster features. This is done with the aggregateIds property of the Query object. Simply pass the ObjectID of the cluster graphic to this property, and use it to query the clustered layer's layer view.

const layerView = await view.whenLayerView(layer);
const query = layerView.createQuery();
query.aggregateIds = [ clusterGraphic.getObjectId() ];
// specify any other query parameters and execute the query
const { features } = await layerView.queryFeatures(query);
// do something with these features...

The code snippets throughout this post leverage async/await to handle promises returned from client-side queries. The async/await pattern allows you to write asynchronous code as if it were synchronous. This modern approach makes the code simpler and easier to read.

The following example translates the previous code snippet from the async/await syntax to using then() callbacks.

Click to view code snippet

Prior to executing the query, however, you should ensure the ObjectID of the selected graphic belongs to a cluster graphic and not an individual feature. I check the isAggregate property on the graphic prior to each query using the function below.

function processParams(graphic, layerView) {
  if (!graphic || !layerView) {
    throw new Error("Graphic or layerView not provided.");
  }

  if (!graphic.isAggregate) {
    throw new Error("Graphic must represent a cluster.");
  }
}

I will follow this pattern of querying clusters within popup actions to demonstrate each of the following scenarios in this app:

Display the extent or convex hull of clustered features

When clustering is enabled, the spatial dispersion of clustered features isn't immediately obvious. Displaying the extent of a cluster's features helps the user understand the area claimed by the cluster.

To display the extent, simply call the queryExtent method on the layer view after specifying the cluster's ObjectID in the query.

Click to view code snippet

[

Clustered power plants with a square graphic indicating the cluster's extent.

](https://developers.arcgis.com/javascript/latest/sample-code/featurereduction-cluster-query/index.html)

While viewing the extent is instructive, the convex hull provides a more accurate representation of the spatial footprint of the clustered features. You can calculate the convex hull using the geometryEngine.

Click to view code snippet

[

Clustered power plants with a graphic indicating the cluster's convex hull.

](https://developers.arcgis.com/javascript/latest/sample-code/featurereduction-cluster-query/index.html)

Display all features in the view

There may be occasions when you want to display all features, or just a few of the clustered features directly in the view. For example, if you have a layer of clustered traffic incidents, perhaps you want to give the user the ability to display only features that represent fatalities.

To accomplish this, simply add the features returned from the query directly to the view. Remember to set a symbol to the returned graphics. I use the getDisplayedSymbol method to ensure the symbol matches the renderer of the layer.

Click to view code snippet

[

Clustered power plants. One cluster shows all features in the cluster.

](https://developers.arcgis.com/javascript/latest/sample-code/featurereduction-cluster-query/index.html)

Keep in mind that clusters are no longer valid once the view's scale changes. So features displayed in the view (and any other cluster information displayed to the user) should be cleared once the view's scale updates.

Display summary statistics

The popup displays useful information, such as cluster count, predominant value of string fields, and the average value of numeric fields. However, sometimes the suggested cluster popup doesn't display enough information to the user.

In the case of a layer rendered with a UniqueValueRenderer, you may want to display the count of each category in the cluster rather than display only the total count with the predominant value.

You can get this information with the outStatistics and groupByFieldsForStatistics query parameters.

Click to view code snippet

[

Clustered power plants with a popup showing statistics for the selected cluster.

](https://developers.arcgis.com/javascript/latest/sample-code/featurereduction-cluster-query/index.html)

Once the statistics are returned, you can display the results in the popup, or in another UI element, such as a table or chart. You can make the statistical summaries as simple or as complex as you want. The example below displays multiple charts summarizing the selected cluster's data.

[

This app displays 10 years of homicide data and summarizes it based on whether the crime was solved and the age, gender, and race of the victims. Each time the user clicks a cluster, the cluster is summarized by the charts to the right.

This app displays 10 years of homicide data and summarizes it based on whether the crime was solved and the age, gender, and race of the victims. Each time the user clicks a cluster, the cluster is summarized by the charts to the right.

](https://codepen.io/kekenes/full/wvzjBxm)

Browse features

While summaries and charts can be extremely useful, there are cases when the user would rather drill into the cluster and browse the popups of individual features. You can do this by querying for all features in the cluster and pushing them to the view's popup.

// push all features in cluster to the popup features
// to allow users to browse their popup templates
const { features } = await layerView.queryFeatures(query);
view.popup.features = features;

When a feature is selected in the popup, you can also display its location in the map. Again, don't forget to set a symbol on the graphic.

Click to view code snippet

[

](https://developers.arcgis.com/javascript/latest/sample-code/featurereduction-cluster-query/index.html)

Conclusion

While you can display lots of detailed information for clusters, it is important to remember you shouldn't use summary statistics from clusters as if it were the result of a scientific study. Clusters do not represent statistically significant hot spots. Instead, clustering is the result of aggregating points according to geohashes (spatial grids) to declutter the view.

Also, once the view's extent changes either by zooming in or out, a cluster's information in the previous view is no longer relevant and should be discarded.

Thanks for reading! Please reach out in the comments or email me directly if you have any questions or suggestions for improving to our clustering implementation.

Leave a Reply

Your email address will not be published. Required fields are marked *