我有以下帶權重的資料框:
df = pd.DataFrame({'a': [0.1, 0.5, 0.1, 0.3], 'b': [0.2, 0.4, 0.2, 0.2], 'c': [0.3, 0.2, 0.4, 0.1],
'd': [0.1, 0.1, 0.1, 0.7], 'e': [0.2, 0.1, 0.3, 0.4], 'f': [0.7, 0.1, 0.1, 0.1]})
然后我使用以下方法對每一行進行標準化:
df = df.div(df.sum(axis=1), axis=0)
我想優化每一行的歸一化權重,使權重不小于 0 或大于 0.4。
如果權重大于 0.4,它將被剪裁為 0.4,額外的權重將按比例分配給其他條目(意味著第二大權重將獲得更多權重,因此它接近 0.4,如果有剩余重量,將分配給第三個,依此類推)。
這可以使用“優化”功能完成嗎?
謝謝你。
uj5u.com熱心網友回復:
不幸的是,我只能找到這個問題的回圈解決方案。當您修剪掉多余的重量并按比例重新分配時,重量過輕可能會超過限制。然后它們必須被修剪掉。并且回圈不斷重復,直到沒有價值超重。
如果所有專案都大于 0,則下面的代碼有效。處理重量為 0 的專案很棘手,因為您無法將多余的重量轉移給它們(根據您的比例公式)。您必須以某種方式為它們定義“種子”權重。
# The original data frame. No normalization yet
df = pd.DataFrame({
'a': [0.1, 0.5, 0.1, 0.3],
'b': [0.2, 0.4, 0.2, 0.2],
'c': [0.3, 0.2, 0.4, 0.1],
'd': [0.1, 0.1, 0.1, 0.7],
'e': [0.2, 0.1, 0.3, 0.4],
'f': [0.7, 0.1, 0.1, 0.1]}
)
values = df.to_numpy()
normalized = values / values.sum(axis=1)[:, None]
max_weight = 0.4
for i in range(len(values)):
row = normalized[i]
while True:
overweight = row > max_weight
if not overweight.any():
break
# Calculate the excess weight
excess_weight = row[overweight].sum() - (max_weight * overweight.sum())
# Distribute this excess weight proportionally to the underweight items
row[~overweight] = excess_weight / row[~overweight].sum() * row[~overweight]
# Clip the overweight to max_weight
row[overweight] = max_weight
# Floating point math is not exact. We test for "close to 1"
# as opposed to "exactly equal 1"
assert np.isclose(row.sum(), 1)
normalized[i] = row
values = normalized * values.sum(axis=1)[:, None]
輸出:
> df
a b c d e f
0.1 0.2 0.3 0.1 0.2 0.7
0.5 0.4 0.2 0.1 0.1 0.1
0.1 0.2 0.4 0.1 0.3 0.1
0.3 0.2 0.1 0.7 0.4 0.1
> pd.DataFrame(values, columns=df.columns)
a b c d e f
0.106667 0.213333 0.32 0.106667 0.213333 0.64
0.500000 0.400000 0.20 0.100000 0.100000 0.10
0.100000 0.200000 0.40 0.100000 0.300000 0.10
0.300000 0.200000 0.10 0.700000 0.400000 0.10
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/383414.html
