J'essaie de créer un script R pour le football fantastique (football britannique, pas d'oeuf :-)) où je peux entrer une liste de joueurs dans un csv et il crachera chaque combinaison de 11 joueurs, qui répond à diverses contraintes .

Voici mon exemple de dataframe:

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

Et les contraintes sont les suivantes:

1) Le salaire total de chaque alignement de 11 joueurs ne peut pas dépasser 100000000

2) Il ne peut y avoir qu'un maximum de quatre joueurs par équipe. Par exemple. quatre joueurs de «CHE» (Chelsea).

3) Il y a une limite au nombre de joueurs dans chaque alignement de 11 joueurs pouvant être de chaque position. Il peut y avoir:

1 G (gardien de but), 3 à 4 D (défenseur), 3 à 5 M (milieu de terrain), 1 à 3 F (avant)

J'aimerais que chaque combinaison de 11 joueurs qui satisfait aux contraintes ci-dessus soit renvoyée. L'ordre n'est pas important (par exemple, 1,2,3 est considéré comme le même que 2,1,3 et ne doit pas être dupliqué) et un joueur peut apparaître dans plus d'un alignement.

J'ai fait pas mal de recherches et joué, mais je n'arrive pas à aller nulle part avec ça. Je suis nouveau chez R. Je ne m'attends pas à ce que quelqu'un cloue ça pour moi, mais si quelqu'un pouvait diriger un débutant comme moi dans la bonne direction, ce serait très apprécié.

Merci.

r
2
Gary866 27 déc. 2015 à 14:55

2 réponses

Meilleure réponse

Un moyen brutal de résoudre ce problème (qui est également magnifiquement parallélisable et vous garantit toutes les combinaisons possibles) consiste à calculer toutes les permutations à 11 joueurs, puis à filtrer les combinaisons qui ne sont pas conformes à votre limites par étapes.

Pour faire entrer un programme comme celui-ci dans la mémoire de votre ordinateur, attribuez à chaque joueur un identifiant entier unique et créez des vecteurs d'identifiants sous forme d'ensembles d'équipe. Lorsque vous implémentez ensuite vos filtres, vos fonctions peuvent faire référence aux informations du joueur par cet identifiant dans une seule trame de données.

Dites que df est votre bloc de données avec toutes les données du joueur.

df$id <- 1:nrow(df)

Obtenez toutes les combinaisons d'identifiants:

# 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) 

Bien sûr, si votre dataframe est volumineuse (comme des centaines de joueurs), cette implémentation pourrait prendre beaucoup de temps à se terminer. Vous feriez probablement mieux de simplement échantillonner 11 sets de votre ensemble de joueurs sans remplacement et de constituer des équipes "à la demande".

Un moyen plus intelligent est de partitionner votre jeu de données en fonction de la position du joueur en un pour les gardiens de but, un pour la défense, etc. Et puis utilisez l'approche ci-dessus pour créer des permutations de différents joueurs de chaque position et combiner les résultats finaux. Cela prendrait ridiculement moins de temps, ce serait toujours parallélisable et exhaustif (vous donner toutes les combinaisons possibles).

1
kliron 27 déc. 2015 à 13:34

Cela peut être résolu sous forme de programme d'entiers linéaires à l'aide de la bibliothèque LPSolve. Ce genre de problèmes est très bien résolu - contrairement à ce qui a été écrit auparavant - car généralement le nombre de solutions est beaucoup plus petit que la taille du domaine.

Vous pouvez ajouter pour chaque joueur une variable zéro un, que ce joueur soit ou non dans l'équipe.

Le package peut être installé en utilisant

 install.packages("lpSolve")
 install.packages("lpSolveAPI")

La documentation peut être trouvée à: https: //cran.r-project .org / web / packages / lpSolve / lpSolve.pdf

Première contrainte somme des joueurs 11

Le salaire est fondamentalement une somme de tous les joueurs variable multipliée par la colonne salaire et ainsi de suite ...

Pour obtenir des solutions appropriées, vous devez spécifier dans

lp.solve(all.bin=TRUE

De telle sorte que toutes les variables se référant aux joueurs sont soit zéro soit un.

(J'ai compris que tu essayais d'apprendre, c'est pourquoi je m'abstiens de donner une solution complète)

MODIFIER Comme j'ai été déclassé, probablement parce que je n'ai pas donné la solution complète. Un peu triste, car l'auteur original a explicitement écrit qu'il ne s'attend pas à une solution complète

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)

Je n'ai pas ajouté la contrainte d'équipe car elle n'aurait pas fourni d'informations supplémentaires ici ....

** MODIFIER2 ** Cela peut être utile si vous modifiez votre ensemble de données R lpsolve binary trouve toutes les solutions possibles

7
Community 23 mai 2017 à 10:29