3 回答
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)
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
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
添加回答
举报