在分组中各选择一个

2024-06-11 16:52:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建所有可能的球员配对组合,根据A、B、C或D型障碍分配到4人高尔夫球队

我尝试过各种itertools方法,比如组合和排列,但都没有找到正确的方法。你知道吗

from itertools import combinations, product, permutations
g = player_df.groupby(by = 'hcp_ABCD')
teams_listoflists = [group[1].index for group in g]
teams_combo_ndx = [player for player in permutations(teams_listoflists, 4)]

这是我的熊猫桌:

        handicap      name hcp_ABCD
0         24   Player1        D
1         21   Player2        D
2          8   Player3        B
3         14   Player4        C
4         20   Player5        D
5         13   Player6        C
6         -1   Player7        A
7          5   Player8        A
8          8   Player9        B
9          6  Player10        B
10        20  Player11        D
11        15  Player12        C
12         0  Player13        A
13        12  Player14        C
14         0  Player15        A
15        10  Player16        B

我想输出的所有组合(没有重复)的球员组合(队),这样每个队有一个类型a,B,C,和D的每一个。此输出可以是一个类似于上面按“选项”分组的表

编辑: 为了清楚起见,我添加了这个输出示例。你知道吗

                       A Player     B Player     C Player   D Player
    option 1  team1    Player7      Player3      Player4    Player1
              team2    Player8      Player9      Player6    Player2
              team3    Player13     Player10     Player12   Player5
              team4    Player15     Player16     Player14   Player11

    option 2  team1    Player7      Player16     Player4    Player1
              team2    Player8      Player3      Player6    Player2
              team3    Player13     Player9      Player12   Player5
              team4    Player15     Player10     Player14   Player11

    ...


                       A Player     B Player     C Player   D Player
    option n  team1    Player7      Player3      Player4    Player11
              team2    Player8      Player9      Player6    Player1
              team3    Player13     Player10     Player12   Player2
              team4    Player15     Player16     Player14   Player5

上面的观点是,我试图找到一个生成器,它循环遍历每个残障组中所有球员的组合,这样就可以清楚地看到球队的选择组合。你知道吗

编辑#2 我已确定此代码生成所有潜在团队组合的组合:

g = df.groupby(by = 'hcp_ABCD')
combinations = [list(group[1].index) for group in g]

这将创建一个列表,其中a个玩家在列表[0]中,B个玩家在列表[1]中,等等

这会得到所有可能的团队组合的索引器:

from itertools import product
options = [option for option in product(*combinations)]

但是,如何将这些分配到“选项”(见上面的例子)中并确保没有重复是我一直坚持的。你知道吗

编辑#3更简单的版本(思考此问题的方式)是使用以下集合:

A = ['A1', 'A2', 'A3', 'A4']
B = ['B1', 'B2', 'B3', 'B4']
C = ['C1', 'C2', 'C3', 'C4']
D=  ['D1', 'D2', 'D3', 'D4']

这基本上与groupby在上面所做的相同(按hcp\u ABCD分组),但将每个人命名为“A Player”、“B Player”等

可能的团队组合:

team_combinations = [team for team in product(A, B, C, D)]

然后,下一个技巧是将这些分配到4个团队的组合中,没有重复的玩家。你知道吗


Tags: inforgroupproductoptionplayerhcpabcd
3条回答

下面的方法是使用笛卡尔积,然后分组两次,将玩家分配到具有一组独特障碍的团队中。你知道吗

import pandas as pd
from pandas.compat import StringIO

print(pd.__version__)
pd.options.display.max_rows = 664

csvdata = StringIO("""handicap,name,hcp_ABCD
24,Player1,D
21,Player2,D
8,Player3,B
14,Player4,C
20,Player5,D
13,Player6,C
-1,Player7,A
5,Player8,A
8,Player9,B
6,Player10,B
20,Player11,D
15,Player12,C
0,Player13,A
12,Player14,C
0,Player15,A
10,Player16,B""")

df=pd.read_csv(csvdata)

# Generate all possible groups
# https://stackoverflow.com/questions/53699012/performant-cartesian-product-cross-join-with-pandas
def cartesian_product(left, right):
    return (left.assign(key=1).merge(right.assign(key=1), on='key').drop('key', 1))

def distribute_players(x):
    x['distribute'] = range(0, 4)
    return x

