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

如何为300万行Pandas DataFrame生成无重复的拼接ID列?

问题描述

我有一个Pandas DataFrame,包含一列随机字母数字组合的id列,以及一列表示需为对应id添加的随机字符长度的missing列,数据量达300万行以上,示例如下:

id     missing
XK39J       4
NI94N       4
9IN3        5
MN83D       4
IUN2        5

我使用以下代码生成新的随机序列并拼接得到final_id:

import string
import random
import pandas as pd

def id_generator(size, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.SystemRandom().choice(chars) for _ in range(size))

data['new_id'] = data['missing'].apply(lambda x: id_generator(size=x))
data['final_id'] = data['id'] + data['new_id']

但生成的final_id列存在重复值,而我需要该列所有值唯一。我曾尝试将生成的ID存入列表并校验重复,但面对300万行数据时效率极低,代码如下:

def id_generator(size, chars=string.ascii_uppercase + string.digits):
    val_ls = []
    val = ''.join(random.SystemRandom().choice(chars) for _ in range(size))
    while val in val_ls:
       val = ''.join(random.SystemRandom().choice(chars) for _ in range(size))
    else:
       val_ls.append(val)
       return val

请问如何高效确保final_id列无重复?

高效解决方案

方法1:批量生成+重复补全(适合完全随机需求)

核心思路:先批量生成所有new_id,再检查final_id的重复项,仅对重复的行重新生成,直到无重复。利用集合的O(1)查询特性替代列表的O(n)查询,大幅提升效率。

代码实现:

import string
import random
import pandas as pd

def generate_batch_ids(sizes, chars=string.ascii_uppercase + string.digits):
    # 批量生成对应长度的随机字符串
    return [''.join(random.SystemRandom().choice(chars) for _ in range(s)) for s in sizes]

# 初始生成
data['new_id'] = generate_batch_ids(data['missing'].tolist())
data['final_id'] = data['id'] + data['new_id']

# 处理重复项
while True:
    # 找出重复的final_id行
    duplicates = data[data.duplicated('final_id', keep=False)]
    if len(duplicates) == 0:
        break
    # 为重复行重新生成new_id
    duplicates['new_id'] = generate_batch_ids(duplicates['missing'].tolist())
    duplicates['final_id'] = duplicates['id'] + duplicates['new_id']
    # 更新原数据
    data.loc[duplicates.index] = duplicates

优势:保证生成的字符串完全随机,仅处理少量重复项(当missing长度足够时,重复概率极低),效率远高于逐行校验。

方法2:基于行号的唯一随机字符串(最高效,绝对唯一)

核心思路:利用DataFrame的行号(唯一标识)生成指定长度的36进制字符串(字母+数字),既满足missing的长度要求,又能保证final_id绝对唯一,无需任何重复校验。

代码实现:

import string

def row_id_to_str(row_num, length):
    # 36进制字符集,和原生成器一致
    chars = string.ascii_uppercase + string.digits
    base = len(chars)
    # 转换行号为36进制
    result = []
    while row_num > 0:
        row_num, rem = divmod(row_num, base)
        result.append(chars[rem])
    # 反转并补零至指定长度
    str_id = ''.join(reversed(result)).zfill(length)
    # 若长度超要求则截断末尾(300万行用5位36进制足够:36^5=60466176)
    return str_id[-length:] if len(str_id) > length else str_id

# 生成唯一的new_id
data['new_id'] = data.apply(lambda row: row_id_to_str(row.name, row['missing']), axis=1)
data['final_id'] = data['id'] + data['new_id']

优势:O(n)时间复杂度,无重复校验,绝对保证唯一性,适合超大规模数据。唯一缺点是字符串基于行号生成,并非完全随机,若允许这种“伪随机”,这是最优解。

方法3:分组预生成唯一随机字符串(适合分组场景)

核心思路:按missing的长度分组,为每个分组预先生成足够多的唯一随机字符串(数量大于该分组的行数),然后分配给对应行,避免重复。

代码实现:

import string
import random
import pandas as pd

def generate_unique_ids(count, size, chars=string.ascii_uppercase + string.digits):
    # 生成指定数量的唯一随机字符串
    unique_ids = set()
    while len(unique_ids) < count:
        unique_ids.add(''.join(random.SystemRandom().choice(chars) for _ in range(size)))
    return list(unique_ids)

# 按missing分组处理
for size, group in data.groupby('missing'):
    # 为该组生成足够的唯一字符串
    unique_ids = generate_unique_ids(len(group), size)
    # 分配给组内的行
    data.loc[group.index, 'new_id'] = unique_ids

data['final_id'] = data['id'] + data['new_id']

优势:每组内的字符串完全随机,且组内无重复;集合去重的效率高于逐行校验,适合missing取值较少的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:55:17