1

我基本上是在尝试进行这种蒙特卡罗类型的分析,在这种分析中,我将实验中的参与者随机重新分配到新组,然后在给定随机新组的情况下重新分析数据。所以这就是我想要做的:

参与者最初被分成八组,每组四名参与者。我想将每个参与者随机重新分配到一个新组,但我不希望任何参与者最终与来自同一原始组的另一个参与者进入一个新组

这是我在这方面的进展:

import random
import pandas as pd
import itertools as it

data = list(it.product(range(8),range(4)))
test_df = pd.DataFrame(data=data,columns=['group','partid'])
test_df['new_group'] = None

for idx, row in test_df.iterrows():
    start_group = row['group']
    takens      = test_df.query('group == @start_group')['new_group'].values
    fulls       = test_df.groupby('new_group').count().query('partid >= 4').index.values
    possibles   = [x for x in test_df['group'].unique() if (x not in takens)
                                                      and (x not in fulls)]
    test_df.loc[idx,'new_group'] = random.choice(possibles)

这里的基本思想是我随机将参与者重新分配到一个新组,其约束条件是(a)新组没有他们原来的组合作伙伴之一,(b)新组没有 4 或更多的参与者已经重新分配给它。

这种方法的问题是,很多时候,当我们尝试重新分配最后一个组时,唯一剩余的组槽位在同一个组中。我可以尝试在失败时重新随机化直到成功,但这感觉很愚蠢。另外,我想进行 100 次随机重新分配,所以这种方法可能会变得非常慢......

所以必须有一个更聪明的方法来做到这一点。我也觉得应该有一个更简单的方法来解决这个问题,考虑到目标的简单性(但我意识到这可能会产生误导......)

4

1 回答 1

1

编辑:更好的解决方案


睡在上面之后,我发现了一个明显更好的解决方案~ Big O of numGroups

样本数据

import random
import numpy as np
import pandas as pd
import itertools as it

np.random.seed(0)
numGroups=4
numMembers=4

data = list(it.product(range(numGroups),range(numMembers)))
df = pd.DataFrame(data=data,columns=['group','partid'])

解决方案

g = np.repeat(range(numGroups),numMembers).reshape((numGroups,numMembers))
In [95]: g
Out[95]: 
array([[0, 0, 0, 0],
       [1, 1, 1, 1],
       [2, 2, 2, 2],
       [3, 3, 3, 3]])

g = np.random.permutation(g)
In [102]: g
Out[102]: 
array([[2, 2, 2, 2],
       [3, 3, 3, 3],
       [1, 1, 1, 1],
       [0, 0, 0, 0]])

g = np.tile(g,(2,1))
In [104]: g
Out[104]: 
array([[2, 2, 2, 2],
       [3, 3, 3, 3],
       [1, 1, 1, 1],
       [0, 0, 0, 0],
       [2, 2, 2, 2],
       [3, 3, 3, 3],
       [1, 1, 1, 1],
       [0, 0, 0, 0]])

注意对角线。

array([[2, -, -, -],
       [3, 3, -, -],
       [1, 1, 1, -],
       [0, 0, 0, 0],
       [-, 2, 2, 2],
       [-, -, 3, 3],
       [-, -, -, 1],
       [-, -, -, -]])

从上到下取对角线。

newGroups = []
for i in range(numGroups):
    newGroups.append(np.diagonal(g[i:i+numMembers]))

In [106]: newGroups
Out[106]: 
[array([2, 3, 1, 0]),
 array([3, 1, 0, 2]),
 array([1, 0, 2, 3]),
 array([0, 2, 3, 1])]

newGroups = np.ravel(newGroups)
df["newGroups"] = newGroups

In [110]: df
Out[110]: 
    group  partid  newGroups
0       0       0          2
1       0       1          3
2       0       2          1
3       0       3          0
4       1       0          3
5       1       1          1
6       1       2          0
7       1       3          2
8       2       0          1
9       2       1          0
10      2       2          2
11      2       3          3
12      3       0          0
13      3       1          2
14      3       2          3
15      3       3          1

旧解决方案:蛮力法


结果比我想象的要难很多...

我有一种蛮力方法,它基本上猜测组的不同排列,直到最终得到一个每个人最终都进入不同组的方法。与您所展示的相比,这种方法的好处是它不会受到“最后用完组”的影响。

它可能会变慢 - 但对于 8 个组和每个组 4 名成员来说它很快。

样本数据

import random
import numpy as np
import pandas as pd
import itertools as it

random.seed(0)
numGroups=4
numMembers=4

data = list(it.product(range(numGroups),range(numMembers)))
df = pd.DataFrame(data=data,columns=['group','partid'])

解决方案

g = np.repeat(range(numGroups),numMembers).reshape((numGroups,numMembers))

In [4]: g
Out[4]: 
array([[0, 0, 0, 0],
       [1, 1, 1, 1],
       [2, 2, 2, 2],
       [3, 3, 3, 3]])

def reArrange(g):
    g = np.transpose(g)
    g = [np.random.permutation(x) for x in g]
    return np.transpose(g)

# check to see if any members in each old group have duplicate new groups
# if so repeat
while np.any(np.apply_along_axis(lambda x: len(np.unique(x))<numMembers,1,g)):
    g = reArrange(g)

df["newGroup"] = g.ravel()

In [7]: df
Out[7]: 
    group  partid  newGroup
0       0       0         2
1       0       1         3
2       0       2         1
3       0       3         0
4       1       0         0
5       1       1         1
6       1       2         2
7       1       3         3
8       2       0         1
9       2       1         0
10      2       2         3
11      2       3         2
12      3       0         3
13      3       1         2
14      3       2         0
15      3       3         1
于 2017-03-05T09:49:04.240 回答