Попытка создать алгоритм соответствия для врачей и больниц в Python, застрял на условиях - PullRequest
0 голосов
/ 24 января 2019

Прежде всего, я хотел бы отметить, что я довольно новичок в питоне, поэтому, если моя формулировка или вопрос сам по себе кажутся глупыми, пожалуйста, потерпите меня, просто пытаясь научиться.

Я создал два словаря: один из врачей, который присваивает рейтинг больницам, и один из больниц, который присваивает рейтинг врачам. Врачи в больницы:

{'Doctor_5': {1.0: 'Hospital_7', 2.0: 'Hospital_6', 3.0: 'Hospital_8', 4.0: 'Hospital_5', 5.0: 'Hospital_9', 6.0: 'Hospital_4', 7.0: 'Hospital_10', 8.0: 'Hospital_3', 9.0: 'Hospital_2', 10.0: 'Hospital_1'}, 'Doctor_9': {1.0: 'Hospital_9', 2.0: 'Hospital_8', 3.0: 'Hospital_10', 4.0: 'Hospital_7', 5.0: 'Hospital_6', 6.0: 'Hospital_5', 7.0: 'Hospital_4', 8.0: 'Hospital_3', 9.0: 'Hospital_2', 10.0: 'Hospital_1'}, 'Doctor_8': {1.0: 'Hospital_8', 2.0: 'Hospital_9', 3.0: 'Hospital_10', 4.0: 'Hospital_7', 5.0: 'Hospital_6', 6.0: 'Hospital_5', 7.0: 'Hospital_4', 8.0: 'Hospital_3', 9.0: 'Hospital_2', 10.0: 'Hospital_1'}, 'Doctor_1': {1.0: 'Hospital_1', 2.0: 'Hospital_2', 3.0: 'Hospital_3', 4.0: 'Hospital_4', 5.0: 'Hospital_5', 6.0: 'Hospital_6', 7.0: 'Hospital_7', 8.0: 'Hospital_8', 9.0: 'Hospital_9', 10.0: 'Hospital_10'}, 'Doctor_4': {1.0: 'Hospital_5', 2.0: 'Hospital_6', 3.0: 'Hospital_4', 4.0: 'Hospital_7', 5.0: 'Hospital_3', 6.0: 'Hospital_2', 7.0: 'Hospital_1', 8.0: 'Hospital_8', 9.0: 'Hospital_9', 10.0: 'Hospital_10'}, 'Doctor_3': {1.0: 'Hospital_4', 2.0: 'Hospital_3', 3.0: 'Hospital_2', 4.0: 'Hospital_1', 5.0: 'Hospital_5', 6.0: 'Hospital_6', 7.0: 'Hospital_7', 8.0: 'Hospital_8', 9.0: 'Hospital_9', 10.0: 'Hospital_10'}, 'Doctor_6': {1.0: 'Hospital_7', 2.0: 'Hospital_8', 3.0: 'Hospital_6', 4.0: 'Hospital_9', 5.0: 'Hospital_5', 6.0: 'Hospital_10', 7.0: 'Hospital_4', 8.0: 'Hospital_3', 9.0: 'Hospital_2', 10.0: 'Hospital_1'}, 'Doctor_7': {1.0: 'Hospital_8', 2.0: 'Hospital_7', 3.0: 'Hospital_9', 4.0: 'Hospital_6', 5.0: 'Hospital_5', 6.0: 'Hospital_4', 7.0: 'Hospital_3', 8.0: 'Hospital_2', 9.0: 'Hospital_1'}, 'Doctor_10': {1.0: 'Hospital_10', 2.0: 'Hospital_9', 3.0: 'Hospital_8', 4.0: 'Hospital_7', 5.0: 'Hospital_6', 6.0: 'Hospital_5', 7.0: 'Hospital_4', 8.0: 'Hospital_3', 9.0: 'Hospital_2', 10.0: 'Hospital_1'}, 'Doctor_2': {1.0: 'Hospital_3', 2.0: 'Hospital_2', 3.0: 'Hospital_4', 4.0: 'Hospital_1', 5.0: 'Hospital_5', 6.0: 'Hospital_6', 7.0: 'Hospital_7', 8.0: 'Hospital_8', 9.0: 'Hospital_9', 10.0: 'Hospital_10'}}

