Creating Data Expressions

1002
6
Jump to solution
03-07-2022 05:57 AM
JD1016
by
Occasional Contributor III

Hello,

I'm new to Arcade and even newer to creating Data Expressions in Dashboards.  I have three fields that I can populate using Arcade in my AGO web map Configure Pop-Ups section.  Unfortunately, as we all know, these type of calculated fields do not show up in Dashboards and Globals are not present.  I've been reading over past postings and it seems the key for me would be to employ FeatureSetByPortalItem() and create a data expression inside Dashboards so this data can be used.  The three fields are Temporal Block, Hour, and Weekday. 

The code I'm using in AGO for Temporal Block is:

var t = Hour($feature.PresentDate);

When(

  t >= 22 || t < 6, "Night (10pm - 6am)",

  t >= 6 && t < 11, "Morning (6am - 11am)",

  t >= 11 && t < 13, "Midday (11am - 1pm)",

  t >= 13 && t < 17, "Afternoon (1pm - 5pm)",

  t >= 17 && t < 22, "Evening (5pm - 10pm)",

"Invalid date" );

The code I'm using in AGO for Hour is:

Hour($feature.PresentDate)

And the code I am using in AGO for Weekday is:

Weekday($feature.PresentDate)

Can someone please help me or give me some hints at how to create an Arcade expression employing FeatureSetByPortalItem that will perform these calculations inside Dashboard?

Thank you so much in advance.

Jeff

1 Solution

Accepted Solutions
jcarlson
MVP Esteemed Contributor

You'll want to check out the Arcade GitHub repo for lots of examples.

If all you want is to get those three items into your Data Expression, that's easy enough. The basic things to know about data expressions are the FeatureSetByPortalItem function to get your inputs, and then the basic structure of a FeatureSet's JSON definition so that you can build your own.

Also, just a side note: when you've got multiple conditions, they evaluate in order. So anything that fails to meet the ">= 22" condition will be less than 22 (or null) by definition, so you don't need to later use "< 22". Especially when you're using a numeric value, you can just evaluate in ascending or descending order.

And a side side note: since you're working with the hours field and one of your decoded strings spans the midnight mark, you can get that into a single condition by using the modulo (%) operator. Put another way, 23 % 22 = 1. So in the initial condition in that when function, we can use that to reduce the >= 22 hours to a small number that will be caught in the same condition.

var portal = Portal('your portal url')

var fs = FeatureSetByPortalItem(
    portal,
    'itemID of your service',
    0, // or whatever the layer index is
    ['PresentDate', 'any', 'other', 'fields', 'you', 'want'],
    false // unless you really need geometry, but it performs much better without
)

// Create a dictionary to hold our output
var out_dict = {
    fields: [
        {name: 'PresentDate', type: 'esriFieldTypeDate'},
        {name: 'Weekday',     type: 'esriFieldTypeString'},
        {name: 'Hour',        type: 'esriFieldTypeInteger'},
        {name: 'TimeString',  type: 'esriFieldTypeString'}
        // include any other fields you want in the output here
    ],
    geometryType: '',
    features: []
}

// Iterate over features, calculate new fields, push to dictionary
for (var f in fs){
    var t = Hour(f['PresentDate'])
    
    var time_str = When(
        (t % 22) < 6, "Night (10pm - 6am)",
        t < 11, "Morning (6am - 11am)",
        t < 13, "Midday (11am - 1pm)",
        t < 17, "Afternoon (1pm - 5pm)",
        t < 22, "Evening (5pm - 10pm)",
        t < 24, "Night (10pm - 6am)",
        "Invalid date"
    )
    
    var wkday = Weekday(f['PresentDate'])
    
    Push(
        out_dict['features'],
        {
            attributes: {
                PresentDate: f['PresentDate'],
                Weekday: wkday,
                Hour: t,
                TimeString: time_str
            }
        }
    )
}

return FeatureSet(Text(out_dict))

 

It looks like a lot, but once you get the basic syntax down, it's not that bad.

- Josh Carlson
Kendall County GIS

View solution in original post

6 Replies
jcarlson
MVP Esteemed Contributor

You'll want to check out the Arcade GitHub repo for lots of examples.

If all you want is to get those three items into your Data Expression, that's easy enough. The basic things to know about data expressions are the FeatureSetByPortalItem function to get your inputs, and then the basic structure of a FeatureSet's JSON definition so that you can build your own.

Also, just a side note: when you've got multiple conditions, they evaluate in order. So anything that fails to meet the ">= 22" condition will be less than 22 (or null) by definition, so you don't need to later use "< 22". Especially when you're using a numeric value, you can just evaluate in ascending or descending order.

And a side side note: since you're working with the hours field and one of your decoded strings spans the midnight mark, you can get that into a single condition by using the modulo (%) operator. Put another way, 23 % 22 = 1. So in the initial condition in that when function, we can use that to reduce the >= 22 hours to a small number that will be caught in the same condition.

var portal = Portal('your portal url')

