为Pandas中的每组生成唯一随机数的范围

2024-06-16 11:58:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我必须为每个组创建一个介于0到99999之间的唯一随机数范围。 我有以下数据集

District    Prefix  Quota       
A           98426   783
A           98427   223
A           98446   127
A           98626   51
B           98049   167
B           98079   153
B           98140   120
B           98159   139
B           98169   182
B           98249   86
B           98426   588
B           98446   96
C           98049   104
C           98060   68
C           98149   65
C           98150   68
C           98159   86
C           98160   80
C           98169   113

要复制的代码:

import pandas as pd
df = pd.DataFrame([
    ['A', 98426, 783],
    ['A', 98427, 223],
    ['A', 98446, 127],
    ['A', 98626, 51],
    ['B', 98049, 167],
    ['B', 98079, 153],
    ['B', 98140, 120],
    ['B', 98159, 139],
    ['B', 98169, 182],
    ['B', 98249, 86],
    ['B', 98426, 588],
    ['B', 98446, 96],
    ['C', 98049, 104],
    ['C', 98060, 68],
    ['C', 98149, 65],
    ['C', 98150, 68],
    ['C', 98159, 86],
    ['C', 98160, 80],
    ['C', 98169, 113]
], 
    columns=['District', 'Prefix', 'Quota'])

因此,我必须生成从0到99999的“配额”唯一编号,并将其添加到前缀中,以便创建一个10位数的编号

我试过:

numbers = np.random.choice(range(99999), size=df.Quota.sum(), replace=False)
random = df.Prefix.repeat(df.Quota)*100000 + numbers

但问题是,它对“配额”进行小计,并生成从0到99999的唯一数字。但我希望每个前缀都有唯一的0到99999号。例如假设np.random.choice(范围(99999),size=df.Quota.sum(),replace=False)生成16195并添加到第一个前缀“98426”。相同的号码不会生成,也不会提供给其他前缀。因此,每个前缀的范围(0-99999)应该是唯一的


Tags: falsedfsizeprefixnprandomreplace编号
2条回答

这里有一个使用transformrandom.choiceexplode的解决方案

def make_random_numbers(x):
    total = x.sum()
    r = np.random.choice(range(99999), total, replace = False)
    chunks = x.cumsum()[:-1]
    res =  np.hsplit(r, chunks)  
    return res

df["rand_items"] = df.groupby("Prefix")["Quota"].transform(make_random_numbers)
df.explode("rand_items")

结果是:

  District  Prefix  Quota rand_items
0        A   98426    783       2681
0        A   98426    783      94952
0        A   98426    783      79496
0        A   98426    783      58361
0        A   98426    783      54883
0        A   98426    783      44819
0        A   98426    783      36209
0        A   98426    783      91710
...
18        C   98169    113      41859
18        C   98169    113      92311
18        C   98169    113      18572
18        C   98169    113      72492
18        C   98169    113      39188
18        C   98169    113      36808
18        C   98169    113      32055
18        C   98169    113      74678

此方法返回每行的随机选择列表:

def gen_rand(x):
    return (x['Prefix'].min() * 1E5 + np.random.choice(range(99999),
        size=sum(x['Quota']), replace = False)).astype(int)
df.groupby('Prefix').apply(gen_rand)

相关问题 更多 >