Arcade expression to count points in polygons

389
6
10-15-2020 04:26 AM
Occasional Contributor

Hi, I want to build an arcade expression that will count the number of points in a polygon layer.

So for example I have a polygon layer called "Data Zones" and a point layer called "Bus Stops". I want to count the number of Bus Stops that are in each Data Zone. Both Layers will be in the same web map.

I believe I have to use the Intersects and Count functions and the expression has to be in the Polygon layer , I just can't can't get an expression to successfully work.

Thanks in advance

Tags (3)
Reply
0 Kudos
6 Replies
Occasional Contributor

I managed to get this expression to work but don't understand how the 'bus' and 'Bus' text works?!

Reply
0 Kudos
Esri Esteemed Contributor

Hi C McDonald ,

Let me try to provide some explanation on what you have created:

  • The first line assigns to variable "bus" the featureset (layer) that is accessed using the FeatureSetByName function. This function in your case will find a layer called "Bus Facilities" in your map ($map). In addition you optimize the expression by limiting the fields and not requesting the geometry.
  • The second line, has two nested functions. The Intersects will intersect the bus facilities featureset stored in variable "bus" obtained on line 1 and intersect it with the current feature (the data zone the user clicked on). This will return all the bus facilities in the current polygon. The Count function will then count the number of bus facilities found in the data zone. 
  • Line 3 returns the number of bus facilities in the data zone determined on line 2. 

Later on you might want to extend the expression and list some details of each bus facility found. This is also possible with Arcade.

Occasional Contributor

Thanks Xander Bakker, that's helpful.  I think I understand a bit more clearly now.

With reference to your last comment I actually have a field in the Bus Facilities Layer called which lists the type.  There are 3 types of entries: Bus Stop, Bus Shelter and Unknown.

So in theory I could generate a Count for each of these?

Reply
0 Kudos
Esri Esteemed Contributor

Hi C McDonald ,

That is indeed something you could do, using the GroupBy function. Have a look at the expression below:

  • Please note that I am using a name "FacilityType" for the field that contains the facility type, this should be replaced by the actual name of the field. (changes are required on lines 4, 17 and 22)
  • The script starts the same, accessing the bus facilities on line 4 and reducing the number of field o only the facility type field.
  • On line 7 the facilities are intersected with the data zone ($feature) and on line 10 a count is done of the facilities
  • On line 14 the this count is used to define how to proceed. If there are no bus facilities, it will not do the GroupBy and simply return a message "No bus facilities found" (see line 26
  • When you have bus facilities, the groupby is performed on line 17 with the COUNT statistics type grouping the facility types
  • On line 20 the first line of the result is generated which will show the total number of bus facilities found in the data zone
  • The loop on lines 21 to 23 will add a line for each facility type, showing the facility type description and the count 
  • the result is returned on line 29
// replace "FacilityType" with the real name of the field!

// get the bus layer with only the field that contains the facility type
var bus_fs = FeatureSetByName($map, "Bus Facilities", ["FacilityType"], False);

// Intersect the bus featureset with the current data zone ($feature)
var bus_facilities = Intersects(bus_fs, $feature);

// count al bus facilities
var cnt = Count(bus_facilities);

// validate if there are bus facilities
var result = "";
if (cnt > 0) {
// there are bus facilities found
// apply groupby to create a count per facility type
var stats = GroupBy(bus_facilities, "FacilityType", [{name: "FacilityCount", expression: "FacilityType", statistic: "COUNT" }]);

// loop through the statistics to create the result
result = cnt + " bus facilities found:";
for (var stat in stats) {
result += TextFormatting.NewLine + " - " + stat.FacilityType + " (" + stat.FacilityCount + ")";
}
} else {
// there are NO bus facilities found
result = "No bus facilities found";
}

return result;‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Not sure if this will work for you, since I don't have the data to test the expression against.

Occasional Contributor

Unfortunately I was unable to get this code to work despite substituting the field name however I found a way that seems to work.

var busstops = Filter(FeatureSetByName($map,"Bus Facilities"),"STOP_SHELT = 'Bus Stop'")
var countBusStops = Count(Intersects(busstops,$feature))
return countBusStops

Reply
0 Kudos
Esri Esteemed Contributor

Hi C McDonald ,

I see from your expression that the field is called "STOP_SHELT". This might require some small adjustments in the expression like shown below. A field that contains an underscore sometimes causes some problems when retrieving the information like $feature.Field_Name and it is better to use $feature["Field_Name"] . 

// using "STOP_SHELT" as name of the field in the code below

// get the bus layer with only the field that contains the facility type
var bus_fs = FeatureSetByName($map, "Bus Facilities", ["STOP_SHELT"], False);

// Intersect the bus featureset with the current data zone ($feature)
var bus_facilities = Intersects(bus_fs, $feature);

// count al bus facilities
var cnt = Count(bus_facilities);

// validate if there are bus facilities
var result = "";
if (cnt > 0) {
// there are bus facilities found
// apply groupby to create a count per facility type
var stats = GroupBy(bus_facilities, "STOP_SHELT", [{name: "FacilityCount", expression: "STOP_SHELT", statistic: "COUNT" }]);

// loop through the statistics to create the result
result = cnt + " bus facilities found:";
for (var stat in stats) {
result += TextFormatting.NewLine + " - " + stat["STOP_SHELT"] + " (" + stat["FacilityCount"] + ")";
}
} else {
// there are NO bus facilities found
result = "No bus facilities found";
}

return result;

Your code will not do a count per bus facility type but will just return the count of the bus stop. If that is what you want, don't use the expression above, but in a previous post you mentioned that you wanted to get a count per facility type and that is why I provided this expression. 

You you want to get the count per facility type and run into problems, it would be a possibility to create a group, share the web map and data with that group and invite me to that group using my ArcGIS Online username: "xbakker.spx".