var fs = FeatureSetByPortalItem(
    portal,
    'itemID of your service',
    0, // or whatever the layer index is
    ['PresentDate', 'any', 'other', 'fields', 'you', 'want'],
    false // unless you really need geometry, but it performs much better without
)

// Create a dictionary to hold our output
var out_dict = {
    fields: [
        {name: 'PresentDate', type: 'esriFieldTypeDate'},
        {name: 'Weekday',     type: 'esriFieldTypeString'},
        {name: 'Hour',        type: 'esriFieldTypeInteger'},
        {name: 'TimeString',  type: 'esriFieldTypeString'}
        // include any other fields you want in the output here
    ],
    geometryType: '',
    features: []
}

// Iterate over features, calculate new fields, push to dictionary
for (var f in fs){
    var t = Hour(f['PresentDate'])
    
    var time_str = When(
        (t % 22) < 6, "Night (10pm - 6am)",
        t < 11, "Morning (6am - 11am)",
        t < 13, "Midday (11am - 1pm)",
        t < 17, "Afternoon (1pm - 5pm)",
        t < 22, "Evening (5pm - 10pm)",
        t < 24, "Night (10pm - 6am)",
        "Invalid date"
    )
    
    var wkday = Weekday(f['PresentDate'])
    
    Push(
        out_dict['features'],
        {
            attributes: {
                PresentDate: f['PresentDate'],
                Weekday: wkday,
                Hour: t,
                TimeString: time_str
            }
        }
    )
}

return FeatureSet(Text(out_dict))

 

It looks like a lot, but once you get the basic syntax down, it's not that bad.

- Josh Carlson
Kendall County GIS
JD1016
by
Occasional Contributor III

Thank you so much Josh!  I really appreciate your help.

Jeff

0 Kudos
JD1016
by
Occasional Contributor III

Hi Josh,

I think I might have spoke too soon.  I added the script and upon testing received the following (see Data Expression Test.png attached).

I'm assuming I should be seeing data below my field headings.  Correct?

Thanks.

Jeff

0 Kudos
jcarlson
MVP Esteemed Contributor

Oh! Right! I completely forgot to mention, but data expressions don't like "naked" date values, and it returns an empty FeatureSet when it encounters them. To get around this, we need to dress up the date as a number.

Try replacing line 44 of the above expression with this:

PresentDate: Number(f['PresentDate'])

That should get you what you need.

- Josh Carlson
Kendall County GIS
0 Kudos
JD1016
by
Occasional Contributor III

That did it.  Thank you, Josh.

One quick additional related question...I would like to be able to add one more field, CrimeEntry, to the data available.  Am I understanding that I would need to add the CrimeEntry field after 'PresentDate' following FeatureSetByPortalItem, add it as a field in the out_dict fields section, call it out as a var for the iterate over features section, and then list it within out_dict for attributes section to see the corresponding crimes reported for that particular date?

Hope that makes sense...novice here...terminology escapes.

Jeff

0 Kudos
JD1016
by
Occasional Contributor III

First, I'd like to thank Josh Carlson for the big assist and the Community Forum in general for being such a great resource to GIS professionals. Truly outstanding. Secondly, I just wanted to post a follow-up to my last question.  I was able to add CrimeEntry to the original code which allowed me to associate temporal data with the particular crime reported at that given time and day.  The following is the modified data expression to achieve this result:

//Set which data I want to use with what fields I want as part of my output
var portal = Portal('your portal')
var fs = FeatureSetByPortalItem(
    portal,
    'your itemID',
    0, ['PresentDate', 'CrimeEntry'],
    false // unless you really need geometry, but it performs much better without
);
// Create an empty dictionary to hold our output
var out_dict = {
    fields: [
        {name: 'PresentDate', type:  'esriFieldTypeDate'},
        {name: 'CrimeEntry',  type:  'esriFieldTypeString'},
        {name: 'Weekday',     type:  'esriFieldTypeInteger'},
        {name: 'Hour',        type:  'esriFieldTypeInteger'},
        {name: 'TimeString',  type:  'esriFieldTypeString'}
        // include any other fields you want in the output here
    ],
    geometryType: '',
    features: []
}

// Iterate over features, calculate new fields, push to dictionary
for (var f in fs){
    var t = Hour(f['PresentDate'])
    
    
    var time_str = When(
        (t % 22) < 6, "Night (10pm - 6am)",
        t < 11, "Morning (6am - 11am)",
        t < 13, "Midday (11am - 1pm)",
        t < 17, "Afternoon (1pm - 5pm)",
        t < 22, "Evening (5pm - 10pm)",
        t < 24, "Night (10pm - 6am)",
        "Invalid date"
    )
    
    var wkday = Weekday(f['PresentDate'])
    
    
    Push(
        out_dict['features'],
        {
            attributes: {
                PresentDate: Number(f['PresentDate']),
                CrimeEntry: (f['CrimeEntry']),
                Weekday: wkday,
                Hour: t,
                TimeString: time_str
                
            }
        }
    )
}

return FeatureSet(Text(out_dict))