我有一个权重数据框,其中我想将任何一个元素的最大权重限制为30%。但是,这样做的结果是,权重的总和小于1,因此应均匀增加所有其他元素的权重,然后重复限制为30%,直到所有权重的总和为1。
例如:
如果我的数据在熊猫数据框中,那么我该如何有效地做到这一点? 注意:实际上我有20个元素,但我想将其上限限制为10%...因此涉及的处理更多。我还打算将此步骤运行1000遍。
答案 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())