我有一组像这样的键值对:
{
'key1': [value1_1, value2_1, value3_1, ...],
'key2': [value1_2, value2_2, value3_2, ...],
...
}
以及与值列表顺序相同的列表,其中包含每个变量应该应用的权重。所以它看起来像[weight_1, weight_2, weight_3, ...]
。
我的目标是最终获得一个有序的键列表,其中键的总得分最高。请注意,这些值并非全部标准化/标准化,因此value1_x的范围可以是1 - 10,但值2_x的范围可以是1 - 100000.这对我来说是一个棘手的部分,因为我必须以某种方式规范化数据。
我正在努力使这个算法针对许多不同的值进行缩放,因此它需要相同的时间用于1或100(或至少以对数方式更多的时间)。那可能吗?我能解决这个问题吗?
答案 0 :(得分:1)
你无法获得线性时间,但你可以更快地完成;这对我来说似乎是一个矩阵,所以我建议你使用numpy
:
import numpy as np
keys = ['key1', 'key2', 'key3']
values = np.matrix([
[1.1, 1.2, 1.3, 1.4],
[2.1, 2.2, 2.3, 2.4],
[3.1, 3.2, 3.3, 3.4]
])
weights = np.matrix([[10., 20., 30., 40.]]).transpose()
res = (values * weights).transpose().tolist()[0]
items = zip(res, keys)
items.sort(reverse=True)
给出了
[(330.0, 'key3'), (230.0, 'key2'), (130.0, 'key1')]
对于np.dot和thanks to @Ondro,修改: to @unutbu for np.argsort,这是一个完全在numpy中的改进版本:
import numpy as np
# set up values
keys = np.array(['key1', 'key2', 'key3'])
values = np.array([
[1.1, 1.2, 1.3, 1.4], # values1_x
[2.1, 2.2, 2.3, 2.4], # values2_x
[3.1, 3.2, 3.3, 3.4] # values3_x
])
weights = np.array([10., 20., 30., 40.])
# crunch the numbers
res = np.dot(values, -weights) # negative of weights!
order = res.argsort(axis=0) # sorting on negative value gives
# same order as reverse-sort; there does
# not seem to be any way to reverse-sort
# directly
sortedkeys = keys[order].tolist()
会产生['key3', 'key2', 'key1']
。
答案 1 :(得分:0)
这是一个归一化函数,它将您的值线性转换为[0,1]
def normalize(val, ilow, ihigh, olow, ohigh):
return ((val-ilow) * (ohigh-olow) / (ihigh - ilow)) + olow
现在,使用normalize
计算具有标准化值的新字典。然后,按加权和排序:
def sort(d, weights, ranges):
# ranges is a list of tuples containing the lower and upper bounds of the corresponding value
newD = {k:[normalize(v,ilow, ihigh, 0, 1) for v,(ilow, ihigh) in zip(vals, ranges)] for k,val in d.iteritems()} # d.items() in python3
return sorted(newD, key=lambda k: sum(v*w for v,w in zip(newD[k], weights)))