如何创建21个10人的随机组4次,没有人在同一组

时间:2015-12-11 07:50:24

标签: pandas random slice shuffle

我是python的新手,并且努力学习。我有一项非常乏味的任务,我希望你能帮助我。

我正在组织220人的活动。全天有4项活动。这些活动由10人(22支队伍)组成。目标是团队改变的每项活动。所以,我想重新安排团队组成4次。这是为了确保人们尽可能多地了解同事。

在excel中,我在列A中有220个名称的列表。我在列B中为每个名称(1 -220)分配了一个数字。我随机导入了模块和pandas。我的第一步是导入excel文件,将带有Numbers的列B转换为列表并对它们进行洗牌。

在那一步之后我迷失了。从洗牌列表中我想创建22支球队。在第一次抽签之后,我想再次洗牌并重新创建22支球队,但条件是在第二组合中没有来自第一队组成的人。总计这个过程重复四次。

理想情况下,我想将结果导出回excel。

希望有人可以帮助我!

再一次,我正在学习,请分享思考过程:)。

感谢您的时间。

亲切的问候,

BAS

2 个答案:

答案 0 :(得分:0)

首先,不要使用熊猫。这是工作的错误工具。请改用NumPy。这是一个代码:

In [1]: import numpy as np

In [2]: people = np.arange(1, 221, 1)
        people
Out[2]: array([  1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,
                 14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,
                 27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,
                 40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,
                 53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  65,
                 66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,
                 79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,
                 92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 102, 103, 104,
                105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
                118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
                131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
                144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
                157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
                170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
                183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
                196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
                209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220])

In [3]: np.random.choice(people, 220, replace=False).reshape(22,10)
Out[3]: array([[ 20,  48, 164, 176, 135, 190,  67, 147, 203, 130],
               [150, 177, 171, 141, 122, 127, 202, 172,  21, 219],
               [167, 206,  84, 118, 163, 181,  34,  87, 116, 184],
               [ 33,  26,  70, 119, 129, 191, 105,  69,  86, 217],
               [ 94,  24, 146,   9,  31, 208, 179, 148,  57, 102],
               [211, 170,  65, 195, 220,  61,  88, 187,  32,   7],
               [182,  40, 144, 145, 198,  47, 193,  74,  44,  90],
               [174, 121, 216,  63,  82,  38, 201, 113,  13,  66],
               [180, 137, 214,  73,  75,  51,  80,  23,  71,  18],
               [161, 115,   3, 157,  89,  79,  29,  68, 200,   8],
               [142, 173,  98,  36, 133, 215, 138,  50,  53,   4],
               [152, 101, 139,  54,  30, 108,  49, 213, 124,  83],
               [ 76,  17,  64,  10,  56,  22, 128, 153, 158, 140],
               [131,  11,  45, 192,  92, 166,  60,  37,  12, 156],
               [104,  25,   6, 205, 212, 197,  77,  46, 199,  96],
               [ 59,  19, 112, 132, 126, 159, 151, 207,  85, 109],
               [ 42,  55, 204, 188, 185,  35,  62,  41,  27, 178],
               [ 14, 194,   2, 186, 143,  78, 134, 103, 106, 110],
               [100,  91,  99, 111,  72,  58,  15, 120, 136,  97],
               [ 39,  81, 123, 149, 165, 169, 209, 175,   1, 117],
               [189,  28,  95, 114, 162, 160, 196,   5,  93, 154],
               [210,  16, 168, 218,  43, 107, 155, 125,  52, 183]])

请注意,Out[3]是一个包含22行和10列的矩阵(22个团队,每个团队10人)。您只需要在In [3]中运行代码,就像您拥有的任务一样多。所以基本上:

In [4]: tasks = {} # Tasks is a dictionary with task number as key, and teams array as value.
        for i in np.range(1, 5, 1):
            tasks['task_' + str(i)] = np.random.choice(people, 220, replace=False).reshape(22,10)

现在,您可以将存储在tasks中的结果返回到Excel文件中,然后从那里继续。如果您有任何疑虑,请告诉我。

如果您坚持使用Pandas,并且已经在df中加载了数据,那么您可以使用Pandas为每个任务返回每个团队的玩家姓名。此代码应该足以满足您的需求:

df.set_index('player_id', inplace=True) # Which is actually pointless because
# Pandas will automatically create a 0 indexed index when you read your data in.
# So you don't even need any player_id column to begin with. If that is the case,
# change In [2] above to people = np.arange(0, 220, 1), or simply, np.arange(220)

tasks = {}
for i in np.arange(1, 5, 1):
    tasks['task_' + str(i)] = {}
    j = 1
    for team in np.random.choice(people, 220, replace=False).reshape(22,10):
      tasks[i]['team_' + str(j)] = df.loc[team].values
      j += 1
这段代码末尾的

tasks将是嵌套的Dictionary,其结构如下:

tasks = {'task_1' : {'team_1'  : [list_of_players],
                     'team_2'  : [list_of_players],
                      ...
                     'team_19' : [list_of_players],
                     'team_20' : [list_of_players]},
         'task_1' : {'team_1'  : [list_of_players],
                     'team_2'  : [list_of_players],
                      ...
                     'team_19' : [list_of_players],
                     'team_20' : [list_of_players]},
         'task_1' : {'team_1'  : [list_of_players],
                     'team_2'  : [list_of_players],
                      ...
                     'team_19' : [list_of_players],
                     'team_20' : [list_of_players]},
         'task_1' : {'team_1'  : [list_of_players],
                     'team_2'  : [list_of_players],
                      ...
                     'team_19' : [list_of_players],
                     'team_20' : [list_of_players]}}

希望这有帮助!

答案 1 :(得分:0)

这是一个蛮力算法 - 它取决于随机选择,如果失败,它只是再次尝试。

根本没有使用pandas,只是普通的列表和集合。

工作原理:

  • 选择一个人加入团队
  • 如果他已经遇到某人,请带他回去挑选另一个人
  • 否则让他加入团队并更新整个团队的met变量
  • 有时,事实上,剩下的每个人都已经在团队中遇到过某人 - 在这种情况下,只是不要打扰并提出异常
from random import choice

class Person:
    def __init__(self, name):
        self.name = name
        self.met = set()

    def __repr__(self):
        return self.name

class TooManyIteration(Exception):
    pass

GAMES = 4
TEAMS = 22
TEAMSIZE = 10

def pick_teams(s):
    s_ = s.copy()
    teams = [set() for _ in range(TEAMS)]
    for t in teams:
        c = 0
        while len(t) < TEAMSIZE:
            p = choice(tuple(s_))
            s_.remove(p)

            if all(p not in x.met for x in t):
                t.add(p)
            else:
                s_.add(p)

                c += 1
                if c > len(s):
                    # failed to pick
                    raise TooManyIteration()

    for t in teams:
        for x in t:
            x.met.update(t)

    return teams

s = set(Person(str(i)) for i in range(220))
# s = set(Person(name) for name in LIST_OF_NAMES)

games = []
while len(games) < GAMES:
    try:
        games.append(pick_teams(s))
    except TooManyIteration:
        continue
print(games)
幸运的是,你只想要四场比赛,我认为它具有指数级的复杂性。