主要方法是使用
Series.map()
在“ID”上分配新值。
用于将系列中的每个值替换为另一个值,该值可以来自函数、dict
或Series
。
这正是您要寻找的。
以下是生成新ID的一些选项:
1. 以所需方式生成随机生成的8位整数
您可以首先创建一个包含数据框中每个
唯一ID的随机生成的8位整数映射。然后在“ID”上使用
Series.map()
分配新值回去。我已经包括了一个
while
循环,以确保生成的ID是唯一的。
import random
original_ids = df['ID'].unique()
while True:
new_ids = {id_: random.randint(10_000_000, 99_999_999) for id_ in original_ids}
if len(set(new_ids.values())) == len(original_ids):
break
df['ID'] = df['ID'].map(new_ids)
输出:
ID Sales
0 91154173 100
1 27127403 50
2 91154173 70
3 55892778 60
编辑和警告:原始ID是中文字符,长度已经为8。肯定有超过10个中文字符,因此如果使用错误的原始ID组合,则可能无法为新集合创建足够唯一的8位ID。除非受到内存限制,否则建议使用16-24位数字。或者更好的选择是...
2. 使用UUIDs。[理想情况]
您仍然可以使用ID的“整数”版本而不是十六进制版本。这样做的额外好处是不需要检查唯一性:
import uuid
original_ids = df['ID'].unique()
new_ids = {cid: uuid.uuid4().int for cid in original_ids}
df['ID'] = df['ID'].map(new_ids)
(如果您接受十六进制 ID,请将上面的 uuid.uuid4().int
更改为 uuid.uuid4().hex
。)
输出:
ID Sales
0 10302456644733067873760508402841674050 100
1 99013251285361656191123600060539725783 50
2 10302456644733067873760508402841674050 70
3 112767087159616563475161054356643068804 60
2.B. 从UUID中获取较小的数字
如果上面生成的ID太长,您可以截断它,但存在一些风险。在此,我仅使用前16个十六进制字符并将其转换为int。您可能将其放入与选项1相同的唯一性循环检查中。
import uuid
original_ids = df['ID'].unique()
DIGITS = 16
new_ids = {cid: int(uuid.uuid4().hex[:DIGITS], base=16) for cid in original_ids}
df['ID'] = df['ID'].map(new_ids)
输出:
ID Sales
0 14173925717660158959 100
1 10599965012234224109 50
2 14173925717660158959 70
3 13414338319624454663 60
3. 基于实际值创建映射:
这组选项具有以下优点:
- 不需要唯一性检查,因为它是基于原始ID确定性生成的,
- 不需要提前创建映射表
3.A. CRC32
(与上述2.B选项相比,更容易发现不同ID之间的冲突。)
import zlib
df['ID'] = df['ID'].map(lambda cid: zlib.crc32(bytes(cid, 'utf-8')))
输出:
ID Sales
0 2083453980 100
1 1445801542 50
2 2083453980 70
3 708870156 60
3.B. 使用Python内置的hash()
函数对原始ID进行哈希[我首选的方法]
- 可以在一行代码中完成,无需导入任何模块
- 对于不同的ID生成不会发生冲突,具有合理的安全性
df['ID'] = df['ID'].map(hash)
输出:
ID Sales
0 4663892623205934004 100
1 1324266143210735079 50
2 4663892623205934004 70
3 6251873913398988390 60
3.C. MD5Sum或hashlib
中的任何内容
由于ID预计很小(8个字符),即使使用MD5,碰撞的概率也非常低。
import hashlib
DIGITS = 16
df['ID'] = df['ID'].str.encode('utf-8').map(lambda x: int(hashlib.md5(x).hexdigest()[:DIGITS], base=16))
输出:
ID Sales
0 17469287633857111608 100
1 4297816388092454656 50
2 17469287633857111608 70
3 11434864915351595420 60
randint()
生成两个相同的ID的情况可能很少发生。 - Arty