# Summarize intersecting points in a popup

This sample demonstrates how use an Arcade expression in a PopupTemplate to summarize points from one layer that intersect a polygon in a different layer.

The map in this sample contains two layers: a polygon layer representing block groups and a point layer representing the locations of crimes. Each crime has a `desc_` field describing the type of crime committed. It also has a `is_night` field containing either a `1` (crime committed at night) or a `0` (crime committed during the day). This app uses a single Arcade expression to do the following each time the user clicks a feature and opens the popup:

1. Query the crimes that intersect a selected polygon.
2. Group those intersecting points by crime type and return the total count and average `is_night` value within each category.
3. Sort the groups in descending order by count.

These three steps are reflected in the expression below.

Use dark colors for code blocksCopy
``````<script type="text/arcgis-arcade" id="crimes-arcade">
// 1. Query the number of crimes that intersect a selected polygon
var crimes = Intersects(
\$feature,
FeatureSetByName(\$map,"San Diego crimes", ["desc_", "is_night"])
);

// 2. Group the intersecting points by crime type and return the total count
// and average `is_night` value within each category of crimes
var stats = GroupBy(crimes, ["desc_"],
[ { name: "total", expression: "1", statistic: "count" },
{ name: "night_avg", expression: "is_night", statistic: "avg" }
]
);

// 3. Sort the crime types in descending order by count.
var topCrimes = Top(OrderBy(Filter(stats, "desc_ <> ''"), "total desc"), 3);

var output = "";
if(Count(topCrimes) == 0){
return "No crimes committed in this area";
}
var num = 0;
// Format the results for display
for(var item in topCrimes){
num++;
var num_crimes = item.total;
var crimeType = item["desc_"];

// The isNight field has values of either 1 or 0.
// If the average value (night_avg) is high, then most crimes
// occurred at night. If the average is low, then
// the crimes typically occurred during daytime hours.

var timeOfDay = When(
item.night_avg >= 0.6, "at night",
item.night_avg <= 0.4, " during the daytime hours",
" at both night and day");

// Display crime type with count using template literals
output += `\${num}. \${crimeType}
-- Total offenses: \${Text(num_crimes, "#,###")}
-- Most crimes were reported \${timeOfDay}

`;
}
return output;
</script>``````

The Arcade documentation for GroupBy() contains additional information for how to query multiple statistics (e.g. sum, min, max, average, standard deviation, variance) in Arcade with a single function call.

After authoring the Arcade expression, you can reference it in JavaScript as a string value and set it to the expression property of the expressionInfos in the layer's `popupTemplate`.

Use dark colors for code blocksCopy
``````const arcadeScript = document.getElementById("crimes-arcade").text;

const blockGroups = new FeatureLayer({
title: "U.S. Census Block Groups",
portalItem: {
id: "181b322639d44fcba6e37d8b82910daf"
},
popupTemplate: {
title: "Tract: {Tract}, Block Group: {BLKGRP}",
content: "Top 3 crimes: <br\><br\>" +
"{expression/top-crimes}",
expressionInfos: [{
// the name is used to reference the expression value in the template
name: "top-crimes",
title: "Top crimes",
// the Arcade expression stored as text