【发布时间】:2018-08-21 13:48:40
【问题描述】:
我有一个权重数据框,我想在其中将任何一个元素的最大权重限制为 30%。但是这样做时,权重之和会小于 1,因此所有其他元素的权重应该均匀增加,然后重复限制在 30%,直到所有权重之和为 1。
例如:
如果我的数据在 pandas 数据框中,我怎样才能有效地做到这一点? 注意:实际上我有 20 个元素,我想将它们限制在 10% ......所以涉及更多的处理。我还打算将此步骤运行 1000 次。
【问题讨论】:
我有一个权重数据框,我想在其中将任何一个元素的最大权重限制为 30%。但是这样做时,权重之和会小于 1,因此所有其他元素的权重应该均匀增加,然后重复限制在 30%,直到所有权重之和为 1。
例如:
如果我的数据在 pandas 数据框中,我怎样才能有效地做到这一点? 注意:实际上我有 20 个元素,我想将它们限制在 10% ......所以涉及更多的处理。我还打算将此步骤运行 1000 次。
【问题讨论】:
这是一种矢量化解决方案。这个想法是计算调整并在非上限值之间按比例分配。
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
【讨论】:
@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())
【讨论】: