Я пытаюсь присвоить уникальные значения определенному распределению или группе. Хитрость заключается в том, что эти уникальные значения динамически начинаются и заканчиваются. Таким образом, группы будут содержать ранее увиденные значения и принимать новые уникальные значения в разные периоды времени. Что касается df
, уникальные значения расположены в Place
, а группы для выбора находятся в Available Group
для каждого периода времени Period
.
Вот общие принципы, которых я пытаюсь придерживаться:
1) Каждый Group
может содержать не более 3 уникальных Places
одновременно
2) Текущий уникальный Places
должен быть равномерно распределен по каждому Group
3) После того, как Places
назначен на Group
, удерживайте до завершения Group
. Если Group
не станет NA или неравномерное распределение собраний
Чтобы понять, сколько Places
происходит в настоящее время, я включил Total
, который основан на том, если Place
значение появляется снова. Я встречаю мои первые два руководства и частично третье. Когда Place
назначено для Group
, оно удерживается на том же Group
до тех пор, пока Place
не будет завершено (больше не появляется).
Однако я не ссылаюсь на Available Group
чтобы понять, если это Group
доступно. Когда Group
становится недоступным, я бы хотел переставить эти Places
по другому Available Group
. Используя df
ниже, назначение мест работает хорошо, уникальные места увеличиваются. Но как только они начинают финишировать, и группа 2 становится недоступной, эти места не перераспределяются в группу 1. На данный момент происходит только 3 места.
df = pd.DataFrame({
'Period' : [1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,5,5,5,5,5,5,6,6],
'Place' : ['CLUB','CLUB','CLUB','HOME','HOME','AWAY','AWAY','WORK','WORK','AWAY','AWAY','GOLF','GOLF','CLUB','CLUB','POOL','POOL','HOME','HOME','WORK','WORK','AWAY','AWAY','POOL','POOL','TENNIS','TENNIS'],
'Total' : [1,1,1,2,2,3,3,4,4,4,4,5,5,4,4,4,4,4,4,4,4,4,4,4,4,5,5],
'Available Group' : ['1','2','1','2','1','2','1','2','1','1','2','1','2','2','1','2','1','2','1','2','1','1','2','1','2','2','1'],
})
Попытка:
# df to store all unique places
uniquePlaces = pd.DataFrame(df["Place"].unique(), columns=["Place"])
# Start stores index of df where the place appears 1st
uniquePlaces["Start"] = -1
# End stores index of df where the place appears last
uniquePlaces["End"] = -1
def assign_place_label(group):
''' Create a label column that calculates the amount of unique meetings
throughout the racing schedule '''
label = uniquePlaces[uniquePlaces["Place"] == group.name].index[0]
group["Place Label"] = label
uniquePlaces.loc[label, "Start"] = group.index.min()
uniquePlaces.loc[label, "End"] = group.index.max()
return group
# Based on Start and End of each place, assign index to each place.
# when 'freed' the index is reused to new place appearing after that
def Assign_Meetings_group(up):
up["Index"] = 0
up["Freed"] = False
max_ind=0
free_indx = []
for i in range(len(up)):
ind_freed = up.index[(up["End"]<up.iloc[i]["Start"]) & (~up["Freed"])]
free = list(up.loc[ind_freed, "Index"])
free_indx += free
up.loc[ind_freed, "Freed"] = True
if len(free_indx)>0:
m = min(free_indx)
up.loc[i, "Index"] = m
free_indx.remove(m)
else:
up.loc[i, "Index"] = max_ind
max_ind+=1
up["Group"] = up["Index"]//3+1
return up
df2 = df.groupby("Place").apply(assign_place_label)
uniquePlaces = Assign_Meetings_group(uniquePlaces)
df3 = df2[df2['Period']!=0].drop_duplicates(subset = ['Period','Place'])
result = df3.merge(uniquePlaces[["Group"]], how="left", left_on="Place Label", right_index=True, sort=False)
Out:
Period Place Total Available Group Place Label Group
0 1 CLUB 1 1 0 1
1 2 CLUB 1 1 0 1
3 2 HOME 2 1 1 1
5 2 AWAY 3 1 2 1
7 3 WORK 4 1 3 2
9 3 AWAY 4 1 2 1
11 3 GOLF 5 1 4 2
13 3 HOME 5 1 1 1
15 4 CLUB 4 1 0 1
17 4 AWAY 3 1 2 1
19 4 POOL 3 1 5 1
21 5 WORK 3 1 3 2
23 5 POOL 2 1 5 1
25 6 GOLF 1 1 4 2
Предполагаемый выход:
Period Place Total Available Group Place Label Group
0 1 CLUB 1 1 0 1
1 2 CLUB 1 1 0 1
3 2 HOME 2 1 1 1
5 2 AWAY 3 1 2 1
7 3 WORK 4 1 3 2
9 3 AWAY 4 1 2 1
11 3 GOLF 5 1 4 2
13 3 HOME 5 1 1 1
15 4 CLUB 4 1 0 1
17 4 AWAY 3 1 2 1
19 4 POOL 3 1 5 1
21 5 WORK 3 1 3 1
23 5 POOL 2 1 5 1
25 6 GOLF 1 1 4 1