use results of FeatureSet FOR LOOP in arcade as the input for additional functions

7885
15
Jump to solution
01-29-2021 01:57 PM
LynnBerni
Occasional Contributor II

I have a hosted Feature Layer (SampleSites) with water quality sampling locations. The sample data is saved in a hosted Table (BacteriaSamples) which has the SITEID field in common. From this table I am looking at the MPN_ECOLI field to designate a "rating" for each sample collected, based on the following criteria:

MPN_ECOLI <100 'Good'; > 405 'Poor'; 101-405 'Fair'

I have a When function inside a For Loop to create the rating for each sample and have tested that it works by returning a list in my expression (see my code example saved here).  But what I really want to do, and cannot figure out, is how to use the ratings created inside the loop as input for additional functions. 

Ultimately, my goal is to designate an Ecoli Rating for each site, as defined by the lowest quality samples collected at that site. For example, if any samples are rated as 'Poor', the Ecoli Rating for the site is deemed 'Poor'. If no samples are 'Poor', but some are 'Fair', then 'Fair'. Else 'Good'.

I tried using Distinct() inside the loop and got nothing.  I tried Distinct outside the loop and it returned [Poor], but if it was working it should have returned all three.  I know this because the first site that arcade "looks at" inside my expression has 49 bacteria samples, representing  Good, Fair, and Poor samples. Interestingly, the last sample in the list is rated as 'Poor'. (Is Distinct somehow looking at my last sample rating only?)

Couple other things to note:  I've been working on this expression in "configure popup" in ArcGIS Online. The hosted data is in Portal, but when I tried this expression in a web map in Portal, it doesn't work.

I'm thinking (hoping) Xander Bakker will have an answer for me 🙂

Thanks!
Lynn

p.s. ultimately, I want this expression to update the symbology of the sites, but as I understand it, that functionality is not yet available with arcade.

 

 

 

/*
store SiteID as a variable so it can be used to query
the BacteriaSamples table for matching records
*/
var siteId = $feature.SITEID

/*
Access Bacteria Samples (related table) as a FeatureSet with three
relevant fields and filtered on QA/QC status
*/
var samplesAll = Filter(FeatureSetById($map, /* Watershed - BacteriaSamples */ "Watershed_962", ['SAMPLEDATE', 'SITEID','MPN_ECOLI']), "QAQC_COMPL = 'yes'")

/*
Use SQL filter statement to access variable with "@";
essentially this creates a relate
*/
var filterStatement = "SITEID = @siteId"

//filter the table to find related records at each site
var samplesBysite = Filter(samplesAll, filterStatement)

//Store count of resulting records as a variable
var cnt = Count(samplesBysite)
Console("Number of Samples: " + cnt)
/*
loop thru the records to calculate a rating for each 
sample based on following criteria:
MPN_ECOLI<100=Good; >405=Poor; 101-405=Fair
*/

var rating = ''
if (cnt > 0) {
    for(var f in samplesBysite){
    
//returns a list of each sample rating
    rating += When(f.MPN_ECOLI < 100, 'Good', f.MPN_ECOLI > 405, 'Poor', 'Fair') + TextFormatting.NewLine   
    }
    return (rating)
    
} else {
    rating = "No sample data"
}

/*
Next, determine final ecoliRating for the site. If any sample rating is 'Poor', the final ecoliRating for the site is 'Poor'. If no samples are 'Poor' but some are 'Fair', then 'Fair'. Else 'Good'.   Help!!!
*/

 

 

 

 

0 Kudos
15 Replies
DavidPike
MVP Frequent Contributor

Glad it worked, but unsure of your view that symbology can't be changed on the fly.

It's my understanding that the arcade expression is evaluated per each map refresh/GET or refresh interval.  Surely symbolising by certain values will update the symbology accordingly, or is there an issue with the related table?

0 Kudos
LynnBerni
Occasional Contributor II