df = cartesian_product(df, df.copy())
df = df.groupby(['name_x', 'hcp_ABCD_y']).apply(distribute_players)
df['team'] = df.groupby(['name_x', 'distribute']).ngroup()
print(df[['handicap_y','name_y','hcp_ABCD_y','team']].sort_values(['team']))

     handicap_y    name_y hcp_ABCD_y  team
0            24   Player1          D     0
2             8   Player3          B     0
3            14   Player4          C     0
6            -1   Player7          A     0
1            21   Player2          D     1
5            13   Player6          C     1
7             5   Player8          A     1
8             8   Player9          B     1

感谢您澄清预期结果。这是我测试的答案。它可能不是您预期结果的确切格式,但我让您来解决它。你知道吗

import pandas as pd
def is_duplicate_team(team, group):
    '''check if an option already exists'''
    return any(group == t for t in team)
def is_player_exists(group, arr):
    '''check if a player exists in a group'''
    return any(x in g for g in group for x in arr)

df = [         (24   ,'Player1','D'),
         (21   ,'Player2','D'),
          (8   ,'Player3','B'),
         (14   ,'Player4','C'),
         (20   ,'Player5','D'),
         (13   ,'Player6','C'),
         (-1   ,'Player7','A'),
          (5   ,'Player8','A'),
          (8   ,'Player9','B'),
          (6  ,'Player10','B'),
        (20  ,'Player11','D'),
        (15  ,'Player12','C'),
         (0  ,'Player13','A'),
        (12  ,'Player14','C'),
         (0  ,'Player15','A'),
        (10  ,'Player16','B')]
df = pd.DataFrame(df, columns=['handicap', 'name', 'hcp_ABCD'])
from itertools import product
grouped = df.groupby('hcp_ABCD')['name'].apply(list).reset_index()
df_name = [n for n in grouped.name]
df_comb = [p for p in product(*df_name)]

# below code will get all combinations of groups and for a team having all players
teams=[]
for i in df_comb[:-1]:
    group=[i] 
    for j in df_comb[1:]: 
        if not is_player_exists(group, j):
            group.append(j)
        if len(group) == 4:
            if not is_duplicate_team(teams, group):
                teams.append(group)
            continue

# below code will print the output similar to what you expected
i=0
for t in teams:
    i+=1
    print('option: ', str(i) )
    for p in t:
        print(p)

我在评论中提出了一个建议。下面是一个实现:

import pandas as pd
from functools import reduce

data = [
    (24,'Player1','D'),
    (21,'Player2','D'),
    (8,'Player3','B'),
    (8,'Player4','B'),
    (14,'Player5','C'),
    (13,'Player6','C'),
    (-1,'Player7','A'),
    (5,'Player8','A')
]
df = pd.DataFrame(
    data,
    columns=['handicap', 'name', 'hcp_ABCD']
)

dfs = [
    grp_df.drop(columns="hcp_ABCD")
          .rename(columns={"name": f"player_{hndcp}",
                           "handicap": f"handicap_{hndcp}"})
    for hndcp, grp_df in df.assign(key=1)
                           .groupby("hcp_ABCD")
]
result = reduce(
    lambda left, right: left.merge(right, how="outer", on="key"),
    dfs
).drop(columns="key")
print(result)

输出:

    handicap_A player_A  handicap_B player_B  handicap_C player_C  handicap_D player_D
0           -1  Player7           8  Player3          14  Player5          24  Player1
1           -1  Player7           8  Player3          14  Player5          21  Player2
2           -1  Player7           8  Player3          13  Player6          24  Player1
3           -1  Player7           8  Player3          13  Player6          21  Player2
4           -1  Player7           8  Player4          14  Player5          24  Player1
5           -1  Player7           8  Player4          14  Player5          21  Player2
6           -1  Player7           8  Player4          13  Player6          24  Player1
7           -1  Player7           8  Player4          13  Player6          21  Player2
8            5  Player8           8  Player3          14  Player5          24  Player1
9            5  Player8           8  Player3          14  Player5          21  Player2
10           5  Player8           8  Player3          13  Player6          24  Player1
11           5  Player8           8  Player3          13  Player6          21  Player2
12           5  Player8           8  Player4          14  Player5          24  Player1
13           5  Player8           8  Player4          14  Player5          21  Player2
14           5  Player8           8  Player4          13  Player6          24  Player1
15           5  Player8           8  Player4          13  Player6          21  Player2

相关问题 更多 >