如何在一定范围内分配值(0 - 1.0)

How to distribute values within a certain range (0 - 1.0)

在 Python 中,我有一个总和为 1.0 的值字典。

weights = {u'obj_1': 0.018564743024138134, u'obj_2': 0.012814665648003992, 
           u'obj_3': 0.38978992409415425, u'obj_4': 0.0594938403597285, 
           u'obj_5': 0.41613932145700294, u'obj_6': 0.10319750541697208}

我希望能够为其中一个设置一个新值,差值将平均分配给其余的。所有值的总和应始终为 1.0。

我写这个就是为了做到这一点。

set_inf = "obj_4"
set_weight = 0.9

rest = set_weight-weights[set_inf]
distribute_count = len(weights)-1
distribute_weight = rest/distribute_count

for inf, val in weights.items():
    if inf == set_inf:
        weights[inf] = set_weight
    else:
        new_val = val-distribute_weight
        weights[inf] = new_val

    print "%s : %s" % (inf, weights[inf])

输出:

obj_3 : 0.221688692166
obj_2 : -0.15528656628
obj_1 : -0.149536488904
obj_6 : -0.0649037265111
obj_5 : 0.248038089529
obj_4 : 0.9
Total sum: 1.0

obj_4设置了我想要的值,总和等于1.0。问题是我想确保每个值都不会低于 0,也不会超过 1.0。

这就是混乱的来源,我不确定处理它的最佳方法。如果我限制这些值,它仍然需要补偿其他值,否则总和不会是 1.0。我怎样才能实现这样的目标?

set_weight 可以是 0 到 1.0 之间的任何值。

这在很大程度上取决于您要实现的算法类型。如果将在您的实施中变为负值的值设置为零并将其余值分配给剩余的值对您有用,请尝试这样的事情

def updateDict(oldDict, key, val):
    assert(val <= 1.0)
    assert(sum(oldDict.values()) == 1.0)
    while sum(oldDict.values()) + val > 1.0:
        nVals = len(oldDict)
        diff = 1. - (sum(oldDict.values()) + val)
        diffPerVal = diff / nVals
        for k in oldDict:
            if oldDict[k] + diffPerVal >= 0.:
                oldDict[k] += diffPerVal
            else:
                oldDict[k] = 0.
    oldDict[key] = val

现在

d = {1: 0.5, 2: 0.5}
updateDict(d, 3, 0.2)

产量 d = {1: 0.4, 2: 0.4, 3: 0.2},而

d = {1: 0.2, 2: 0.8}
updateDict(d, 3, 0.9)

产量 d = {1: 0.0, 2: 0.10000000000000009, 3: 0.9}.

总和不是 1(我怪浮点精度),但我想你想这样做?

weights = {u'obj_1': 0.018564743024138134, u'obj_2': 0.012814665648003992,
           u'obj_3': 0.38978992409415425, u'obj_4': 0.0594938403597285,
           u'obj_5': 0.41613932145700294, u'obj_6': 0.10319750541697208}

set_inf = "obj_4"
set_weight = 0.9

rest = set_weight-weights[set_inf]
distribute_count = len(weights)-1
distribute_weight = rest/distribute_count

sum = 0.0
for inf, val in weights.items():
    if inf == set_inf:
        weights[inf] = set_weight
    else:
        weights[inf] = val*(1-set_weight)  # this changed

    print "%s : %s" % (inf, weights[inf])
    sum += weights[inf]
print "%s" % sum

这产生

obj_3 : 0.0389789924094
obj_2 : 0.0012814665648
obj_1 : 0.00185647430241
obj_6 : 0.0103197505417
obj_5 : 0.0416139321457
obj_4 : 0.9
0.994050615964

既然您的字典中已经有了分数,您只需要将其余数字乘以 0.1 (1 - 0.9)? 取决于你想要达到什么。

这似乎符合我的预期。

weights = [0.2, 0.4, 0.3, 0.1]

def update_value(index, new_value):
    dif = (1.0-new_value) / (1.0-weights[index])

    for i in range(len(weights)):
        if i == index:
            weights[i] = new_value
        else:
            weights[i] *= dif

如果新值小于或大于原始值,所有其他值都会相应地传播,这种方式有效。

update_value(1, 0.6)
# Returns [0.13333333333333336, 0.6, 0.19999999999999998, 0.06666666666666668]

update_value(1, 0.1)
# Returns: [0.30000000000000004, 0.1, 0.44999999999999996, 0.15000000000000002]

如果有更好的方法欢迎告诉我!