Я не могу придумать хороший способ сделать это векторизованным способом, но это относительно легко сделать с помощью цикла.
Во-первых, вам нужно пары DIX-карт (Crime, ID) для идентификаторов, чтобы, например, вы могли присвоить строке 9 тот же идентификатор, что и строке 7.
Далее, вам нужны идентификаторы для точного сопоставления с самыми высокими на данный момент подидентификаторами, чтобы, например, вы могли присвоить строке 16 идентификатор, отличный от строк 12 и 14.
Как-то так (не проверено):
def remap(df):
pairmap = {}
subidmap = {}
for row in df.itertuples():
if (row.Crime, row.ID) not in pairmap:
if row.ID not in subidmap:
subidmap[row.ID] = 0
subid = str(row.ID)
else:
subidmap[row.ID] += 1
subid = f'{row.ID}.{subidmap[row.ID]}'
pairmap[row.Crime, row.ID] = subid
yield pairmap[row.Crime, row.ID]
df1.ID = list(remap(df1))