封顶/约束重量

时间:2018-08-21 13:48:41

标签: python pandas weighted

我有一个权重数据框,其中我想将任何一个元素的最大权重限制为30%。但是,这样做的结果是,权重的总和小于1,因此应均匀增加所有其他元素的权重,然后重复限制为30%,直到所有权重的总和为1。

例如:

如果我的数据在熊猫数据框中,那么我该如何有效地做到这一点? 注意:实际上我有20个元素,但我想将其上限限制为10%...因此涉及的处理更多。我还打算将此步骤运行1000遍。

2 个答案:

答案 0 :(得分:0)

这是一个矢量化解决方案。想法是计算调整并在非上限值之间按比例分配。

df = pd.DataFrame({'Elements': list('ABCDE'),
                   'Uncon': [0.53, 0.34, 0.06, 0.03, 0.03]})

df['Con'] = np.minimum(0.30, df['Uncon'])
nonmax = df['Con'].ne(0.30)

adj = (1 - df['Con'].sum()) * df['Uncon'].loc[nonmax] / df['Uncon'].loc[nonmax].sum()

df['Con'] = df['Con'].mask(nonmax, df['Uncon'] + adj)

print(df)

  Elements  Uncon  Con
0        A   0.53  0.3
1        B   0.34  0.3
2        C   0.06  0.2
3        D   0.03  0.1
4        E   0.03  0.1

答案 1 :(得分:0)

@jpp

以下是一种粗略的方法,从您的答案修改为迭代求解和重新概括。它确实产生了一个完美的答案……而while循环使它效率低下。有什么想法可以改进吗?

import pandas as pd
import numpy as np
cap = 0.1
df = pd.DataFrame({'Elements': list('ABCDEFGHIJKLMNO'),
               'Values': [17,11,7,5,4,4,3,2,1.5,1,1,1,0.8,0.6,0.5]})
df['Uncon'] = df['Values']/df['Values'].sum()
df['Con'] = np.minimum(cap, df['Uncon'])

while df['Con'].sum() < 1 or len(df['Con'][df['Con']>cap]) >=1:
    df['Con'] = np.minimum(cap, df['Con'])
    nonmax = df['Con'].ne(cap)

    adj = (1 - df['Con'].sum()) * df['Con'].loc[nonmax] / 
    df['Uncon'].loc[nonmax].sum()

    df['Con'] = df['Con'].mask(nonmax, df['Con'] + adj)
    print(df)
    print(df['Con'].sum())