series_stats_dynamic
You can use series_stats_dynamic when you need statistical summaries with easier property-based access, better code readability, or when integrating with other dynamic data structures. This is particularly useful in complex analytical workflows where referring to statistics by name (stats.min, stats.avg) is clearer than using array indices.
Usage#
Syntax#
series_stats_dynamic(array)Parameters#
| Parameter | Type | Description |
|---|---|---|
array |
dynamic | A dynamic array of numeric values. |
Returns#
A dynamic object containing the following statistical properties:
| Property | Description |
|---|---|
min |
The minimum value in the input array. |
min_idx |
The first position of the minimum value in the array. |
max |
The maximum value in the input array. |
max_idx |
The first position of the maximum value in the array. |
avg |
The average value of the input array. |
variance |
The sample variance of the input array. |
stdev |
The sample standard deviation of the input array. |
Use case examples#
In log analysis, you can use series_stats_dynamic to generate comprehensive statistical reports with readable property names.
Query
['sample-http-logs']
| summarize durations = make_list(req_duration_ms) by id
| extend stats = series_stats_dynamic(durations)
| extend performance_score = 100 - (stats.stdev / stats.avg * 100)
| project id,
min = stats.min,
max = stats.max,
avg = stats.avg,
performance_score
| take 5Output
| id | min | max | avg | performance_score |
|---|---|---|---|---|
| u123 | 15 | 245 | 95 | 52.4 |
| u456 | 8 | 189 | 78 | 50.4 |
This query uses property names to access statistics and calculate a custom performance score based on the coefficient of variation.
In security logs, you can use series_stats_dynamic to build adaptive anomaly detection thresholds with clear, self-documenting property access.
Query
['sample-http-logs']
| summarize durations = make_list(req_duration_ms) by status
| extend stats = series_stats_dynamic(durations)
| extend lower_bound = stats.avg - (2 * stats.stdev)
| extend upper_bound = stats.avg + (2 * stats.stdev)
| extend range_ratio = (stats.max - stats.min) / stats.avg
| project status,
avg_duration = stats.avg,
stdev = stats.stdev,
lower_bound,
upper_bound,
range_ratioOutput
| status | avg_duration | stdev | lower_bound | upper_bound | range_ratio |
|---|---|---|---|---|---|
| 200 | 52 | 12.5 | 27 | 77 | 6.44 |
| 401 | 450 | 850.2 | -1250.4 | 2150.4 | 19.68 |
| 500 | 125 | 95.3 | -65.6 | 315.6 | 4.36 |
This query uses named properties to calculate confidence intervals and assess the relative range of values for adaptive security monitoring.
List of related functions#
- series_stats: Returns the same statistics as a 7-element array instead of a dynamic object with named properties.
- series_max: Compares two arrays element-wise and returns the maximum values.
- series_min: Compares two arrays element-wise and returns the minimum values.
- todynamic: Converts values to dynamic type for custom object construction.
Other query languages#
Splunk SPL users
In Splunk SPL, you typically use multiple stats functions and store results as separate fields. In APL, series_stats_dynamic provides all statistics in a dynamic object that you can access by property names.
Splunk example
... | stats min(value) as min_val, max(value) as max_val,
avg(value) as avg_val, stdev(value) as stdev_val by userAPL equivalent
['sample-http-logs']
| summarize values = make_list(req_duration_ms) by id
| extend stats = series_stats_dynamic(values)
| extend min_val = stats.min, max_val = stats.max, avg_val = stats.avgANSI SQL users
In SQL, you calculate statistics separately and work with individual columns. In APL, series_stats_dynamic provides all statistics in a single dynamic object with named properties that you can query and transform.
SQL example
SELECT
user_id,
MIN(value) as min_val,
MAX(value) as max_val,
AVG(value) as avg_val,
STDDEV(value) as std_val
FROM measurements
GROUP BY user_id;APL equivalent
['sample-http-logs']
| summarize values = make_list(req_duration_ms) by id
| extend stats = series_stats_dynamic(values)
| extend min_val = stats.min, max_val = stats.max