Лучший источник - официальный источник:
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.join.html
Возможно, вы также захотите узнать о мультииндексах, уровнях и т. Д.
Я предпочитаю присоединиться:
import pandas as pd
columns = ['PatientID', 'Model#', 'Ear', 'SerNum', 'FName', 'LName', 'PName', 'PPhone']
data = [[
'P99999', '300', 'Left', '1234567', 'John', 'Doe', 'Jane Doe', '(999) 111-2222'],
['P99999', '400', 'Right', '2345678', 'John', 'Doe', 'Jane Doe', '(999) 111-2222']]
df = pd.DataFrame(data=data, columns=columns)
df = df.set_index('PatientID')
df = df[df['Ear'] == 'Left'].drop('Ear', axis=1).join(df[df['Ear'] == 'Right'].drop('Ear', axis=1), lsuffix='_left', rsuffix='_right').reset_index()
Вывод:
PatientID Model#_left SerNum_left ... LName_right PName_right PPhone_right
0 P99999 300 1234567 ... Doe Jane Doe (999) 111-2222
РЕДАКТИРОВАТЬ :
1. Исправлено, забыл сбросить столбец:)
2. Теперь с вашими данными:)