我正在尝试使用Python编写一个函数,以在输入列表时找到一个最大值,该函数将限制列表中的值,并将从数字中减去的多余部分按比例重新分配给列表中的其他数字。
例如,我希望[0.05,0.02,0.05,0.08,0.80]通过最大为0.3的函数成为[0.175,0.07,0.175,0.28,0.30]。
目前,我在Python中有类似的内容:
'''
import numpy as np
x = np.array([0.05, 0.05, 0.02, 0.08, 0.80])
limit = 0.3
excess = 0
y = np.zeros(len(x))
z = np.zeros(len(x))
for i in range(len(x)):
if x[i] > limit:
excess = x[i] - limit
x[i] = 0
y[i] = limit
z = x*(1/sum(x)*excess)
z = z+x+y
'''
z是此特定数组的结果。
'''
z = array([0.175, 0.175, 0.07 , 0.28 , 0.3 ])
'''
但是,当我有多个超出限制的数字,或者数组的顺序不同时,这种情况就会消失。
答案 0 :(得分:0)
您可以使用以下脚本实现目标。这个想法是采用“多余的重量”,并在体重不足的元素上重复地分配它,直到所有元素都被覆盖。需要重新进行此过程,因为重新分配可能会使某些原本偏低的要素超出上限。另外,您没有明确提及它,但是基于财务标签和您的示例,我假设列表的总和需要保持不变。
首先,我创建了一个熊猫数据框,其中包含20个总计为1的值,并按降序对其进行排序。
Elements Uncon
3 D 0.081778
1 B 0.079887
19 T 0.079451
17 R 0.070283
11 L 0.068052
4 E 0.057335
12 M 0.054695
5 F 0.051099
6 G 0.049873
18 S 0.049469
14 O 0.045059
16 Q 0.043583
8 I 0.041186
2 C 0.036802
7 H 0.036315
13 N 0.035440
0 A 0.034311
15 P 0.031519
10 K 0.027173
9 J 0.026689
第二,我们将上限设置为0.06。对于您面临的多个超重元素问题,这将成为一个很好的测试案例。
cap = 0.06
weights = df.Uncon
下面是迭代脚本。
# Obtain constrained weights
constrained_wts = np.minimum(cap, weights)
# Locate all stocks with less than max weight
nonmax = constrained_wts.ne(cap)
# Calculate adjustment factor - this is proportional to original weights
adj = ((1 - constrained_wts.sum()) *
weights.loc[nonmax] / weights.loc[nonmax].sum())
# Apply adjustment to obtain final weights
constrained_wts = constrained_wts.mask(nonmax, weights + adj)
# Repeat process in loop till conditions are satisfied
while ((constrained_wts.sum() < 1) or
(len(constrained_wts[constrained_wts > cap]) >=1 )):
# Obtain constrained weights
constrained_wts = np.minimum(cap, constrained_wts)
# Locate all stocks with less than max weight
nonmax = constrained_wts.ne(cap)
# Calculate adjustment factor - this is proportional to original weights
adj = ((1 - constrained_wts.sum()) *
constrained_wts.loc[nonmax] / weights.loc[nonmax].sum())
# Apply adjustment to obtain final weights
constrained_wts = constrained_wts.mask(nonmax, constrained_wts + adj)
然后可以将结果重新分配给数据框并进行比较。
df['Cons'] = constrained_wts
Elements Uncon Cons
0 A 0.034311 0.039189
1 B 0.079887 0.060000
2 C 0.036802 0.042034
3 D 0.081778 0.060000
4 E 0.057335 0.060000
5 F 0.051099 0.058364
6 G 0.049873 0.056964
7 H 0.036315 0.041478
8 I 0.041186 0.047041
9 J 0.026689 0.030483
10 K 0.027173 0.031037
11 L 0.068052 0.060000
12 M 0.054695 0.060000
13 N 0.035440 0.040479
14 O 0.045059 0.051465
15 P 0.031519 0.036001
16 Q 0.043583 0.049780
17 R 0.070283 0.060000
18 S 0.049469 0.056502
19 T 0.079451 0.060000
元素M是说明为什么需要重复过程的一个很好的例子。它最初是轻量级的,但是非常接近上限,以至于在第一次重新分配后它会变得超重。