如何获得一个列表的加权平均值,它的权重受Python 3.6中的变量的限制

我希望这个标题有意义.我想要达到的目的是获得不同价格的鞋子的加权平均价格.所以我举个例子:

list_prices = [12,12.7,13.5,14.3]
list_amounts = [85,100,30,54]
BuyAmount = x

我想知道我的加权平均价格,以及我为每双鞋支付的最高价格如果我购买x量的鞋子(假设我想先买最便宜的)

这就是我现在拥有的(我使用numpy):

    if list_amounts[0] >= BuyAmount:
        avgprice = list_prices[0]
        highprice = list_prices[0]

    elif (sum(list_amounts[0: 2])) >= BuyAmount:
        avgprice = np.average(list_prices[0: 2], weights=[list_amounts[0],BuyAmount - list_amounts[0]])
        highprice = list_prices[1]

    elif (sum(list_amounts[0: 3])) >= BuyAmount:
        avgprice = np.average(list_prices[0: 3], weights=[list_amounts[0],list_amounts[1],BuyAmount - (sum(list_amounts[0: 2]))])
        highprice = list_prices[2]

    elif (sum(list_amounts[0: 4])) >= BuyAmount:
        avgprice = np.average(list_prices[0: 4], weights=[list_amounts[0],list_amounts[1],list_amounts[2],BuyAmount - (sum(list_amounts[0: 3]))])
        highprice = list_prices[3]

    print(avgprice)
    print(highprice)

此代码有效,但可能过于复杂和广泛.特别是因为我想能够处理20个项目的金额和价格表.

有什么更好的方法呢?

最佳答案 这是一个通用的矢量化解决方案,使用cumsum替换那些切片的摘要和argmax,以获得用于设置IF-case操作的切片限制的适当索引 –

# Use cumsum to replace sliced summations - Basically all those 
# `list_amounts[0]`, `sum(list_amounts[0: 2]))`, `sum(list_amounts[0: 3])`, etc.
c = np.cumsum(list_amounts)

# Use argmax to decide the slicing limits for the intended slicing operations.
# So, this would replace the last number in the slices - 
# list_prices[0: 2], list_prices[0: 3], etc.
idx = (c >= BuyAmount).argmax()

# Use the slicing limit to get the slice off list_prices needed as the first
# input to numpy.average
l = list_prices[:idx+1]

# This step gets us the weights. Now, in the weights we have two parts. E.g.
# for the third-IF we have : 
# [list_amounts[0],list_amounts[1],BuyAmount - (sum(list_amounts[0: 2]))]
# Here, we would slice off list_amounts limited by `idx`.
# The second part is sliced summation limited by `idx` again.
w = np.r_[list_amounts[:idx], BuyAmount - c[idx-1]]

# Finally, plug-in the two inputs to np.average and get avgprice output.
avgprice = np.average(l,weights=w)

# Get idx element off list_prices as the highprice output.
highprice = list_prices[idx]

我们可以进一步优化以删除连接步骤(使用np.r_)并获得avgprice,就像这样 –

slice1_sum = np.multiply(list_prices[:idx], list_amounts[:idx]).sum()
        # or np.dot(list_prices[:idx], list_amounts[:idx])
slice2_sum = list_prices[idx]*(BuyAmount - c[idx-1])
weight_sum = np.sum(list_amounts[:idx]) + BuyAmount - c[idx-1]
avgprice = (slice1_sum+slice2_sum)/weight_sum
点赞