为了账号安全,请及时绑定邮箱和手机立即绑定

在熊猫分组中选择一个

在熊猫分组中选择一个

拉莫斯之舞 2022-01-11 20:27:43
我正在尝试创建所有可能的球员配对组合,以根据障碍类型 A、B、C 或 D 分配到 4 人高尔夫球队。我尝试了各种 itertools 方法,例如组合和排列,但无法找出正确的方法。from itertools import combinations, product, permutationsg = 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_ABCD0         24   Player1        D1         21   Player2        D2          8   Player3        B3         14   Player4        C4         20   Player5        D5         13   Player6        C6         -1   Player7        A7          5   Player8        A8          8   Player9        B9          6  Player10        B10        20  Player11        D11        15  Player12        C12         0  Player13        A13        12  Player14        C14         0  Player15        A15        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上面的重点是,我正在尝试找到一个生成器,该生成器循环遍历每个障碍组中的所有球员组合,以便团队选项的组合清晰。编辑#2 我已经确定此代码产生了所有潜在团队组合的组合:g = df.groupby(by = 'hcp_ABCD')combinations = [list(group[1].index) for group in g]这将创建一个列表列表,其中包含列表 [0] 中的 A 玩家、列表 [1] 中的 B 玩家等。这为所有可能的团队组合提供了一个索引器:from itertools import productoptions = [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_ABCD 分组),但命名每个“A Player”、“B Player”等。可能的团队组合:team_combinations = [team for team in product(A, B, C, D)]然后下一个技巧是将这些分配到 4 支球队的组合中,并且没有重复的球员。
查看完整描述

3 回答

?
MMMHUHU

TA贡献1834条经验 获得超8个赞

感谢您澄清预期结果。这是我测试的答案。它可能不是您预期结果的确切格式,但我留给您修复它。


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)



查看完整回答
反对 回复 2022-01-11
?
眼眸繁星

TA贡献1873条经验 获得超9个赞

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


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


查看完整回答
反对 回复 2022-01-11
?
GCT1015

TA贡献1827条经验 获得超4个赞

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


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


查看完整回答
反对 回复 2022-01-11
  • 3 回答
  • 0 关注
  • 129 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信