diff --git a/docs/manpage.rst b/docs/manpage.rst index 6cd651677..fecc679f7 100644 --- a/docs/manpage.rst +++ b/docs/manpage.rst @@ -1544,6 +1544,7 @@ The following aggregation functions are supported: - ``sum``: return the sum of every group - ``median``: return the median of every group - ``p``: return the QQ% percentile of every group. Two digits a required even for quantiles less than 10%, e.g., the 5% percentile should be requested as ``p05``. +- ``count``: return the number of elements of every group There is also the pseudo-function ``stats``, which is essentially a shortcut for ``min,p01,p05,median,p95,p99,max,mean,std``. It can also be applied to any other attribute than ``pval`` @@ -1664,7 +1665,7 @@ Note that parts that have a grammar defined elsewhere (e.g., Python attributes a ::= | ::= "(" ")" ::= - ::= "first" | "last" | "max" | "min" | "mean" | "median" | "std" | "sum" | + ::= "first" | "last" | "max" | "min" | "mean" | "median" | "std" | "sum" | | "count" ::= "p" [0-9] [0-9] ::= | ::= ("+" )+ diff --git a/reframe/frontend/reporting/utility.py b/reframe/frontend/reporting/utility.py index d08be5713..891e9ad63 100644 --- a/reframe/frontend/reporting/utility.py +++ b/reframe/frontend/reporting/utility.py @@ -17,7 +17,7 @@ class Aggregation: AGG_REGEX = re.compile(r'(?P\S+)\((?P\S+)\)|(?P\S+)') OP_REGEX = re.compile( - r'min|max|median|mean|std|first|last|sum|stats|p\d{2}' + r'min|max|median|mean|std|first|last|sum|stats|count|p\d{2}' ) Q_REGEX = re.compile(r'p(\d{2})') @@ -89,6 +89,8 @@ def _expr_from_op(col, op): return pl.col(col).last().alias(f'{col} (last)') elif op == 'sum': return pl.col(col).sum().alias(f'{col} (sum)') + elif op == 'count': + return pl.col(col).count().alias(f'{col} (count)') elif m := self.Q_REGEX.match(op): perc = m.group(1) if perc == '00': diff --git a/unittests/test_reporting.py b/unittests/test_reporting.py index 2d1138f1c..d95f31631 100644 --- a/unittests/test_reporting.py +++ b/unittests/test_reporting.py @@ -228,7 +228,8 @@ def test_parse_cmp_spec_period(time_period): @pytest.fixture(params=['first', 'last', 'mean', 'median', 'min', 'max', 'std', 'stats', 'sum', - 'p00', 'p01', 'p05', 'p95', 'p99']) + 'p00', 'p01', 'p05', 'p95', 'p99', + 'count']) def aggregator(request): return request.param @@ -289,6 +290,9 @@ def test_parse_cmp_spec_aggregations(aggregator): assert agg['pval (p95)'][0] == 10 elif aggregator == 'p05': assert agg['pval (p99)'][0] == 10 + elif aggregator == 'count': + assert 'pval (count)' in agg.columns + assert agg['pval (count)'][0] == num_recs # Check variant without base period match = parse_cmp_spec(f'now-1d:now/{aggregator}:/')