在整个数组中规范化一个包含直接值和其他字典的字典数组

Normalising an array of dicts which contain both values directly and other dicts, across whole array

我有一个巨大的数组,看起来像(示例行):

[
        {
            'value':21,
            'openValues':{
                'a':24,
                'b':56,
                'c':78
                }
        },
        {
            'value':12,
            'openValues':{
                'a':98,
                'b':3
                }
        },
        {
            'value':900,
            'openValues':{
                'a':7811,
                'b':171,
                'c':11211,
                'd':4231
                }
        }
        ]

我想将每个键中的所有值以及键中每个字典中的值标准化为 0 和 1 之间。例如:

以下是要执行的计算:

    [{
       'value':(21-12)/(900-12),
       'openValues':{'a':(24-24)/(7811-24),'b':(56-3)/(171-3),'c':(78-78)/(11211-78)}
     },
     {
       'value':(12-12)/(900-12),
       'openValues':{'a':(98-24)/(7811-24),'b':(3-3)/(171-3)}
     },
     {
       'value':(900-12)/(900-12),
       'openValues':{'a':(7811-24)/(7811-24),'b':(171-3)/(171-3),'c':(11211-78)/(11211-78),'d':(4231-4231)/(4231-4231)}
     }]

可以看到,每个value已经归一化了(减去最小值再除以取值范围),和openValues中的每个键值对一样。

我该怎么做?

我想找到一种比必须创建额外的 max/min/range 值和指令更快的方法,因为这是我现有的方法(这是计算 openValues 字典:

    openValuesMin = {}
    openValuesMax = {}
    for i, dict in enumerate(array):
        for property,value in dict['openValues'].items():
            if property not in openValuesMax:
                openValuesMax[property] = 0
            if openValuesMax[property]<value:
                openValuesMax[property]=value
            if property not in openValuesMin:
                openValuesMin[property] = 0
            if openValuesMin[property]>value:
                openValuesMin[property] = value

    openValuesRange = {key: openValuesMax[key] - openValuesMin.get(key, 0) for key in openValuesMax.keys()}

是否有以这种方式规范化一切的单行解决方案?

不确定我是否很好地理解了你的问题,但假设你想在 [0-1] 之间归一化,考虑到数组中所有可能项的最小值和最大值,这里有一个可能的解决方案:

array = [
    {
        'value': 21,
        'openValues': {
            'a': 24,
            'b': 56,
            'c': 78
        }
    },
    {
        'value': 12,
        'openValues': {
            'a': 98,
            'b': 3
        }
    },
    {
        'value': 900,
        'openValues': {
            'a': 7811,
            'b': 171,
            'c': 11211,
            'd': 4231
        }
    }
]


def normalize(v0, v1, t):
    return float(t - v0) / float(v1 - v0)


def f(v0, v1, item):
    return {
        "value": normalize(v0, v1, item["value"]),
        "openValues": {
            k: normalize(v0, v1, v) for k, v in item["openValues"].iteritems()
        }
    }

values = sum([[item["value"]] + item["openValues"].values()
              for item in array], [])
v_min, v_max = min(values), max(values)
output = [f(v_min, v_max, item) for item in array]
print output

编辑:

如果你想分别考虑 values 和 openValues 进行标准化,你可以像这样扩展上面的代码

array = [
    {
        'value': 21,
        'openValues': {
            'a': 24,
            'b': 56,
            'c': 78
        }
    },
    {
        'value': 12,
        'openValues': {
            'a': 98,
            'b': 3
        }
    },
    {
        'value': 900,
        'openValues': {
            'a': 7811,
            'b': 171,
            'c': 11211,
            'd': 4231
        }
    }
]


def normalize(v0, v1, t):
    return float(t - v0) / float(v1 - v0)


def f(vmin0, vmax0, vmin1, vmax1, item):
    return {
        "value": normalize(vmin0, vmax0, item["value"]),
        "openValues": {
            k: normalize(vmin1, vmax1, v) for k, v in item["openValues"].iteritems()
        }
    }

values = [item["value"] for item in array]
v_min0, v_max0 = min(values), max(values)
values = sum([item["openValues"].values() for item in array], [])
v_min1, v_max1 = min(values), max(values)

output = [f(v_min0, v_max0, v_min1, v_max1, item) for item in array]
print output