我正在尝试制作幻想足球的R脚本(适当的英国足球,而不是手蛋:-))我可以在csv中输入一个玩家列表,它会吐出每个11人的组合,满足各种约束。
这是我的示例数据框:
df <- read.csv("Filename.csv",
header = TRUE)
> print(df)
Name Positon Team Salary
1 Eric Dier D TOT 9300000
2 Erik Pieters D STO 9200000
3 Christian Fuchs D LEI 9100000
4 Héctor Bellerín D ARS 9000000
5 Charlie Daniels D BOU 9000000
6 Ben Davies D TOT 8900000
7 Federico Fernández D SWA 8800000
8 Per Mertesacker D ARS 8800000
9 Alberto Moreno D LIV 8700000
10 Chris Smalling D MUN 8700000
11 Seamus Coleman D EVE 8700000
12 Jan Vertonghen D TOT 8700000
13 Romelu Lukaku F EVE 12700000
14 Harry Kane F TOT 12500000
15 Max Gradel F BOU 11900000
16 Alexis Sánchez F ARS 11300000
17 Jamie Vardy F LEI 11200000
18 Theo Walcott F ARS 10700000
19 Olivier Giroud F ARS 10700000
20 Wilfried Bony F MCI 10000000
21 Kristoffer Nordfeldt G SWA 7000000
22 Joe Hart G MCI 6800000
23 Jack Rose G WBA 6600000
24 Asmir Begovic G CHE 6600000
25 Mesut Özil M ARS 15600000
26 Riyad Mahrez M LEI 15200000
27 Ross Barkley M EVE 13300000
28 Dimitri Payet M WHM 12800000
29 Willian M CHE 12500000
30 Bertrand Traore M CHE 12500000
31 Kevin De Bruyne M MCI 12400000
约束如下:
1)每个11人阵容的总薪水不能超过100,000,000
2)一支球队最多只能有四名球员。例如。来自'CHE'(切尔西)的四名球员。
3)每个11位玩家阵容中有多少玩家可以从每个位置获得限制。可以有:
1 G(守门员),3至4 D(后卫),3至5 M(中场),1至3 F(前锋)
我希望每个符合上述约束条件的11名球员组合都会被退回。顺序并不重要(例如,1,2,3被认为与2,1,3相同,不应重复),并且玩家可以出现在多个阵容中。
我做了很多研究并玩过,但似乎无法随心所欲。我是R的新手。我不希望有人为我指出这一点,但如果有人能指出像我这样的新手正确的方向,那将非常感激。
感谢。
答案 0 :(得分:8)
这可以使用库LPSolve作为线性整数程序来解决。 这种问题可以很好地解决 - 与之前编写的相反 - 因为典型的解决方案的数量远小于域大小。
您可以为每个玩家添加一个零变量,无论该玩家是否在团队中。
可以使用
安装包 install.packages("lpSolve")
install.packages("lpSolveAPI")
可以在以下网址找到该文档:https://cran.r-project.org/web/packages/lpSolve/lpSolve.pdf
球员的第一个约束总和11
薪水基本上是所有球员变量乘以薪水栏等的总和......
要获得正确的解决方案,您需要在
中指定lp.solve(all.bin=TRUE
这样所有涉及玩家的变量都是零或一。
(我知道你正在努力学习,这就是为什么我不提供完整的解决方案)
修改强> 因为我没有给出完整的解决方案,所以我投了票。有点悲伤,就像原作者明确写道他不期望一个完整的解决方案
library(lpSolve)
df <- read.csv("/tmp/football.csv",header = TRUE,sep=";")
f.obj <- rep(1,nrow(df))
f.con <-
matrix(c(f.obj <- rep(1,nrow(df)),
as.vector(df$Salary),
(df$Positon=="G") *1.0,
(df$Positon=="D") *1.0,
(df$Positon=="D") *1.0,
(df$Positon=="M") *1.0,
(df$Positon=="M") *1.0,
(df$Positon=="F") *1.0,
(df$Positon=="F") *1.0),nrow=9,byrow= TRUE)
f.dir <- c("==", "<=","==",">=","<=",">=","<=",">=","<=")
f.rhs<- c(11, #number players
100000000, #salary
1 , #Goalkeeper
3 , # def min
4 , # def max
3 , # mdef min
5, # mdef max
1, # for, min
3 # wor, max
)
solutions <- lp ("max", f.obj, f.con, f.dir, f.rhs,all.bin=TRUE)
我没有添加团队约束,因为它不会在这里提供任何额外的见解....
** EDIT2 ** 如果您更改数据集,这可能会派上用场 R lpsolve binary find all possible solutions
答案 1 :(得分:1)
解决这个问题的一种强力方法(也可以很好地并行化并保证你所有可能的组合)是计算所有11个玩家的排列然后过滤掉那些没有的组合以逐步的方式符合您的限制。
要使这样的程序适合您的计算机内存,请为每个玩家提供唯一的整数ID,并创建ID作为团队集的向量。然后,当您实现过滤器时,您的功能可以在单个数据帧中通过该ID引用播放器信息。
说df
是包含所有玩家数据的数据框。
df$id <- 1:nrow(df)
获取所有ID组合:
# This will take a long time or run out of memory!
# In my 2.8Gz laptop took 466 seconds just for your 31 players
teams <- combn(df$id, 11)
当然,如果你的数据框很大(比如数百名玩家),这个实现可能需要很长时间才能完成。你可能最好只从你的玩家组中抽取11套而无需替换,并以“按需”方式构建团队。
更聪明的方法是根据玩家位置将数据集划分为 - 一个用于守门员,一个用于防守等等。然后使用上述方法从每个位置创建不同玩家的排列并组合最终结果。这将花费更少的时间,它仍然可以并行化和详尽无遗(给你所有可能的组合)。