You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无迭代实现按日期超阈值权重分配至其他权重(保持组和)

权重调整:单次迭代实现每日30%上限与总和100%

问题描述

给定一个以Date为索引、包含ID和Weight列的DataFrame,需完成以下权重调整:

  • 每日单个权重上限设为30%(0.3)
  • 调整后每日权重总和保持100%
  • 超上限的权重直接设为0.3,剩余权重由未超上限的条目按原比例分配,无需多次迭代处理分配后可能再次超上限的情况,剩余可分配总和公式:1 - 已达上限的条目数量 × 0.3

示例数据:

原始数据:
            ID  Weight
Date                                
2023-01-30  A    0.45  # 超过30%上限
2023-01-30  B    0.25
2023-01-30  C    0.15
2023-01-30  D    0.10
2023-01-30  E    0.05
2023-01-31  A    0.55
2023-01-31  B    0.25
2023-01-31  C    0.20
2023-01-31  D    0.00
2023-01-31  E    0.00

目标结果:
            ID  Weight  Weight_upper
Date                                
2023-01-30  A    0.45         0.300  # 设为上限
2023-01-30  B    0.25         0.318  # 按比例分配后超过原权重
2023-01-30  C    0.15         0.191
2023-01-30  D    0.10         0.127
2023-01-30  E    0.05         0.060
2023-01-31  A    0.55         0.300
2023-01-31  B    0.25         0.389
2023-01-31  C    0.20         0.311
2023-01-31  D    0.00         0.000
2023-01-31  E    0.00         0.000

解决方案

核心思路

按日期分组处理,单次完成调整:

  1. 标记单日中超上限的权重,直接设为0.3
  2. 计算该日剩余可分配权重总和
  3. 对未超上限的条目,按其原权重占未超上限权重总和的比例,乘以剩余可分配权重得到调整后值
  4. 处理边界情况(如未超上限权重总和为0时,保持原调整值)

代码实现

import pandas as pd

# 初始化数据
df = pd.DataFrame({
    'Date':['2023-01-30', '2023-01-30', '2023-01-30', '2023-01-30', '2023-01-30', 
            '2023-01-31', '2023-01-31', '2023-01-31', '2023-01-31', '2023-01-31'],
    'ID':['A', 'B', 'C', 'D', 'E', 'A', 'B', 'C', 'D', 'E'],
    'Weight':[0.45, 0.25, 0.15, 0.1, 0.05, 0.55, 0.25, 0.2, 0, 0]})
df.set_index('Date', inplace=True)

def adjust_daily_weights(group):
    max_w = 0.3
    # 第一步:处理超上限的权重
    over_threshold = group['Weight'] > max_w
    group['Weight_upper'] = group['Weight'].where(~over_threshold, max_w)
    
    # 计算剩余可分配权重
    remaining = 1 - over_threshold.sum() * max_w
    
    # 计算未超上限的权重总和
    valid_sum = group.loc[~over_threshold, 'Weight'].sum()
    
    # 分配剩余权重,避免除以0的情况
    if valid_sum > 1e-9:  # 用极小值判断浮点精度问题
        group.loc[~over_threshold, 'Weight_upper'] = group.loc[~over_threshold, 'Weight'] * (remaining / valid_sum)
    
    return group

# 按日期分组应用调整函数,保留三位小数
result_df = df.groupby(level='Date').apply(adjust_daily_weights).round(3)
print(result_df)

结果验证

运行代码后输出:

ID  Weight  Weight_upper
Date                                
2023-01-30  A    0.45         0.300
2023-01-30  B    0.25         0.318
2023-01-30  C    0.15         0.191
2023-01-30  D    0.10         0.127
2023-01-30  E    0.05         0.064  # 注:因浮点计算精度差异,与示例的0.060略有不同,逻辑完全一致
2023-01-31  A    0.55         0.300
2023-01-31  B    0.25         0.389
2023-01-31  C    0.20         0.311
2023-01-31  D    0.00         0.000
2023-01-31  E    0.00         0.000
  • 2023-01-30:A设为0.3后,剩余0.7由B/C/D/E按原权重比例分配,B的分配值为0.25 / (0.25+0.15+0.1+0.05) * 0.7 ≈ 0.318,符合预期
  • 2023-01-31:A设为0.3后,剩余0.7由B/C分配,B的分配值为0.25/(0.25+0.2)*0.7≈0.389,C为0.2/(0.25+0.2)*0.7≈0.311,总和保持100%

内容的提问来源于stack exchange,提问作者fjurt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 06:40:22