>

DF에서 그룹을 정의하려고합니다. 이러한 그룹은 범주 형 변수를 기반으로 가능한 한 유사해야합니다.

예를 들어, 나는 10 개의 구슬을 가지고 있으며 3 개의 그룹을 만들어야합니다. 내 구슬 중 4 개는 파란색, 2 개는 노란색, 4 개는 흰색입니다.

10 개의 구슬이 3 개의 그룹으로 균등하게 분할되지 않으므로 그룹 크기는 4,3,3이 될 수 있습니다.

마찬가지로, 우리는 단지 2 노랑 만 있기 때문에 그룹들 사이에서도 색상이 표현되지 않을 것입니다. 그러나 이러한 노란색 구슬은 그룹 전체에 가능한 한 고르게 분포되어야합니다. 이는 데이터 세트의 모든 범주 형 변수에서 계속됩니다.

원래의 계획은 해당 행의 다른 그룹에 존재하는지 확인하고 그룹에있는 경우 다른 그룹을 시도하는 것입니다. 공동 작업자는 그룹을 생성하고 하나의 핫 인코딩으로 점수를 매긴 다음 하나의 핫 인코딩의 합계가 비슷한 수준에 도달 할 때까지 행을 교환하는 더 좋은 방법을 지적했습니다 (행에 각 범주 변수의 "대표적"변이가 있음을 나타냅니다) 그의 해결책은 게시 된 답변입니다.

import pandas as pd
import numpy as np
test = pd.DataFrame({'A' : ['alice', 'bob', 'george', 'michael', 'john', 'peter', 'paul', 'mary'], 
                 'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
                 'C' : ['dog', 'cat', 'dog', 'cat', 'dog', 'cat', 'dog', 'cat'],
                 'D' : ['boy', 'girl', 'boy', 'girl', 'boy', 'girl', 'boy', 'girl']})
gr1, gr2, gr3 = [], [], []
gr1_names = []
def test_check1(x):
    #this is where I'm clearly not approaching this problem correctly
    for index, row in x.iterrows():
        if row['A'] not in gr1 and row['B'] not in gr1 and row['C'] not in gr1 and row['D'] not in gr1:
                 gr1.extend(row) # keep a record of what names are in what groups
                 gr1_names.append(row['A']) #save the name

그러나 여기에 오기만하면 "행이 모든 그룹에 허용되지 않으면 첫 번째 그룹에 행을 던져야합니다. 다음에 행이 모든 그룹에 허용되지 않은 경우" 두 번째로 던지기 "등.

샘플 코드가 해당 상황을 적절하게 처리하지 못한다는 것을 알 수 있습니다.

난수를 생성 한 다음 빈을 만들었고 솔직히 이것은 매우 가까웠지만, 난수가 아닌 답변을 찾기를 바랐습니다.

오늘 제가이 작업을하면서 도움이되었다고 생각되는 링크는 다음과 같습니다. 모두 얻는 방법 목록 요소의 가능한 조합?

파이썬 목록에서 고유 한 요소 조합 얻기

참가자가 원래 참가자가되도록 그룹에 무작위로 재 할당 같은 그룹에서 같은 그룹으로 끝나지 않습니다 --- 이것은 매우 가깝게 느껴지지만 필요한 것으로 조작하는 방법을 알 수 없습니다 .---

요소 사양에서 목록을 생성하는 방법 조합

예상되는 출력은 모든 형태의 데이터 프레임이지만 해당 데이터 프레임의 피벗은 다음을 나타냅니다.

group id    foo bar faz
       1    3   2   5
       2    3   2   5
       3    3   1   5
       4    4   1   5

  • 답변 # 1

    동료가 해결책을 찾았으며 문제를 더 잘 설명 할 수있는 해결책이 있습니다.

    import pandas as pd
    import random
    import math
    import itertools
    def n_per_group(n, n_groups):
        """find the size of each group when splitting n people into n_groups"""
        n_per_group = math.floor(n/n_groups)
        rem = n % n_per_group
        return [n_per_group if k<rem else n_per_group + 1 for k in range(n_groups)]
    def assign_groups(n, n_groups):
        """split the n people in n_groups pretty evenly, and randomize"""
        n_per = n_per_group(n ,n_groups)
        groups = list(itertools.chain(*[i[0]*[i[1]] for i in zip(n_per,list(range(n_groups)))]))
        random.shuffle(groups)
        return groups
    def group_diff(df, g1, g2):
        """calculate the between group score difference"""
        a = df.loc[df['group']==g1, ~df.columns.isin(('A','group'))].sum()
        b = df.loc[df['group']==g2, ~df.columns.isin(('A','group'))].sum()
        #print(a)
        return abs(a-b).sum()
    def swap_groups(df, row1, row2):
        """swap the groups of the people in row1 and row2"""
        r1group = df.loc[row1,'group']
        r2group = df.loc[row2,'group']
        df.loc[row2,'group'] = r1group
        df.loc[row1,'group'] = r2group
        return df
    def row_to_group(df, row):
        """get the group associated to a given row"""
        return df.loc[row,'group']
    def swap_and_score(df, row1, row2):
        """
        given two rows, calculate the between group scores
        originally, and if we swap rows. If the score difference
        is minimized by swapping, return the swapped df, otherwise
        return the orignal (swap back)
        """
        #orig = df
        g1 = row_to_group(df,row1)
        g2 = row_to_group(df,row2)
        s1 = group_diff(df,g1,g2)
        df = swap_groups(df, row1, row2)
        s2 = group_diff(df,g1,g2)
        #print(s1,s2)
        if s1>s2:
            #print('swap')
            return df
        else:
            return swap_groups(df, row1, row2)
    def pairwise_scores(df):
        d = []
        for i in range(n_groups):
            for j in range(i+1,n_groups):
                d.append(group_diff(df,i,j))
        return d
    # one hot encode and copy
    df_dum = pd.get_dummies(df, columns=['B', 'C', 'D']).copy(deep=True)
    #drop extra cols as needed
    groups = assign_groups(n, n_groups)
    df_dum['group'] = groups
    # iterate
    for _ in range(5000):
        rows = random.choices(list(range(n)),k=2)
        #print(rows)
        df_dum = swap_and_score(df_dum,rows[0],rows[1])
        #print(pairwise_scores(df))
    print(pairwise_scores(df_dum))
    df['group'] = df_dum.group
    df['orig_groups'] = groups
    for i in range(n_groups):
            for j in range(i+1,n_groups):
                a = df_dum.loc[df_dum['group']==3, ~df_dum.columns.isin(('A','group'))].sum()
                b = df_dum.loc[df_dum['group']==0, ~df_dum.columns.isin(('A','group'))].sum()
                print(a-b)
    
    

    필요한 사항을 더 잘 설명하기 위해 질문 자체를 바꾸겠습니다. 특히 처음 목표를 잘 설명하지 못했다고 생각하기 때문입니다.

  • 이전 Dijkstra의 알고리즘을 이해하려고
  • 다음 Acumatica GetLocalizedLabel 메소드가 때때로 키를 찾지 못했습니다