File size: 1,357 Bytes
87608ea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
"""General-purpose helpers used by evaluation modules.

The public evaluation path currently uses recursive scalar aggregation. The
small standalone interface avoids coupling metrics to command-line code.
"""

import math
from numbers import Number
from typing import Any, Dict


def key_average(items: list) -> Dict[str, Any]:
    """Recursively average matching finite numeric dictionary leaves.

    Args:
        items: List of nested dictionaries. Missing keys are ignored, nested
            dictionaries recurse, numeric NaNs are excluded, and unsupported
            leaf types are omitted.

    Returns:
        Dictionary with the union of supported keys and arithmetic means at
        numeric leaves. Returns an empty dictionary for an empty list.
    """
    if not items:
        return {}
    keys = set().union(*(item.keys() for item in items))
    result: Dict[str, Any] = {}
    for key in keys:
        values = [item[key] for item in items if key in item]
        if not values:
            continue
        if isinstance(values[0], dict):
            result[key] = key_average(values)
        elif isinstance(values[0], Number):
            finite_values = [value for value in values if not math.isnan(float(value))]
            result[key] = sum(finite_values) / len(finite_values) if finite_values else float("nan")
    return result