这里的主要方法是使用Series.map() https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.map.html在“ID”上分配新值。
用于用另一个值替换系列中的每个值,该值可以从函数、adict
or a Series https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html#pandas.Series.
这是exactly你在寻找什么。
以下是一些选项生成新的 ID:
1.随机生成8位整数,按要求
您可以首先创建一个随机生成的 8 位整数的映射,其中每个唯一的ID在数据框中。然后使用Series.map()
在“ID”上分配新值。我已经包括了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):
# all the generated id's were unique
break
# otherwise this will repeat until they are
df['ID'] = df['ID'].map(new_ids)
Output:
ID Sales
0 91154173 100
1 27127403 50
2 91154173 70
3 55892778 60
编辑 &Warning:原始 ID 是汉字,长度已经为 8。汉字肯定超过 10 个,因此如果原始 ID 的组合错误,可能无法为新集合制作足够唯一的 8 位数字 ID。除非您内存有限,否则我建议使用 16-24 位数字。或者甚至更好...
2. Use UUIDs https://docs.python.org/3/library/uuid.html。 [理想的]
您仍然可以使用 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
.)
Output:
ID Sales
0 10302456644733067873760508402841674050 100
1 99013251285361656191123600060539725783 50
2 10302456644733067873760508402841674050 70
3 112767087159616563475161054356643068804 60
2.B. UUID 中的数字较小
如果上面生成的 ID 太长,您可以将其截断,但存在一些小风险。在这里,我仅使用前 16 个十六进制字符并将它们转换为 int。你may将其放入唯一性循环检查中,如上面选项 1 所做的那样。
import uuid
original_ids = df['ID'].unique()
DIGITS = 16 # number of hex digits of the UUID to use
new_ids = {cid: int(uuid.uuid4().hex[:DIGITS], base=16) for cid in original_ids}
df['ID'] = df['ID'].map(new_ids)
Output:
ID Sales
0 14173925717660158959 100
1 10599965012234224109 50
2 14173925717660158959 70
3 13414338319624454663 60
3. 根据实际值创建映射:
这组选项具有以下优点:
- not needing a uniqueness check since it's deterministically based on the original ID and
- 不需要提前创建地图
3.A. CRC32
(与上面的选项 2.B. 相比,发现不同 ID 发生冲突的概率更高。)
import zlib
df['ID'] = df['ID'].map(lambda cid: zlib.crc32(bytes(cid, 'utf-8')))
Output:
ID Sales
0 2083453980 100
1 1445801542 50
2 2083453980 70
3 708870156 60
3.B. Python 的内置hash() https://docs.python.org/3/library/functions.html#hash原始 IS [在这种情况下我的首选方法]
- 可以一行完成,无需导入
- 相当安全,不会因不同的 ID 而产生冲突
df['ID'] = df['ID'].map(hash)
Output:
ID Sales
0 4663892623205934004 100
1 1324266143210735079 50
2 4663892623205934004 70
3 6251873913398988390 60
3.C. MD5Sum,或任何来自hashlib https://docs.python.org/3/library/hashlib.html
由于 ID 预计会很小(8 个字符),因此即使使用 MD5,冲突的概率为very low.
import hashlib
DIGITS = 16 # number of hex digits of the hash to use
df['ID'] = df['ID'].str.encode('utf-8').map(lambda x: int(hashlib.md5(x).hexdigest()[:DIGITS], base=16))
Output:
ID Sales
0 17469287633857111608 100
1 4297816388092454656 50
2 17469287633857111608 70
3 11434864915351595420 60