Yes, it's the related tables. Neither the $map or $datastore global variables are available to use in a symbology expression, so there's no way to access the related tables. So frustrating! 

DavidPike
MVP Frequent Contributor

To be honest I don't use AGOL and have done very limited Arcade custom popups in a standalone 10.6 Portal.

I've not even done a symbology expression! In what environment does the expression you have at the moment work on, and what does it do?

Can you not just create a new custom field/popup, which has your returned GOOD, FAIR, POOR etc. and then just symbolize using that new custom field?

0 Kudos
LynnBerni
Occasional Contributor II

The expression is working like a charm in the AGOL popups (see attached screenshot). Portal popups too, with a minor tweak. I started out trying to get this to work in Pro. Then switched to AGOL mainly because I wanted to create a map that's easy to share with colleagues who have limited GIS skills. 

Ideally, I wanted Arcade to customize symbology on the fly, without needing a new "rating" field, since my data is in an egdb and I don't have full access to easily add new fields. I'm using published REST services in the webmaps, which are referencing the tables that are updated whenever new water quality samples are submitted via Survey123.  Plus, I don't really want a "rating" field in my site points, since the value will change based on the samples being evaluated (as currently written, the expression looks at all samples collected at each site, but we'll also want to see ratings based on date ranges, such as comparing 3Q 2020 to 3Q 2019 for example).

In an attempt to symbolize the Good, Fair, Poor rating with a field calculation, I just exported a copy of my site points so I could add an "E.coli Rating" field.  Unfortunately though, the arcade field calculation in AGOL doesn't allow me to access a FeatureSet from other layers in the map...there's no $map variable! There is the $datastore variable which, "allows you to define a FeatureSet from any sub-layer of the Feature Layer that you’re currently working with in the Arcade editor."  I don't even know what that means. Ugh. 

Even if I could get it to work, the other bummer about field calculations is that they're static. Whereas an arcade expression in a popup (and hopefully someday in the symbology) is dynamic, and will update when the input to the expression updates. Like I said before, custom on-the-fly symbology is the dream!

So now, I jumped back into Pro and I'm trying to use my shiny new expression in a field calculation, but I can't figure out how to get at the related tables. I don't know how to access FeatureSets in the field calculation. Dagnabbit!!  It's frustrating how the Arcade functionality is different in each platform. 

Working with related data is so tricky. Maybe its time to abandon Arcade, at least for now.
David or @JoeBorgione, do either of you think Python would be a better solution? 

For now, in order to get these ratings published in a map asap, I'm just gonna crunch all the numbers in Excel and then use a join to "manually" add the ratings into my copy of the site points. Which is ridiculous, I know.

I hope this answered your questions David. Thanks again for all your help!

0 Kudos
JoeBorgione
MVP Emeritus

@LynnBerni  - I don't want to discourage you from using Arcade in favor of Python. With AGOL, you have no choice but to stick with Arcade; AGOL provides a means with which meaningful spatial data can be consumed by the non-gis population.  Using either Arcade or Python with related data is going to be a challenge.

That should just about do it....
0 Kudos
JoeBorgione
MVP Emeritus

 

PS: here's what your code looks like in the insert/edit code window.  For arcade, I use Java Script...

var rating = ''
if (cnt > 0) {
for(var f in samplesBysite){
//returns ratings for each sample in a list, with date
//When(f.MPN_ECOLI < 100, 'Good', f.MPN_ECOLI > 405, 'Poor', 'Fair') + " -- " + Text(f.SAMPLEDATE, 'MMMM Y') + TextFormatting.NewLine
//returns one E.coli Rating for the site
rating = When(f.MPN_ECOLI < 100, 'Good', f.MPN_ECOLI > 405, 'Poor', 'Fair')
if(rating=='Poor') break;
if(rating=='Fair') continue}

} else {
rating = "No samples"
}

return rating

  

That should just about do it....
0 Kudos