Больницы для врачей:

{'Hospital_2': {1.0: 'Doctor_1', 2.0: 'Doctor_2', 3.0: 'Doctor_3', 4.0: 'Doctor_4', 5.0: 'Doctor_5', 6.0: 'Doctor_6', 7.0: 'Doctor_7', 8.0: 'Doctor_8', 9.0: 'Doctor_9', 10.0: 'Doctor_10'}, 'Hospital_1': {1.0: 'Doctor_1', 2.0: 'Doctor_2', 3.0: 'Doctor_3', 4.0: 'Doctor_4', 5.0: 'Doctor_5', 6.0: 'Doctor_6', 7.0: 'Doctor_7', 8.0: 'Doctor_8', 9.0: 'Doctor_9', 10.0: 'Doctor_10'}, 'Hospital_8': {1.0: 'Doctor_8', 2.0: 'Doctor_9', 3.0: 'Doctor_7', 4.0: 'Doctor_6', 5.0: 'Doctor_10', 6.0: 'Doctor_4', 7.0: 'Doctor_3', 8.0: 'Doctor_2', 9.0: 'Doctor_1'}, 'Hospital_7': {1.0: 'Doctor_5', 2.0: 'Doctor_6', 3.0: 'Doctor_7', 4.0: 'Doctor_8', 5.0: 'Doctor_3', 6.0: 'Doctor_2', 7.0: 'Doctor_9', 8.0: 'Doctor_1', 9.0: 'Doctor_10'}, 'Hospital_10': {1.0: 'Doctor_10', 2.0: 'Doctor_9', 3.0: 'Doctor_8', 4.0: 'Doctor_7', 5.0: 'Doctor_6', 6.0: 'Doctor_5', 7.0: 'Doctor_4', 8.0: 'Doctor_3', 9.0: 'Doctor_2', 10.0: 'Doctor_1'}, 'Hospital_3': {1.0: 'Doctor_1', 2.0: 'Doctor_2', 3.0: 'Doctor_3', 4.0: 'Doctor_4', 5.0: 'Doctor_5', 6.0: 'Doctor_6', 7.0: 'Doctor_7', 8.0: 'Doctor_8', 9.0: 'Doctor_9', 10.0: 'Doctor_10'}, 'Hospital_9': {1.0: 'Doctor_9', 2.0: 'Doctor_10', 3.0: 'Doctor_8', 4.0: 'Doctor_7', 5.0: 'Doctor_6', 6.0: 'Doctor_5', 7.0: 'Doctor_4', 8.0: 'Doctor_3', 9.0: 'Doctor_2', 10.0: 'Doctor_1'}, 'Hospital_5': {1.0: 'Doctor_4', 2.0: 'Doctor_3', 3.0: 'Doctor_2', 4.0: 'Doctor_1', 5.0: 'Doctor_5', 6.0: 'Doctor_6', 7.0: 'Doctor_7', 8.0: 'Doctor_8', 9.0: 'Doctor_9', 10.0: 'Doctor_10'}, 'Hospital_4': {1.0: 'Doctor_3', 2.0: 'Doctor_2', 3.0: 'Doctor_4', 4.0: 'Doctor_1', 5.0: 'Doctor_5', 6.0: 'Doctor_6', 7.0: 'Doctor_7', 8.0: 'Doctor_8', 9.0: 'Doctor_9', 10.0: 'Doctor_10'}, 'Hospital_6': {1.0: 'Doctor_4', 2.0: 'Doctor_5', 3.0: 'Doctor_6', 4.0: 'Doctor_3', 5.0: 'Doctor_2', 6.0: 'Doctor_1', 7.0: 'Doctor_8', 8.0: 'Doctor_9', 9.0: 'Doctor_10'}}

Я также создал список врачей, так как он используется для создания индекса моего DataFrame, полученного из алгоритма:

['Doctor_5', 'Doctor_9', 'Doctor_8', 'Doctor_1', 'Doctor_4', 'Doctor_3', 'Doctor_6', 'Doctor_7', 'Doctor_10', 'Doctor_2']

