Arcade expression to count points in polygons

5914
8
Jump to solution
10-15-2020 04:26 AM
CMcDonald
Occasional Contributor II

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)
0 Kudos
2 Solutions

Accepted Solutions
CMcDonald
Occasional Contributor II

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

View solution in original post

0 Kudos
XanderBakker
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.

View solution in original post

8 Replies
CMcDonald
Occasional Contributor II

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

0 Kudos
XanderBakker
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.

CMcDonald
Occasional Contributor II

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?

0 Kudos
XanderBakker
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.

CMcDonald
Occasional Contributor II

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

0 Kudos
XanderBakker
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".

VadimS
by
New Contributor

What would be the approach to return domain descriptions (if the "FacilityType" field is using coded domain values in this example)?

0 Kudos
SarahHartholt
Occasional Contributor III

Wondering if it is possible to use this expression (or something similar) to display dynamic text in a map layout. I would like to display a count of points within a polygon in the map display. This is what I have so far but keep getting a table not found error: 

 

var Licence = 
 Distinct($feature["xxx.LicenceID"])
var Buff = FeatureSetByName($datastore, "Buffer_of_Site_Address_Points_500m",["BuferDist"], True)
var countSTA = Count(Intersects(Buff,Licence))
return countSTA

 

 

SarahHartholt_0-1629728771639.png

0 Kudos