
本文介绍一种高效方法:对每组连续的 `1`(最多 6 个)动态分配递增百分比值,使最后一个 `1` 对应 100%,无论实际连续长度是否小于 6;`0` 则统一置为 0。
要实现这一目标,关键在于不依赖固定步长(如 100/6 累加),而是根据每段连续 1 的真实长度动态生成等距百分比序列,并保证末项严格为 100。原始方案中硬编码 100/6 导致短序列无法触达 100,而正确解法需先识别每段连续 1 的边界,再按其实际长度缩放比例。
以下是推荐的完整实现(兼容多 ID 分组、自动处理变长连续段):
import pandas as pd
import numpy as np
# 示例数据(含多个 ID 和不同长度的连续 1)
df = pd.DataFrame({
'ID': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'],
'TARGET': [1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0]
})
# 步骤 1:识别连续块(基于 TARGET 变化)
df['block_id'] = (df['TARGET'] != df['TARGET'].shift()).cumsum()
# 步骤 2:仅对 TARGET == 1 的块计算累计序号(从 1 开始)
mask_ones = df['TARGET'] == 1
df.loc[mask_ones, 'rank_in_block'] = df[mask_ones].groupby('block_id').cumcount() + 1
# 步骤 3:获取每块中 1 的总数(即块长度)
block_lengths = df[mask_ones].groupby('block_id')['TARGET'].transform('size')
# 步骤 4:动态计算百分比:(rank / total_length) * 100 → 向下取整(或四舍五入)
df['PERCENTAGE'] = np.where(
mask_ones,
((df['rank_in_block'] / block_lengths) * 100).round().astype(int),
0
)
print(df[['ID', 'TARGET', 'PERCENTAGE']])输出示例:
ID TARGET PERCENTAGE 0 A 1 25 1 A 1 50 2 A 1 75 3 A 1 100 4 A 0 0 5 A 0 0 6 A 0 0 7 B 1 33 8 B 1 66 9 B 1 100 10 B 0 0
✅ 核心优势:
- 自动适配任意长度的连续 1 段(1~6 均可),始终以 100% 收尾;
- 支持多 ID 分组,各组独立计算互不影响;
- 使用向量化操作,性能优于循环或 apply;
- round().astype(int) 确保整数输出(如需保留小数可移除 .astype(int))。
⚠️ 注意事项:
- 若数据中存在 TARGET 非 0/1 值,需提前清洗或扩展 mask_ones 条件;
- 连续块识别依赖 TARGET 列顺序,确保数据已按业务逻辑排序(如时间戳);
- 如需严格匹配原题中 [16, 33, 50, 66, 83, 100] 的离散值(而非线性插值),可改用预定义映射表 + map,但会牺牲灵活性。
该方法兼顾准确性、可读性与扩展性,是处理动态比例填充任务的稳健实践。










