创建一列独特的随机生成的字母Pandas Dataframe ?

p4tfgftt  于 2023-01-07  发布在  其他
关注(0)|答案(1)|浏览(136)

我有一个 Dataframe ,其中有一列随机字母和数字,然后一列多少随机字母/数字需要添加到第一列的随机字符串。像这样,但我的 Dataframe 是3+百万行:

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

我使用下面的代码来生成新的随机序列:

def id_generator(size, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) 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'列中得到了两个重复的值。但是,我需要'final_id'列中的每个值都是唯一的。例如:

id     missing     new_id      final_id
XK39J       4       NJI4       XK39JNJI4 
NI94N       4       BNER       NI94NBNER
9IN3        5       ER41J      9IN3ER41J
MN83D       4       9D4S       MN83D9D4S
IUN2        5       MNST3      IUN2MNST3

我的想法是把所有的id存储在一个列表中,然后如果匹配的话得到一个新的随机生成的序列,但是考虑到将有300多万个id,这是行不通的,因为迭代3 m行将花费太长的时间。

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

我如何确保没有重复?

5uzkadbs

5uzkadbs1#

这仍然是一个蛮力,但你可以尝试这样的东西。

from uuid import uuid4

# First generate final_id for all without caring about duplicates
df['new_id'] = df.missing.transform(lambda x: str(uuid4()).upper().replace('-', '')[:x])
df['final_id'] = df.id + df.new_id

# final_ids that are unique and already good
id_good = df.final_id.unique().tolist()

# Try re-generating final_id until we get no more duplicates
while(len(df[df.final_id.duplicated()]) > 0):
    dupe_mask = df.final_id.duplicated()

    # Regenerate final_id, store in temp column
    df.loc[dupe_mask, 'new_id'] = df.loc[dupe_mask].missing.transform(lambda x: str(uuid4()).upper().replace('-', '')[:x])
    df.loc[dupe_mask, 'temp'] = df.loc[dupe_mask].id + df.loc[dupe_mask].new_id

    # If the new final_id is not duplicates with currently good final_ids, keep it.
    df.loc[dupe_mask & ~df.temp.isin(id_good), 'final_id'] = df.loc[dupe_mask & ~df.temp.isin(id_good), 'temp']
    
    id_good += df.loc[dupe_mask & ~df.temp.isin(id_good), 'final_id'].unique().tolist()
    
    df = df.drop('temp', axis=1)

当我用3M行测试时,它只需要执行1个循环,但是,您可能需要添加超时,因为理论上它可以永远运行。

相关问题