Обнаружьте возможные комбинации в триадах перестановки с определенными критериями - PullRequest
0 голосов
/ 25 ноября 2018

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

  • Каждый заголовок столбца обозначает Период / урок дня
  • Каждый день имеет 7 периодов / уроков, поэтому понедельникпо пятницам = 35 столбцов
  • каждая ячейка содержит дескриптор класса (первые 3 символа), интелитуры учителя (3 символа после знака «$») и название комнаты (3 символа после"(").

Я хочу объединить учителей в группы по 3 (триады), где выполняются следующие критерии:

  • В любой данный период / урок2 недели учителя «свободны», не преподают, а 1 учитель преподает.
  • В той же самой триаде в другой период есть другой учитель, который «несвободен» и обучает, где два других учителяпреподают
  • , кроме того, в любой другой период другая комбинация из двух учителей, являющихся «бесплатными» неучащими, и неиспользованный учитель учат.

См. нижеa для дальнейшего разъяснения:

Инициалы A и B находятся в наборе, но отсутствуют в C, присутствуют в наборе, а также C и A в наборе, но не присутствуют в наборе, а также B и C в наборе, но не присутствуют в Aнабор Все 3 критерия должны быть верны, чтобы найти окончательную триаду

, поэтому из тысяч перестановок должно быть не так много комбинаций, которые соответствуют этим критериям

Проще говоря, что яПопытка найти - это поместить учителей в группы по 3 человека. Где 2 учителя могут пойти и понаблюдать за уроком другого учителя, то есть в любой период 2 учителя свободны, а один преподает.В каждой колонке вы увидите всех учителей, которые преподают в любой конкретный период и день.Поэтому тот, кто не находится в этой колонке, которую мы можем вывести, не учит.Мы хотим, чтобы группа из трех учителей оставалась триадой, чтобы каждого из нас можно было наблюдать.Таким образом, в любой другой период недели другой учитель преподает из той же триады, а два других НЕ преподают.

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

import pandas as pd
import numpy as np
import itertools

class unique_element:
    def __init__(self,value,occurrences):
        self.value = value
        self.occurrences = occurrences


def perm_unique(elements):
    eset=set(elements)
    listunique = [unique_element(i,elements.count(i)) for i in eset]
    u=len(elements)
    return perm_unique_helper(listunique,[0]*u,u-1)


def perm_unique_helper(listunique,result_list,d):
    if d < 0:
        yield tuple(result_list)
    else:
        for i in listunique:
            if i.occurrences > 0:
                result_list[d]=i.value
                i.occurrences-=1
                for g in  perm_unique_helper(listunique,result_list,d-1):
                    yield g
                i.occurrences+=1


def findsubsets(S, m):
    return set(itertools.combinations(S, m))


csv_file = pd.read_csv('Whole_School_TT.csv')
df = csv_file.dropna(how='all')
df = csv_file.fillna(0)
cols = df.columns
df_class_name = df.copy()
df_names = df.copy()
df_room_number = df.copy()

for col in range(0, len(df.columns)):
    for row in range(0, len(df)):
        if df[cols[col]].iloc[row] is not 0:
            text = df[cols[col]].iloc[row]
            index_dollar = df[cols[col]].iloc[row].find('$')
            r_index_dollar = df[cols[col]].iloc[row].rfind('$')
            if index_dollar is not -1:
                if index_dollar == r_index_dollar:
                    df_names[cols[col]].iloc[row] = df[cols[col]].iloc[row][index_dollar+1:index_dollar+4]
                else:
                    name1 = df[cols[col]].iloc[row][index_dollar + 1:index_dollar + 4]
                    name2 = df[cols[col]].iloc[row][r_index_dollar + 1:r_index_dollar + 4]
                    df_names[cols[col]].iloc[row] = name1 + ' ' + name2
                index_hash = df[cols[col]].iloc[row].find('#')
                df_class_name[cols[col]].iloc[row] = df[cols[col]].iloc[row][:(index_dollar - 1)]
                df_room_number[cols[col]].iloc[row] = df[cols[col]].iloc[row][index_hash + 1:-1]
            else:
                df_names[cols[col]].iloc[row] = 0
                index_hash = df[cols[col]].iloc[row].find('#')
                if index_hash is -1:
                    df_class_name[cols[col]].iloc[row] = df[cols[col]].iloc[row][:3]
                    df_room_number[cols[col]].iloc[row] = 0
                else:
                    df_class_name[cols[col]].iloc[row] = df[cols[col]].iloc[row][:(index_hash - 2 )]
                    df_room_number[cols[col]].iloc[row] = df[cols[col]].iloc[row][index_hash + 1:-1]

teacher_names = []
for col in range(0, len(cols)):
    period_names = (df_names[cols[col]].unique())
    teacher_names.extend(period_names)

df_all_names = pd.DataFrame(teacher_names, columns=['Names'])
df_all_names = pd.DataFrame(df_all_names['Names'].unique())
df_all_names = df_all_names[(df_all_names.T != 0).any()]
mask = (df_all_names[0].str.len() == 3)
df_single_names = df_all_names.loc[mask] # so now here we have all the teacher names in general who teach
# we will find the teacher who teach per period and teachers who do not teach
set_of_names = set(np.array(df_single_names[0]))  # here i have all the unique teacher names

period_set_names = [0]*len(cols)
period_set_names_NO_teach = [0]*len(cols)

# here i get the names for each one of the periods
# and find the intersection with the unique teacher names in order to figure out who teaches per period
for col in range(0, len(cols)):
    period_set_names[col] = set(np.array(df_names[cols[col]]))  # get teacher names for current period
    period_set_names_NO_teach[col] = set_of_names.difference(period_set_names[col])
    period_set_names[col] = set_of_names.intersection(period_set_names[col])
    # sanity check
    print('Teachers who teach and teacher who dont teach should be equivalent to the full list of names: ', end='')
    print(period_set_names_NO_teach[col].union(period_set_names[col]) == set_of_names)

def get_current_period_triplets(col):
    free_period_pairs = findsubsets(period_set_names_NO_teach[col], 2)  # I got all the period Free teacher pairs
    # teaching_period_pairs = findsubsets(period_set_names[col], 2)
    free_period_pairs_list = list(free_period_pairs)
    period_triplets = []
    for i in range(0, len(free_period_pairs_list)):
        listof = list(free_period_pairs_list)
        current_free_pair = list(listof[i])
        # print(current_free_pair)
        for j in (period_set_names[col]):
            temp = current_free_pair.copy()
            current_triplet = temp.append(j)
            period_triplets.append(tuple(temp))
    period_triplets = set(period_triplets)

    return period_triplets


for col in range(0, len(cols)):
    current_triplets = get_current_period_triplets(col)
    print(current_triplets)
...