Сейчас я пытаюсь создать алгоритм, который назначает врачей в больницы на основе алгоритма Гейла-Шепли (знание специфики не требуется).

Это то, что я до сих пор придумал, в конце я представляю это в DataFrame, потому что нахожу это более понятным для интерпретации:

Matches = {}
Matches['Doctors'] = (doctors)
First_round = []
for Doctor_ in ranking_by_doctors:
    First_round.append(ranking_by_doctors[Doctor_].get(1.0))
Matches['First round'] = (First_round)
Matches
Matches_round_1 = pd.DataFrame.from_dict(Matches)
Matches_round_1.set_index('Doctors', inplace=True)
Matches_round_1   

Это мой результат: enter image description here

Как видите, я назначаю этому врачу наиболее предпочтительную больницу каждого врача. Но мне нужна помощь с условиями моей функции. На данный момент в моем результате есть дубликаты: и doctor_7, и doctor_8 сопоставлены с hospital_8, аналогично hospital_7 сопоставлен с двумя разными врачами. Тем не менее, я хочу добавить в свою функцию условие, которое в таких случаях проверяет, какой врач больше всего предпочитает больницу, подбирает ли он этого врача, а другой врач не имеет себе равных. После этого я хочу снова начать весь процесс для непревзойденных врачей, что приведет к новым результатам во втором раунде. Для этого второго раунда вполне возможно, что уже подобранные больницы сломают их матч, потому что к ним подходит врач, которого они предпочитают по сравнению с их первым матчем.

Однако, посмотрев несколько часов на настройку моей функции и изучив справочные руководства по гуглу и составив список, мне все еще не удалось найти решение. Вот почему я обращаюсь к stackoverflow за помощью, возможно, один из вас уже сталкивался с этой проблемой и может помочь мне решить ее. Если вам нужно больше информации, чем указано выше, дайте мне знать!

Заранее большое спасибо,

1 Ответ

0 голосов
/ 24 января 2019

Я изменил First_round на словарь, чтобы сделать его немного более понятным. Я бы также предложил некоторые другие структурные изменения, но об этом позже. Решение состоит в том, чтобы просто сделать «пу» в проверке «если», чтобы увидеть, назначена ли конкретная больница, а затем обменять врача, если он имеет лучший результат:

def hospital_ranking_of_doctor(hospital, doctor):
    return next(v for k, v in ranking_by_hospital[hospital].items() if v == doctor)

Matches = {}
Matches['Doctors'] = (doctors)
First_round = {}

# We loop through all the doctors one by one
for Doctor_ in ranking_by_doctors:

    # Then we find which hospital the doctor prefers
    favored_hospital = ranking_by_doctors[Doctor_].get(1.0)

    # We test if that hospital has already had a doctor assigned
    if favored_hospital not in First_round:
        # If it has not, then we just assign the current doctor
        First_round[favored_hospital] = Doctor_
    else:
        # If the hosptial was already assigned a doctor we compare 
        # that doctor with the new one and set the new one only if 
        # the hospital prefers him.
        previously_assigned_doctor = First_round[favored_hospital]
        if hospital_ranking_of_doctor(favored_hospital, previously_assigned_doctor) > hospital_ranking_of_doctor(favored_hospital, Doctor_):
            First_round[favored_hospital] = Doctor_

print(First_round)

Теперь, что касается структурных изменений, я думаю, вам также следует либо изменить структуру ранжирования, превратившись из словаря, варьирующего числа в больницы / врачи, либо в просто упорядоченный список предпочтений, либо перевернуть его, чтобы ключом была больница / врач. и приоритет / оценка является значением. Это сделало бы проверку оценки доктора более естественной как:

ranking_by_hospital['Hospital_2']['Doctor_2'] > ranking_by_hospital['Hospital_2']['Doctor_3']

Таким образом, вы можете обновить функцию ранжирования:

def hospital_ranking_of_doctor(hospital, doctor):
    return ranking_by_hospital[hospital][doctor]

Или просто вставьте эти биты кода.

...