Here is my go. Note that it would be much easier if it were ok to replace Carid in both df and df2 with new i=unique ids. But staying with the question, here we go.
First we create a mapping cm between carname and carid for the first df
d = {'Carid': [1, 2, 3, 1], 'Carname': ['Mercedes-Benz', 'Audi', 'BMW', 'Mercedes-Benz'], 'model': ['S-Klasse AMG 63s', 'S6', 'X6 M-Power', 'Maybach']}
df = pd.DataFrame(data=d)
display(df.head())
cm = {name : id for name, id in zip(df['Carname'], df['Carid'])}
cm
Then we do the same for the second df
d2 = {'Carid': [4, 1, 5], 'Carname': ['VW', 'Citroen', 'Opel'], 'model': ['GTI', 'S', 'Corsa']}
df2 = pd.DataFrame(data=d2)
display(df2.head())
cm2= {name : id for name, id in zip(df2['Carname'], df2['Carid'])}
cm2
Then, the main act, combing the two mappings preserving original ids unless there is a clash in which case we assign unique ids.
unique_id = max(list(cm.values()) + list(cm2.values()))+1
for new_name in df2['Carname']:
if new_name in cm:
# already included
pass
elif cm2[new_name] not in cm.values():
# unique carid
cm[new_name] = cm2[new_name]
else:
# the new_name is not in cm but its id is
cm[new_name] = unique_id
unique_id += 1
print(cm)
now cm has unique id per carname, preserving the ones originally used unless they clashed:
{'Mercedes-Benz': 1, 'Audi': 2, 'BMW': 3, 'VW': 4, 'Citroen': 6, 'Opel': 5}
Now remap the ids
df['Carid'] = df['Carname'].replace(cm)
df2['Carid'] = df2['Carname'].replace(cm)
finally combine them together
dfs = []
dfs.append(df)
dfs.append(df2)
pd.concat(dfs)
the result is
| | Carid | Carname | model |
|---:|--------:|:--------------|:-----------------|
| 0 | 1 | Mercedes-Benz | S-Klasse AMG 63s |
| 1 | 2 | Audi | S6 |
| 2 | 3 | BMW | X6 M-Power |
| 3 | 1 | Mercedes-Benz | Maybach |
| 0 | 4 | VW | GTI |
| 1 | 6 | Citroen | S |
| 2 | 5 | Opel | Corsa |