I am trying to create breaks within a certain data field so that, within a Dashboard, a can have a bar chart that shows those bins. I want to do an Arcade expression rather than adjusting the data in a separate field, because these breaks are subject to change as the Dashboard is reviewed. To me this seems like it should be very easy, but nothing works and most frustratingly, there doesn't seem to be a way to actually see what isn't working, as you could on any IDE. Esri documentation is also, as usual for them, terrible. So I am hoping someone can help me. So far I have been working through ChatGPT (I know, I know...) to come up with something.
All I am trying to do is that a field "Taxlot_Acres", which as can be surmised by the name, is the area in acres of a taxlot. I want a bar chart attached to the layer that shows count of taxlots in each bin. This bar chart will dynamically reflect other filters on the layer. Here is what I have come up with so far:
// Connect to your hosted feature layer by portal item ID and layer index
var portal = Portal("https://www.arcgis.com");
var fs = FeatureSetByPortalItem(
portal,
"012345ABCEDF6789", // Your item ID
2, // Layer index
["Taxlot_Acres"], // Only bring in needed field
false // Exclude geometry (faster)
);
// Define output schema
var schema = {
fields: [
{ name: "bin", type: "esriFieldTypeString" },
{ name: "count", type: "esriFieldTypeInteger" }
]
};
// Initialize bin counters
var bins = {
"<1": 0,
"1–4": 0,
"5–9": 0,
"10–24": 0,
"25+": 0
};
// Loop through features and apply binning logic
for (var f in fs) {
var acres = f["Taxlot_Acres"];
if (acres == null) { continue; }
if (acres < 1) {
bins["<1"] += 1;
} else if (acres < 5) {
bins["1–4"] += 1;
} else if (acres < 10) {
bins["5–9"] += 1;
} else if (acres < 25) {
bins["10–24"] += 1;
} else {
bins["25+"] += 1;
}
}
// Convert dictionary to FeatureSet
var output = [];
for (var b in bins) {
Push(output, {
attributes: {
bin: b,
count: bins[b]
}
});
}
return FeatureSet(Text(output), schema);
I feel like I am almost there, though which GPT and Esri's lack of quality documentation, can't be sure of that. Can anyone advise? I would be so grateful.
This should work
// Connect to your hosted feature layer by portal item ID and layer index
var portal = Portal("https://www.arcgis.com");
var fs = FeatureSetByPortalItem(
portal,
"012345ABCEDF6789", // Your item ID
2, // Layer index
["Taxlot_Acres"], // Only bring in needed field
false // Exclude geometry (faster)
);
// Define output schema
var fields = [
{ name: "bin", type: "esriFieldTypeString" },
{ name: "count", type: "esriFieldTypeInteger" }
];
// Initialize bin counters
var bins = {
"<1": 0,
"1–4": 0,
"5–9": 0,
"10–24": 0,
"25+": 0
};
for (var f in fs) {
var acres = f["Taxlot_Acres"];
if (IsEmpty(acres)) continue;
When(
acres < 1, bins["<1"] += 1,
acres < 5, bins["1-5"] += 1,
acres < 10, bins["5-9"] += 1,
acres < 24, bins["10-24"] += 1,
bins["25+"] += 1
);
}
var features = [];
for (var b of bins) {
Push(features, { attributes: { bin: b.key, count: b.value } });
}
return FeatureSet({ fields: fields, features: features });
Says it can't execute 😕 I feel like I am doing something wrong I guess, but since Esri gives literally zero way to troubleshoot, I can't know...
You can trouble-shoot by using the Console function and opening the Console tab after clicking "Run"
The code would sometimes not run due to the bin names. If I changed them to this, it would run consistently
var bins = {
"a": 0,
"b": 0,
"c": 0,
"d": 0,
"e": 0
};
for (var f in fs) {
var acres = f["Taxlot_Acres"];
if (IsEmpty(acres)) continue;
When(
acres < 1, bins["a"] += 1,
acres < 5, bins["b"] += 1,
acres < 10, bins["c"] += 1,
acres < 24, bins["d"] += 1,
bins["e"] += 1
);
}
Then you would add the proper column names in the settings
Well, I did finally get it to work, except I need the bins to dynamically change when filters are adjusted. Doesn't seem like it can do this, since when connecting it to a filter, the source field (the new bin category field in this case) can't connect with any target field in the map layers. It sounds like what I actually need is FeatureSetByName, but the issue is that the layer I am trying to attach is in a layer group, and for various reasons I need it to be in this grouping. Looks like FeatureSetByName doesn't work with layers in groups? I mean I can't get it to work with layers that are at the top level either but if this is true I should basically just stop now and just do it the normal way of calculating the bins in the data itself
Maybe doing this by featuresetname would be better? The layer is called Inventory by Underutilization Rank. I should note that it is in a group layer, but I don't think that should matter
Now I am just trying to even see if I can load a layer at all. Nothing is working. I tried this and still no work:
// Attempt to load your map layer and count features
var fs = FeatureSetByName($map, "Inventory by Underutilization Rank", ["OBJECTID"], false);
// Count features
var total = Count(fs);
// Return result as one row
var features = [{
attributes: {
total_count: total
}
}];
var schema = {
fields: [
{ name: "total_count", type: "esriFieldTypeInteger" }
]
};
return FeatureSet(Text(features), schema);