Loquicom hace 5 años
commit
a9b1bf546b
Se han modificado 3 ficheros con 2270 adiciones y 0 borrados
  1. 302 0
      anilist-api.py
  2. 102 0
      graphql-client.py
  3. 1866 0
      projet-fdd.ipynb

+ 302 - 0
anilist-api.py

@@ -0,0 +1,302 @@
+import pprint
+import numpy as np
+import pandas as pd
+from graphql_client import GraphQLClient
+
+pp = pprint.PrettyPrinter(indent=2)
+
+def myprint(data, show = True):
+    if show:
+        pp.pprint(data)
+
+class AnilistApi:
+    # Le client graphQL pour effectuer les requetes
+    graphql = GraphQLClient('https://graphql.anilist.co')
+    # La derniere query graphql
+    query = None
+    # Le derniere utilisateur
+    user = None
+    
+    def findUser(self, username, returnSelf = True):
+        """Cherche un utilisateur passé en paramètre pour les futures appels à l'API"""
+        request = '''
+            query ($name: String) {
+              User(name: $name) {
+                    id
+                    mediaListOptions {
+                        scoreFormat
+                    }
+              }
+            }
+        '''
+        variables = {
+            'name': username
+        }
+        # Création query
+        self.query = self.graphql.query(request, variables)
+        # Execution query
+        result = self.query.execute().get()
+        if(self.graphql.isError(result)):
+            result = None
+        self.user = result
+        # Retour
+        if returnSelf:
+            return self
+        return result != None
+    
+    def getUserAnimeList(self):
+        """Retourne la liste d'anime complétés de l'utilisateur (ou None en cas de problème)"""
+        if(self.user == None):
+            return None
+        request = '''
+            query ($id: Int) {
+              MediaListCollection (userId: $id, type: ANIME, status: COMPLETED) {
+                lists {
+                    entries {
+                        score
+                        media {
+                          id
+                          title {
+                            userPreferred
+                          }
+                          averageScore
+                          format
+                          episodes
+                          duration
+                          popularity
+                          source
+                          tags {
+                            name
+                          }
+                          genres
+                        }
+                    }
+                }
+            }
+        }
+        '''
+        variables = {
+            'id': self.user['User']['id']
+        }
+        # Création query
+        self.query = self.graphql.query(request, variables)
+        # Execution query
+        result = self.query.execute().get()
+        if(self.graphql.isError(result)):
+            return None
+        return UserAnimeList(result['MediaListCollection']['lists'][0]['entries'], self.user['User']['mediaListOptions']['scoreFormat'])
+    
+    def fetchAnimeList(self, query, page = 0, element = 50):
+        if query.object != 'Media':
+            raise ValueError('bad query type: ' + query.object)
+        # Requete graphql
+        request = '''
+        query ($page: Int, $element: Int, ${def}) {
+            Page(page: $page, perPage: $element) {
+                media(${param}) {
+                    id
+                    title {
+                        userPreferred
+                    }
+                    averageScore
+                    format
+                    episodes
+                    duration
+                    popularity
+                    source
+                    tags {
+                        name
+                    }
+                    genres
+                }
+            }
+        }
+        '''
+        # Recupération info query et application
+        definition, parameter, variable = query.get()
+        request = request.replace('${def}', definition)
+        request = request.replace('${param}', parameter)
+        variable['page'] = page
+        variable['element'] = element
+        # Création query
+        self.query = self.graphql.query(request, variable)
+        # Execution query
+        result = self.query.execute().get()
+        if(self.graphql.isError(result)):
+            return None
+        # Préparation pour creation objet AnimeList
+        data = []
+        for i in range(0, len(result['Page']['media'])):
+            data.append({'media': result['Page']['media'][i]})
+        return UserAnimeList(data)
+    
+    def iterateAnimeListFetch(self, query, nb, element):
+        for i in range (0, nb):
+            yield self.fetchAnimeList(query, i, element)
+    
+class AnilistQuery:
+    __declaration = ''
+    __parameter = ''
+    __variable = {}
+    
+    # Constructeur
+    def __init__(self, obj = 'Media'):
+        self.object = obj
+        self.reset()
+        
+    def scoreGreaterThan(self, value):
+        if(self.__variable.get('sgt') == None):
+            self.__declaration += ',$sgt: Int'
+            self.__parameter += ',averageScore_greater: $sgt'
+            self.__variable['sgt'] = round(value)
+        return self
+    
+    def popularityGreaterThan(self, value):
+        if(self.__variable.get('pgt') == None):
+            self.__declaration += ',$pgt: Int'
+            self.__parameter += ',popularity_greater: $pgt'
+            self.__variable['pgt'] = round(value)
+        return self
+    
+    def episodeBetween(self, minValue, maxValue):
+        if(self.__variable.get('egt') == None):
+            self.__declaration += ',$egt: Int'
+            self.__parameter += ',episodes_greater: $egt'
+            self.__variable['egt'] = round(minValue)
+        if(self.__variable.get('elt') == None):
+            self.__declaration += ',$elt: Int'
+            self.__parameter += ',episodes_lesser: $elt'
+            self.__variable['elt'] = round(maxValue)
+        return self
+    
+    def durationBetween(self, minValue, maxValue):
+        if(self.__variable.get('dgt') == None):
+            self.__declaration += ',$dgt: Int'
+            self.__parameter += ',duration_greater: $dgt'
+            self.__variable['dgt'] = round(minValue)
+        if(self.__variable.get('dlt') == None):
+            self.__declaration += ',$dlt: Int'
+            self.__parameter += ',duration_lesser: $dlt'
+            self.__variable['dlt'] = round(maxValue)
+        return self
+    
+    def formatIn(self, value):
+        if(self.__variable.get('fin') == None):
+            self.__declaration += ',$fin: [MediaFormat]'
+            self.__parameter += ',format_in: $fin'
+            self.__variable['fin'] = value
+        return self
+    
+    def sourceIn(self, value):
+        if(self.__variable.get('sin') == None):
+            self.__declaration += ',$sin: [MediaSource]'
+            self.__parameter += ',source_in: $sin'
+            self.__variable['sin'] = value
+        return self
+    
+    def tagIn(self, value):
+        if(self.__variable.get('tin') == None):
+            self.__declaration += ',$tin: [String]'
+            self.__parameter += ',tag_in: $tin'
+            self.__variable['tin'] = value
+        return self
+    
+    def genreIn(self, value):
+        if(self.__variable.get('gin') == None):
+            self.__declaration += ',$gin: [String]'
+            self.__parameter += ',genre_in: $gin'
+            self.__variable['gin'] = value
+        return self
+    
+    def get(self):
+        return self.__declaration.strip(','), self.__parameter.strip(','), self.__variable
+    
+    def reset(self):
+        self.__declaration = ''
+        self.__parameter = ''
+        self.__variable = {}
+    
+    def __str__(self):
+        return 'Declaration: ' + self.__declaration.strip(',') + '\nParameter: ' + self.__parameter.strip(',') + '\nVariable: ' + pp.pformat(self.__variable)
+
+class UserAnimeList:
+    data = []
+    
+    # Constructeur, met en forme les données
+    def __init__(self, entries, userScoreType = None):
+        self.data = []
+        for entry in entries:
+            media = entry['media']
+            d = {
+                'id': media['id'],
+                'title': media['title']['userPreferred'],
+                'score': media['averageScore'],
+                'popularity': media['popularity'],
+                'format': media['format'],
+                'episode': media['episodes'],
+                'duration': media['duration'],
+                'source': media['source']
+            }
+            # Ajout score de l'utilisateur si present
+            if userScoreType != None and entry.get('score') != None:
+                d['userScore'] = self.__formatScore(entry['score'], userScoreType)
+            # Ajout tag (3 max)
+            end = 3 if len(media['tags']) > 3 else len(media['tags'])
+            for i in range(0, 3):
+                if(i < end):
+                    d['tag' + str(i + 1)] = media['tags'][i]['name']
+                else:
+                    d['tag' + str(i + 1)] = 'None'
+            # Ajout genre (5 max)
+            end = 5 if len(media['genres']) > 5 else len(media['genres'])
+            for i in range(0, 5):
+                if(i < end):
+                    d['genre' + str(i + 1)] = media['genres'][i]
+                else:
+                    d['genre' + str(i + 1)] = 'None'
+            # Ajoute la ligne aux données
+            self.data.append(d)
+            
+    def toDataFrame(self, dummies = False):
+        df = pd.DataFrame(self.data)
+        if dummies and len(self.data) > 0:
+            df = self.__multipleColDummies(df, 'tag', 3)
+            df = self.__multipleColDummies(df, 'genre', 5)
+            df = pd.get_dummies(df, columns=['format', 'source'])
+        return df
+        
+    def __formatScore(self, score, scoreType):
+        if scoreType == 'POINT_10_DECIMAL' or scoreType == 'POINT_10':
+            return 10 * score
+        elif scoreType == 'POINT_5':
+            return 20 * score
+        elif scoreType == 'POINT_3':
+            return (score / 3) * 100
+        else:
+            return score
+        
+    def __multipleColDummies(self, df, colname, num):
+        # Recherche de toutes les valeurs possibles
+        values = []
+        for i in range(1, num + 1):
+            d = df[colname + str(i)]
+            for item in d.iteritems():
+                if not(item[1] in values and item[1] != 'None'):
+                    values.append(item[1])
+        # Creation colonne dans la dataframe
+        for val in values:
+            df[colname + '_' + val.replace(' ', '_')] = 0
+        # Remplissage des colonnes
+        newDf = []
+        for row in df.iterrows():
+            row = pd.Series(row[1])
+            for i in range(1, num + 1):
+                if row[colname + str(i)] != None:
+                    name = row[colname + str(i)].replace(' ', '_')
+                    row[colname + '_' + name] = 1
+            newDf.append(row)
+        df = pd.DataFrame(newDf)
+        # Suppr ancienne colonne
+        for i in range(1, num + 1):
+            df = df.drop(colname + str(i), axis = 1)
+        return df

+ 102 - 0
graphql-client.py

@@ -0,0 +1,102 @@
+import requests
+
+class GraphQLClient:
+    # Constructeur, demande l'url de l'api
+    def __init__(self, url):
+        self.url = url
+        try:
+            requests.get(self.url)
+        except:
+            raise self.__BadURLException('bad url: ' + self.url)
+        
+    # Création d'une query
+    def query(self, graphQlQuery, variables = None):
+        query = self.__GraphQLQuery()
+        return query.set(self.url, graphQlQuery, variables)
+    
+    def isError(self, result):
+        query = self.__GraphQLQuery()
+        return query.isError(result)
+        
+    # Class privée pour gérer les query
+    class __GraphQLQuery:
+        __set = False
+        last = None
+        url = None
+        query = None
+        variables = None
+        
+        # Verif que l'objet est bien set
+        def __isSet(self):
+            if(not(self.__set)):
+                raise ValueError('Object attributes are not set')
+        
+        # Constructeur (le constructeur par defaut doit être gardé)
+        def set(self, url, query, var = None):
+            self.url = url
+            self.query = query
+            self.variables = var
+            self.__set = True
+            return self
+            
+        # Execute la query
+        def execute(self, returnSelf = True):
+            self.__isSet()
+            # Make the HTTP Api request
+            self.last = requests.post(self.url, json={'query': self.query, 'variables': self.variables})
+            if returnSelf:
+                return self
+            else:
+                return self.last.status_code
+            
+        def get(self):
+            if self.last == None:
+                return None
+            elif self.last.status_code == 200:
+                return self.data()
+            elif self.last.status_code >= 400 and self.last.status_code < 500:
+                return self.error()
+            else:
+                return self.last.text
+        
+        def data(self):
+            if self.last == None or self.last.status_code != 200:
+                return None
+            else:
+                return self.last.json()['data']
+            
+        def error(self):
+            if self.last == None or self.last.status_code < 400 or self.last.status_code >= 500:
+                return None
+            else:
+                if len(self.last.json()['errors']) == 1:
+                    return self.__GraphQLError(self.last.json()['errors'][0])
+                errors = []
+                for error in self.last.json()['errors']:
+                    errors.append(self.__GraphQLError(error))
+                return errors
+            
+        def isError(self, result):
+            return type(result) is self.__GraphQLError
+        
+        # Clas privée de query pour gérer les erreurs
+        class __GraphQLError:
+            # Constructeur
+            def __init__(self, error):
+                self.code = error['status']
+                self.message = error['message']
+                if error.get('locations') != None:
+                    self.line = error['locations'][0]['line']
+                    self.column = error['locations'][0]['column']
+                else:
+                    self.line = 'Unknown'
+                    self.column = 'Unknown'
+                
+            # toString
+            def __str__(self):
+                return 'Status code: ' + str(self.code) + ', Line: ' + str(self.line) + ', Column: ' + str(self.column) + ', Message: ' + self.message
+                
+    
+    # Class privée pour gérer les mauvaise url
+    class __BadURLException(Exception):
+        pass

+ 1866 - 0
projet-fdd.ipynb

@@ -0,0 +1,1866 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Projet FDD - Arthur Brandao & Maxence Bacquet\n",
+    "\n",
+    "L'objectif du projet est récupérer la liste des anime regardés par un utilisateur sur le site Anilist.co pour lui faire des recommendations.\n",
+    "\n",
+    "## Import\n",
+    "\n",
+    "Import des class utile pour la recommendation. La class AnilistApi et AnilistQuery ont été créées à l'occasion de ce projet pour permettre d'interroger facielement l'API. de plus l'API d'Anilist utilisant GraphQL une class GraphQLClient à aussi été créée pour l'occasion et est utiliser par la class AnilistApi."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {
+    "_cell_guid": "b1076dfc-b9ad-4769-8c92-a6c4dae69d19",
+    "_uuid": "8f2839f25d086af736a60e9eeb907d3b93b6e0e5"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "numpy: 1.16.4\n",
+      "pandas: 0.25.2\n"
+     ]
+    }
+   ],
+   "source": [
+    "import numpy as np\n",
+    "import pandas as pd\n",
+    "from anilist_api import AnilistApi\n",
+    "from anilist_api import AnilistQuery\n",
+    "from sklearn.model_selection import train_test_split\n",
+    "from sklearn.ensemble import RandomForestClassifier\n",
+    "# Affichage des versions\n",
+    "print('numpy: {}'.format(np.__version__))\n",
+    "print('pandas: {}'.format(pd.__version__))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Définition des variable utile pour tous le projet (variable global et instance d'objet)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Le nom de l'utilisateur pour qui sont faite les recommendations\n",
+    "USER = 'Loquicom'\n",
+    "# La precision minimum du model lors de la phase de test (en %) /!\\ Un trop grand nombre peut être impossible à atteindre\n",
+    "ACCURACYMIN = 80\n",
+    "# Nombre d'iteration maximum avant de considerer que le model ne peut pas atteindre la précision démandée (pourr éviter une boucle infini)\n",
+    "ITERATIONMAX = 25 # -1 <=> Pas de limite\n",
+    "# Le nombre de requete effectué pour la recherche\n",
+    "NBITERATION = 4\n",
+    "# Le nombre d'anime récupérés par requete (max 50)\n",
+    "NBANIME = 50\n",
+    "# L'api d'Anilist\n",
+    "anilist = AnilistApi()\n",
+    "# Le modèle utilisé pour l'apprentissage des features utile à la recommendation\n",
+    "model = RandomForestClassifier(n_estimators = 1000, random_state = 42, max_features=10)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Definition des fonctions utilitaires\n",
+    "\n",
+    "  - **valid_data**: Permet de verifier et mesurer la precision des données predite par le model\n",
+    "  - **identical_features**: Fait en sorte que le dataframe est les même feature que la dataframe source\n",
+    "  - **make_querry**: Création d'une query basique utile pour requeter l'api d'Anilist"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def valid_data(predict, value):\n",
+    "    result = pd.Series(value - predict)\n",
+    "    error = result[result != 0].count()\n",
+    "    accuracy = 100 - ((error / result.size) * 100)\n",
+    "    return result.size, error, accuracy\n",
+    "\n",
+    "def identical_features(source, target, keep = []):\n",
+    "    if keep is str:\n",
+    "        keep = [keep]\n",
+    "    # Ajout feature manquante\n",
+    "    for feature in source.columns:\n",
+    "        if feature not in target.columns:\n",
+    "            target[feature] = 0\n",
+    "    # Suppr feature en trop\n",
+    "    drop = []\n",
+    "    for feature in target.columns:\n",
+    "        if feature not in source.columns and feature not in keep:\n",
+    "            drop.append(feature)\n",
+    "    return target.drop(drop, axis = 1)\n",
+    "\n",
+    "def make_query(score = -1, popularity = -1, epMin = -1, epMax = -1, durationMin = -1, durationMax = -1, source = [], formatType = []):\n",
+    "    query = AnilistQuery()\n",
+    "    if score != -1:\n",
+    "        query.scoreGreaterThan(score)\n",
+    "    if popularity != -1:\n",
+    "        query.popularityGreaterThan(popularity)\n",
+    "    if epMin != -1:\n",
+    "        query.episodeBetween(epMin, epMax)\n",
+    "    if durationMin != -1:\n",
+    "        query.durationBetween(durationMin, durationMax)\n",
+    "    if len(formatType) > 0:\n",
+    "        query.formatIn(formatType)\n",
+    "    if len(source) > 0:\n",
+    "        query.sourceIn(source)\n",
+    "    return query"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Récupèration des données\n",
+    "\n",
+    "Les données sont récupérées sur l'API d'Anilist. Les données utilisées correspondent à la liste des anime complétés par l'utilisateur. Dans les données on retrouve notamment le score donné par l'utilisateur, le score moyen sur le site, le nombre d'episode et leur durée, la popularité, des tags, les genre, le format et la source."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>id</th>\n",
+       "      <th>title</th>\n",
+       "      <th>score</th>\n",
+       "      <th>popularity</th>\n",
+       "      <th>format</th>\n",
+       "      <th>episode</th>\n",
+       "      <th>duration</th>\n",
+       "      <th>source</th>\n",
+       "      <th>userScore</th>\n",
+       "      <th>tag1</th>\n",
+       "      <th>tag2</th>\n",
+       "      <th>tag3</th>\n",
+       "      <th>genre1</th>\n",
+       "      <th>genre2</th>\n",
+       "      <th>genre3</th>\n",
+       "      <th>genre4</th>\n",
+       "      <th>genre5</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>97636</td>\n",
+       "      <td>Akiba's Trip: The Animation</td>\n",
+       "      <td>62</td>\n",
+       "      <td>12475</td>\n",
+       "      <td>TV</td>\n",
+       "      <td>13</td>\n",
+       "      <td>24</td>\n",
+       "      <td>VIDEO_GAME</td>\n",
+       "      <td>80.0</td>\n",
+       "      <td>Super Power</td>\n",
+       "      <td>Otaku Culture</td>\n",
+       "      <td>Demons</td>\n",
+       "      <td>Action</td>\n",
+       "      <td>Ecchi</td>\n",
+       "      <td>Supernatural</td>\n",
+       "      <td>Comedy</td>\n",
+       "      <td>Fantasy</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>20602</td>\n",
+       "      <td>Amagi Brilliant Park</td>\n",
+       "      <td>74</td>\n",
+       "      <td>42303</td>\n",
+       "      <td>TV</td>\n",
+       "      <td>13</td>\n",
+       "      <td>24</td>\n",
+       "      <td>LIGHT_NOVEL</td>\n",
+       "      <td>70.0</td>\n",
+       "      <td>Ensemble Cast</td>\n",
+       "      <td>Magic</td>\n",
+       "      <td>Male Protagonist</td>\n",
+       "      <td>Comedy</td>\n",
+       "      <td>Romance</td>\n",
+       "      <td>Fantasy</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>21077</td>\n",
+       "      <td>Amagi Brilliant Park: Nonbirishiteiru Hima ga ...</td>\n",
+       "      <td>70</td>\n",
+       "      <td>8614</td>\n",
+       "      <td>OVA</td>\n",
+       "      <td>1</td>\n",
+       "      <td>24</td>\n",
+       "      <td>LIGHT_NOVEL</td>\n",
+       "      <td>70.0</td>\n",
+       "      <td>Ensemble Cast</td>\n",
+       "      <td>Male Protagonist</td>\n",
+       "      <td>Work</td>\n",
+       "      <td>Comedy</td>\n",
+       "      <td>Fantasy</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>6547</td>\n",
+       "      <td>Angel Beats!</td>\n",
+       "      <td>79</td>\n",
+       "      <td>88258</td>\n",
+       "      <td>TV</td>\n",
+       "      <td>13</td>\n",
+       "      <td>24</td>\n",
+       "      <td>ORIGINAL</td>\n",
+       "      <td>75.0</td>\n",
+       "      <td>Afterlife</td>\n",
+       "      <td>Tragedy</td>\n",
+       "      <td>School</td>\n",
+       "      <td>Action</td>\n",
+       "      <td>Comedy</td>\n",
+       "      <td>Drama</td>\n",
+       "      <td>Supernatural</td>\n",
+       "      <td>None</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>20755</td>\n",
+       "      <td>Ansatsu Kyoushitsu</td>\n",
+       "      <td>79</td>\n",
+       "      <td>72532</td>\n",
+       "      <td>TV</td>\n",
+       "      <td>22</td>\n",
+       "      <td>23</td>\n",
+       "      <td>MANGA</td>\n",
+       "      <td>90.0</td>\n",
+       "      <td>Assassins</td>\n",
+       "      <td>School</td>\n",
+       "      <td>Shounen</td>\n",
+       "      <td>Action</td>\n",
+       "      <td>Comedy</td>\n",
+       "      <td>Supernatural</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>...</th>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>97</th>\n",
+       "      <td>104252</td>\n",
+       "      <td>Maou-sama, Retry!</td>\n",
+       "      <td>59</td>\n",
+       "      <td>11116</td>\n",
+       "      <td>TV</td>\n",
+       "      <td>12</td>\n",
+       "      <td>24</td>\n",
+       "      <td>LIGHT_NOVEL</td>\n",
+       "      <td>70.0</td>\n",
+       "      <td>Isekai</td>\n",
+       "      <td>Anti-Hero</td>\n",
+       "      <td>Male Protagonist</td>\n",
+       "      <td>Action</td>\n",
+       "      <td>Adventure</td>\n",
+       "      <td>Fantasy</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>98</th>\n",
+       "      <td>107704</td>\n",
+       "      <td>Kawaki wo Ameku</td>\n",
+       "      <td>79</td>\n",
+       "      <td>1676</td>\n",
+       "      <td>MUSIC</td>\n",
+       "      <td>1</td>\n",
+       "      <td>4</td>\n",
+       "      <td>OTHER</td>\n",
+       "      <td>0.0</td>\n",
+       "      <td>Musical</td>\n",
+       "      <td>Female Protagonist</td>\n",
+       "      <td>Primarily Female Cast</td>\n",
+       "      <td>Music</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>99</th>\n",
+       "      <td>99425</td>\n",
+       "      <td>Promare</td>\n",
+       "      <td>83</td>\n",
+       "      <td>9545</td>\n",
+       "      <td>MOVIE</td>\n",
+       "      <td>1</td>\n",
+       "      <td>115</td>\n",
+       "      <td>ORIGINAL</td>\n",
+       "      <td>95.0</td>\n",
+       "      <td>Firefighters</td>\n",
+       "      <td>Robots</td>\n",
+       "      <td>CGI</td>\n",
+       "      <td>Action</td>\n",
+       "      <td>Mecha</td>\n",
+       "      <td>Comedy</td>\n",
+       "      <td>Sci-Fi</td>\n",
+       "      <td>None</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>100</th>\n",
+       "      <td>107226</td>\n",
+       "      <td>Dumbbell Nan Kilo Moteru?</td>\n",
+       "      <td>74</td>\n",
+       "      <td>20176</td>\n",
+       "      <td>TV</td>\n",
+       "      <td>12</td>\n",
+       "      <td>24</td>\n",
+       "      <td>MANGA</td>\n",
+       "      <td>80.0</td>\n",
+       "      <td>Fitness</td>\n",
+       "      <td>Educational</td>\n",
+       "      <td>Athletics</td>\n",
+       "      <td>Comedy</td>\n",
+       "      <td>Ecchi</td>\n",
+       "      <td>Sports</td>\n",
+       "      <td>Slice of Life</td>\n",
+       "      <td>None</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>101</th>\n",
+       "      <td>112381</td>\n",
+       "      <td>raison d'etre</td>\n",
+       "      <td>64</td>\n",
+       "      <td>208</td>\n",
+       "      <td>MUSIC</td>\n",
+       "      <td>1</td>\n",
+       "      <td>4</td>\n",
+       "      <td>ORIGINAL</td>\n",
+       "      <td>0.0</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "      <td>Music</td>\n",
+       "      <td>Action</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "      <td>None</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "<p>102 rows × 17 columns</p>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "         id                                              title  score  \\\n",
+       "0     97636                        Akiba's Trip: The Animation     62   \n",
+       "1     20602                               Amagi Brilliant Park     74   \n",
+       "2     21077  Amagi Brilliant Park: Nonbirishiteiru Hima ga ...     70   \n",
+       "3      6547                                       Angel Beats!     79   \n",
+       "4     20755                                 Ansatsu Kyoushitsu     79   \n",
+       "..      ...                                                ...    ...   \n",
+       "97   104252                                  Maou-sama, Retry!     59   \n",
+       "98   107704                                    Kawaki wo Ameku     79   \n",
+       "99    99425                                            Promare     83   \n",
+       "100  107226                          Dumbbell Nan Kilo Moteru?     74   \n",
+       "101  112381                                      raison d'etre     64   \n",
+       "\n",
+       "     popularity format  episode  duration       source  userScore  \\\n",
+       "0         12475     TV       13        24   VIDEO_GAME       80.0   \n",
+       "1         42303     TV       13        24  LIGHT_NOVEL       70.0   \n",
+       "2          8614    OVA        1        24  LIGHT_NOVEL       70.0   \n",
+       "3         88258     TV       13        24     ORIGINAL       75.0   \n",
+       "4         72532     TV       22        23        MANGA       90.0   \n",
+       "..          ...    ...      ...       ...          ...        ...   \n",
+       "97        11116     TV       12        24  LIGHT_NOVEL       70.0   \n",
+       "98         1676  MUSIC        1         4        OTHER        0.0   \n",
+       "99         9545  MOVIE        1       115     ORIGINAL       95.0   \n",
+       "100       20176     TV       12        24        MANGA       80.0   \n",
+       "101         208  MUSIC        1         4     ORIGINAL        0.0   \n",
+       "\n",
+       "              tag1                tag2                   tag3  genre1  \\\n",
+       "0      Super Power       Otaku Culture                 Demons  Action   \n",
+       "1    Ensemble Cast               Magic       Male Protagonist  Comedy   \n",
+       "2    Ensemble Cast    Male Protagonist                   Work  Comedy   \n",
+       "3        Afterlife             Tragedy                 School  Action   \n",
+       "4        Assassins              School                Shounen  Action   \n",
+       "..             ...                 ...                    ...     ...   \n",
+       "97          Isekai           Anti-Hero       Male Protagonist  Action   \n",
+       "98         Musical  Female Protagonist  Primarily Female Cast   Music   \n",
+       "99    Firefighters              Robots                    CGI  Action   \n",
+       "100        Fitness         Educational              Athletics  Comedy   \n",
+       "101           None                None                   None   Music   \n",
+       "\n",
+       "        genre2        genre3         genre4   genre5  \n",
+       "0        Ecchi  Supernatural         Comedy  Fantasy  \n",
+       "1      Romance       Fantasy           None     None  \n",
+       "2      Fantasy          None           None     None  \n",
+       "3       Comedy         Drama   Supernatural     None  \n",
+       "4       Comedy  Supernatural           None     None  \n",
+       "..         ...           ...            ...      ...  \n",
+       "97   Adventure       Fantasy           None     None  \n",
+       "98        None          None           None     None  \n",
+       "99       Mecha        Comedy         Sci-Fi     None  \n",
+       "100      Ecchi        Sports  Slice of Life     None  \n",
+       "101     Action          None           None     None  \n",
+       "\n",
+       "[102 rows x 17 columns]"
+      ]
+     },
+     "execution_count": 4,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "animelist = anilist.findUser(USER).getUserAnimeList()\n",
+    "completedList = animelist.toDataFrame()\n",
+    "completedList"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Pré-traitement\n",
+    "\n",
+    "Les données sont mis sous une forme plus adéquate pour le model (suppression des chaines de caractères) et une colonne like est ajoutée pour trier les anime en 2 class, ceux aimer par l'utilisateur (like = 1) et les autres (like = 0). On considère que tous anime avec un score égale ou supèrieur à 80 est aimé par l'utilisateur. De plus les colonnes titre, id et userScore sont supprimer car inutile pour l'apprentissage du model"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>score</th>\n",
+       "      <th>popularity</th>\n",
+       "      <th>episode</th>\n",
+       "      <th>duration</th>\n",
+       "      <th>tag_Super_Power</th>\n",
+       "      <th>tag_Ensemble_Cast</th>\n",
+       "      <th>tag_Afterlife</th>\n",
+       "      <th>tag_Assassins</th>\n",
+       "      <th>tag_Cute_Girls_Doing_Cute_Things</th>\n",
+       "      <th>tag_School</th>\n",
+       "      <th>...</th>\n",
+       "      <th>format_OVA</th>\n",
+       "      <th>format_SPECIAL</th>\n",
+       "      <th>format_TV</th>\n",
+       "      <th>source_LIGHT_NOVEL</th>\n",
+       "      <th>source_MANGA</th>\n",
+       "      <th>source_ORIGINAL</th>\n",
+       "      <th>source_OTHER</th>\n",
+       "      <th>source_VIDEO_GAME</th>\n",
+       "      <th>source_VISUAL_NOVEL</th>\n",
+       "      <th>like</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>62</td>\n",
+       "      <td>12475</td>\n",
+       "      <td>13</td>\n",
+       "      <td>24</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>74</td>\n",
+       "      <td>42303</td>\n",
+       "      <td>13</td>\n",
+       "      <td>24</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>70</td>\n",
+       "      <td>8614</td>\n",
+       "      <td>1</td>\n",
+       "      <td>24</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>79</td>\n",
+       "      <td>88258</td>\n",
+       "      <td>13</td>\n",
+       "      <td>24</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>79</td>\n",
+       "      <td>72532</td>\n",
+       "      <td>22</td>\n",
+       "      <td>23</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>...</th>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>97</th>\n",
+       "      <td>59</td>\n",
+       "      <td>11116</td>\n",
+       "      <td>12</td>\n",
+       "      <td>24</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>98</th>\n",
+       "      <td>79</td>\n",
+       "      <td>1676</td>\n",
+       "      <td>1</td>\n",
+       "      <td>4</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>99</th>\n",
+       "      <td>83</td>\n",
+       "      <td>9545</td>\n",
+       "      <td>1</td>\n",
+       "      <td>115</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>100</th>\n",
+       "      <td>74</td>\n",
+       "      <td>20176</td>\n",
+       "      <td>12</td>\n",
+       "      <td>24</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>101</th>\n",
+       "      <td>64</td>\n",
+       "      <td>208</td>\n",
+       "      <td>1</td>\n",
+       "      <td>4</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "<p>102 rows × 124 columns</p>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "     score  popularity  episode  duration  tag_Super_Power  tag_Ensemble_Cast  \\\n",
+       "0       62       12475       13        24                1                  0   \n",
+       "1       74       42303       13        24                0                  1   \n",
+       "2       70        8614        1        24                0                  1   \n",
+       "3       79       88258       13        24                0                  0   \n",
+       "4       79       72532       22        23                0                  0   \n",
+       "..     ...         ...      ...       ...              ...                ...   \n",
+       "97      59       11116       12        24                0                  0   \n",
+       "98      79        1676        1         4                0                  0   \n",
+       "99      83        9545        1       115                0                  0   \n",
+       "100     74       20176       12        24                0                  0   \n",
+       "101     64         208        1         4                0                  0   \n",
+       "\n",
+       "     tag_Afterlife  tag_Assassins  tag_Cute_Girls_Doing_Cute_Things  \\\n",
+       "0                0              0                                 0   \n",
+       "1                0              0                                 0   \n",
+       "2                0              0                                 0   \n",
+       "3                1              0                                 0   \n",
+       "4                0              1                                 0   \n",
+       "..             ...            ...                               ...   \n",
+       "97               0              0                                 0   \n",
+       "98               0              0                                 0   \n",
+       "99               0              0                                 0   \n",
+       "100              0              0                                 0   \n",
+       "101              0              0                                 0   \n",
+       "\n",
+       "     tag_School  ...  format_OVA  format_SPECIAL  format_TV  \\\n",
+       "0             0  ...           0               0          1   \n",
+       "1             0  ...           0               0          1   \n",
+       "2             0  ...           1               0          0   \n",
+       "3             1  ...           0               0          1   \n",
+       "4             1  ...           0               0          1   \n",
+       "..          ...  ...         ...             ...        ...   \n",
+       "97            0  ...           0               0          1   \n",
+       "98            0  ...           0               0          0   \n",
+       "99            0  ...           0               0          0   \n",
+       "100           0  ...           0               0          1   \n",
+       "101           0  ...           0               0          0   \n",
+       "\n",
+       "     source_LIGHT_NOVEL  source_MANGA  source_ORIGINAL  source_OTHER  \\\n",
+       "0                     0             0                0             0   \n",
+       "1                     1             0                0             0   \n",
+       "2                     1             0                0             0   \n",
+       "3                     0             0                1             0   \n",
+       "4                     0             1                0             0   \n",
+       "..                  ...           ...              ...           ...   \n",
+       "97                    1             0                0             0   \n",
+       "98                    0             0                0             1   \n",
+       "99                    0             0                1             0   \n",
+       "100                   0             1                0             0   \n",
+       "101                   0             0                1             0   \n",
+       "\n",
+       "     source_VIDEO_GAME  source_VISUAL_NOVEL  like  \n",
+       "0                    1                    0     1  \n",
+       "1                    0                    0     0  \n",
+       "2                    0                    0     0  \n",
+       "3                    0                    0     0  \n",
+       "4                    0                    0     1  \n",
+       "..                 ...                  ...   ...  \n",
+       "97                   0                    0     0  \n",
+       "98                   0                    0     0  \n",
+       "99                   0                    0     1  \n",
+       "100                  0                    0     1  \n",
+       "101                  0                    0     0  \n",
+       "\n",
+       "[102 rows x 124 columns]"
+      ]
+     },
+     "execution_count": 5,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "df = animelist.toDataFrame(dummies = True)\n",
+    "df['like'] = 0\n",
+    "df.loc[df.userScore >= 80, 'like'] = 1\n",
+    "df = df.drop(['id', 'title', 'userScore'], axis=1)\n",
+    "df"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Entrainement du model\n",
+    "\n",
+    "Les données sont découpées en un jeu d'apprentissage (80% des données) et un jeu de test pour verifier le bonne apprentissage (20% des données). On entraine donc le model puis on le test jusqu'a avoir un niveau de prédiction supèrieur à 70% de réussite"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Iteration 1 : 21 elements, 8 erreur(s), 61.9 % de precision\n",
+      "Iteration 2 : 21 elements, 4 erreur(s), 80.95 % de precision\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Separation x et y\n",
+    "y = df.like\n",
+    "x = df.drop('like', axis=1)\n",
+    "# Tant que la precision n'est pas suffisante\n",
+    "accuracy = 0\n",
+    "ite = 1\n",
+    "while accuracy < ACCURACYMIN:\n",
+    "    # Creation jeu d'apprentissage\n",
+    "    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2)\n",
+    "    # Apprentissage du model\n",
+    "    model.fit(x_train, y_train)\n",
+    "    # Test du model\n",
+    "    y_predict = model.predict(x_test)\n",
+    "    elt, error, accuracy = valid_data(y_predict, y_test)\n",
+    "    # Affichage resultat apprentissage du model sur cette iteration\n",
+    "    print('Iteration', ite, ':', elt, 'elements,', error, 'erreur(s),', round(accuracy, 2), '% de precision')\n",
+    "    ite += 1\n",
+    "    # Si trop d'iteration on coupe\n",
+    "    if ITERATIONMAX != -1 and ite > ITERATIONMAX:\n",
+    "        raise Exception('Imposible to reach ' + str(ACCURACYMIN) + '% of accuracy')"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Récupération des features importantes\n",
+    "\n",
+    "On récupére les features importantes pour qu'un anime plaise à l'utilisateur d'après le modèle"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>feature</th>\n",
+       "      <th>score</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>score</td>\n",
+       "      <td>0.12</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>popularity</td>\n",
+       "      <td>0.11</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>episode</td>\n",
+       "      <td>0.05</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>duration</td>\n",
+       "      <td>0.04</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>18</th>\n",
+       "      <td>tag_Magic</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>22</th>\n",
+       "      <td>tag_Video_Games</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>36</th>\n",
+       "      <td>tag_Female_Protagonist</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>49</th>\n",
+       "      <td>tag_Male_Protagonist</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>92</th>\n",
+       "      <td>genre_Action</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>93</th>\n",
+       "      <td>genre_Comedy</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>94</th>\n",
+       "      <td>genre_Slice_of_Life</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>96</th>\n",
+       "      <td>genre_Supernatural</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>99</th>\n",
+       "      <td>genre_Adventure</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>107</th>\n",
+       "      <td>genre_Psychological</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>117</th>\n",
+       "      <td>source_LIGHT_NOVEL</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>118</th>\n",
+       "      <td>source_MANGA</td>\n",
+       "      <td>0.02</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "                    feature  score\n",
+       "0                     score   0.12\n",
+       "1                popularity   0.11\n",
+       "2                   episode   0.05\n",
+       "3                  duration   0.04\n",
+       "18                tag_Magic   0.02\n",
+       "22          tag_Video_Games   0.02\n",
+       "36   tag_Female_Protagonist   0.02\n",
+       "49     tag_Male_Protagonist   0.02\n",
+       "92             genre_Action   0.02\n",
+       "93             genre_Comedy   0.02\n",
+       "94      genre_Slice_of_Life   0.02\n",
+       "96       genre_Supernatural   0.02\n",
+       "99          genre_Adventure   0.02\n",
+       "107     genre_Psychological   0.02\n",
+       "117      source_LIGHT_NOVEL   0.02\n",
+       "118            source_MANGA   0.02"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Recuperation de la liste des features et de leur score associé par le model\n",
+    "feature_list = list(x.columns)\n",
+    "importances = list(model.feature_importances_)\n",
+    "feature_importances = [(feature, round(importance, 2)) for feature, importance in zip(feature_list, importances)]\n",
+    "# Transformation en DataFrame et on ne garde que les features avec un score supèrieur à 0.02\n",
+    "fi = pd.DataFrame(feature_importances, columns=['feature', 'score'])\n",
+    "fi = fi[fi.score >= 0.02]\n",
+    "fi"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "On interprete cette liste de features et on extrait les infos interessantes pour pouvoir requeter l'API après et récupèrer das anime susceptible de plaire à l'utilisateur"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "numerical = ['score', 'popularity', 'episode', 'duration']\n",
+    "\n",
+    "# Extraction des features de type numerique\n",
+    "scoreMin = -1\n",
+    "popularityMin = -1\n",
+    "nbEpisodeMin = -1\n",
+    "nbEpisodeMax = -1\n",
+    "durationMin = -1\n",
+    "durationMax = -1\n",
+    "if 'score' in fi.feature.values:\n",
+    "    scoreMin = x.score.mean()\n",
+    "if 'popularity' in fi.feature.values:\n",
+    "    popularityMin = x.popularity.mean()\n",
+    "if 'episode' in fi.feature.values:\n",
+    "    mean = x.episode.mean()\n",
+    "    nbEpisodeMin = mean - 5\n",
+    "    nbEpisodeMax = mean + 5\n",
+    "if 'duration' in fi.feature.values:\n",
+    "    mean = x.duration.mean()\n",
+    "    durationMin = mean - 10\n",
+    "    durationMax = mean + 10\n",
+    "\n",
+    "# Extraction des feature de type string\n",
+    "formatIn = []\n",
+    "sourceIn = []\n",
+    "genreIn = []\n",
+    "tagIn = []\n",
+    "for tpl in fi.itertuples():\n",
+    "    # Recuperation feature et passage feature numerique qui ont un traitement particulier\n",
+    "    feature = tpl[1]\n",
+    "    if feature in numerical:\n",
+    "        continue\n",
+    "    # Recuperation du nom du type de la feature et de sa valeur\n",
+    "    name = feature.split('_')\n",
+    "    if(len(name) > 2):\n",
+    "        feature = name[1] + '_' + name[2]\n",
+    "    else:\n",
+    "        feature = name[1]\n",
+    "    name = name[0]\n",
+    "    # Traitement\n",
+    "    if name == 'format':\n",
+    "        formatIn.append(feature)\n",
+    "    elif name == 'source':\n",
+    "        sourceIn.append(feature)\n",
+    "    elif name == 'genre':\n",
+    "        genreIn.append(feature)\n",
+    "    elif name == 'tag':\n",
+    "        tagIn.append(feature)\n",
+    "    else:\n",
+    "        raise ValueError(\"Unknown feature: \" + name)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Récupèration d'anime en fonction des features importantes\n",
+    "\n",
+    "On requete l'api pour récupèrer des animes qui correspondent à nos features, puis ont les verifie les features qui ne peuvent pas être inclus dans la requete à l'api"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>id</th>\n",
+       "      <th>title</th>\n",
+       "      <th>score</th>\n",
+       "      <th>popularity</th>\n",
+       "      <th>episode</th>\n",
+       "      <th>duration</th>\n",
+       "      <th>tag_Super_Power</th>\n",
+       "      <th>tag_Ensemble_Cast</th>\n",
+       "      <th>tag_Afterlife</th>\n",
+       "      <th>tag_Assassins</th>\n",
+       "      <th>...</th>\n",
+       "      <th>format_ONA</th>\n",
+       "      <th>format_OVA</th>\n",
+       "      <th>format_SPECIAL</th>\n",
+       "      <th>format_TV</th>\n",
+       "      <th>source_LIGHT_NOVEL</th>\n",
+       "      <th>source_MANGA</th>\n",
+       "      <th>source_ORIGINAL</th>\n",
+       "      <th>source_OTHER</th>\n",
+       "      <th>source_VIDEO_GAME</th>\n",
+       "      <th>source_VISUAL_NOVEL</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>245</td>\n",
+       "      <td>Great Teacher Onizuka</td>\n",
+       "      <td>84</td>\n",
+       "      <td>31604</td>\n",
+       "      <td>43.0</td>\n",
+       "      <td>25</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>97922</td>\n",
+       "      <td>Inuyashiki</td>\n",
+       "      <td>73</td>\n",
+       "      <td>31631</td>\n",
+       "      <td>11.0</td>\n",
+       "      <td>23</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>10162</td>\n",
+       "      <td>Usagi Drop</td>\n",
+       "      <td>83</td>\n",
+       "      <td>31883</td>\n",
+       "      <td>11.0</td>\n",
+       "      <td>22</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>17549</td>\n",
+       "      <td>Non Non Biyori</td>\n",
+       "      <td>78</td>\n",
+       "      <td>31976</td>\n",
+       "      <td>12.0</td>\n",
+       "      <td>24</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>14967</td>\n",
+       "      <td>Boku wa Tomodachi ga Sukunai Next</td>\n",
+       "      <td>72</td>\n",
+       "      <td>31992</td>\n",
+       "      <td>12.0</td>\n",
+       "      <td>24</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>...</th>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>45</th>\n",
+       "      <td>14741</td>\n",
+       "      <td>Chuunibyou demo Koi ga Shitai!</td>\n",
+       "      <td>76</td>\n",
+       "      <td>67649</td>\n",
+       "      <td>12.0</td>\n",
+       "      <td>24</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>46</th>\n",
+       "      <td>20920</td>\n",
+       "      <td>Dungeon ni Deai wo Motomeru no wa Machigatteir...</td>\n",
+       "      <td>74</td>\n",
+       "      <td>68372</td>\n",
+       "      <td>13.0</td>\n",
+       "      <td>24</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>47</th>\n",
+       "      <td>6746</td>\n",
+       "      <td>Durarara!!</td>\n",
+       "      <td>80</td>\n",
+       "      <td>68550</td>\n",
+       "      <td>24.0</td>\n",
+       "      <td>24</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>48</th>\n",
+       "      <td>10087</td>\n",
+       "      <td>Fate/Zero</td>\n",
+       "      <td>83</td>\n",
+       "      <td>70510</td>\n",
+       "      <td>13.0</td>\n",
+       "      <td>26</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>49</th>\n",
+       "      <td>20623</td>\n",
+       "      <td>Kiseijuu: Sei no Kakuritsu</td>\n",
+       "      <td>82</td>\n",
+       "      <td>71072</td>\n",
+       "      <td>24.0</td>\n",
+       "      <td>24</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>...</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>1</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "      <td>0</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "<p>200 rows × 125 columns</p>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "       id                                              title  score  \\\n",
+       "0     245                              Great Teacher Onizuka     84   \n",
+       "1   97922                                         Inuyashiki     73   \n",
+       "2   10162                                         Usagi Drop     83   \n",
+       "3   17549                                     Non Non Biyori     78   \n",
+       "4   14967                  Boku wa Tomodachi ga Sukunai Next     72   \n",
+       "..    ...                                                ...    ...   \n",
+       "45  14741                     Chuunibyou demo Koi ga Shitai!     76   \n",
+       "46  20920  Dungeon ni Deai wo Motomeru no wa Machigatteir...     74   \n",
+       "47   6746                                         Durarara!!     80   \n",
+       "48  10087                                          Fate/Zero     83   \n",
+       "49  20623                         Kiseijuu: Sei no Kakuritsu     82   \n",
+       "\n",
+       "    popularity  episode  duration  tag_Super_Power  tag_Ensemble_Cast  \\\n",
+       "0        31604     43.0        25                0                  0   \n",
+       "1        31631     11.0        23                0                  0   \n",
+       "2        31883     11.0        22                0                  0   \n",
+       "3        31976     12.0        24                0                  0   \n",
+       "4        31992     12.0        24                0                  0   \n",
+       "..         ...      ...       ...              ...                ...   \n",
+       "45       67649     12.0        24                0                  0   \n",
+       "46       68372     13.0        24                0                  0   \n",
+       "47       68550     24.0        24                0                  1   \n",
+       "48       70510     13.0        26                0                  1   \n",
+       "49       71072     24.0        24                0                  0   \n",
+       "\n",
+       "    tag_Afterlife  tag_Assassins  ...  format_ONA  format_OVA  format_SPECIAL  \\\n",
+       "0               0              0  ...           0           0               0   \n",
+       "1               0              0  ...           0           0               0   \n",
+       "2               0              0  ...           0           0               0   \n",
+       "3               0              0  ...           0           0               0   \n",
+       "4               0              0  ...           0           0               0   \n",
+       "..            ...            ...  ...         ...         ...             ...   \n",
+       "45              0              0  ...           0           0               0   \n",
+       "46              0              0  ...           0           0               0   \n",
+       "47              0              0  ...           0           0               0   \n",
+       "48              0              0  ...           0           0               0   \n",
+       "49              0              0  ...           0           0               0   \n",
+       "\n",
+       "    format_TV  source_LIGHT_NOVEL  source_MANGA  source_ORIGINAL  \\\n",
+       "0           1                   0             1                0   \n",
+       "1           1                   0             1                0   \n",
+       "2           1                   0             1                0   \n",
+       "3           1                   0             1                0   \n",
+       "4           1                   1             0                0   \n",
+       "..        ...                 ...           ...              ...   \n",
+       "45          1                   1             0                0   \n",
+       "46          1                   1             0                0   \n",
+       "47          1                   1             0                0   \n",
+       "48          1                   1             0                0   \n",
+       "49          1                   0             1                0   \n",
+       "\n",
+       "    source_OTHER  source_VIDEO_GAME  source_VISUAL_NOVEL  \n",
+       "0              0                  0                    0  \n",
+       "1              0                  0                    0  \n",
+       "2              0                  0                    0  \n",
+       "3              0                  0                    0  \n",
+       "4              0                  0                    0  \n",
+       "..           ...                ...                  ...  \n",
+       "45             0                  0                    0  \n",
+       "46             0                  0                    0  \n",
+       "47             0                  0                    0  \n",
+       "48             0                  0                    0  \n",
+       "49             0                  0                    0  \n",
+       "\n",
+       "[200 rows x 125 columns]"
+      ]
+     },
+     "execution_count": 9,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Creation de la query\n",
+    "query = make_query(score=scoreMin, popularity=popularityMin, source=sourceIn, formatType=formatIn)\n",
+    "# Creation variable pour receptionner les recommendations\n",
+    "col = x.columns.values\n",
+    "col = np.append(['id', 'title'], col)\n",
+    "finalList = pd.DataFrame(columns = col)\n",
+    "# On parcours plusieurs page \n",
+    "for searchList in anilist.iterateAnimeListFetch(query, NBITERATION, NBANIME):\n",
+    "    # Si il n'y a plus de données\n",
+    "    if len(searchList.data) < 1:\n",
+    "        break\n",
+    "    # Transformation en DataFrame utilisable\n",
+    "    searchList = identical_features(x, searchList.toDataFrame(dummies = True), ['id', 'title'])\n",
+    "    # Verification des features nom presentes dans la requete\n",
+    "    valid = []\n",
+    "    for row in searchList.iterrows():\n",
+    "        isValid = False\n",
+    "        row = pd.Series(row[1])\n",
+    "        for genre in genreIn:\n",
+    "            if ('genre_' + genre) in row.index:\n",
+    "                isValid = True\n",
+    "                break\n",
+    "        if not isValid:\n",
+    "            for tag in tagIn:\n",
+    "                if ('tag_' + genre) in row.index:\n",
+    "                    isValid = True\n",
+    "                    break\n",
+    "        if isValid:\n",
+    "            valid.append(row)\n",
+    "    # Ajoute si tous est ok\n",
+    "    if len(valid) > 0:\n",
+    "        finalList = finalList.append(pd.DataFrame(valid), sort=False)\n",
+    "\n",
+    "# Met en forme la liste final et l'affiche\n",
+    "finalList = identical_features(x, finalList.fillna(0), ['id', 'title'])\n",
+    "finalList"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Interrogation du model\n",
+    "\n",
+    "On interroge le model pour savoir si les animes récupérés plairont ou non à l'utiliateur"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>id</th>\n",
+       "      <th>title</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>20652</td>\n",
+       "      <td>Durarara!!x2 Shou</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>8425</td>\n",
+       "      <td>Gosick</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>20593</td>\n",
+       "      <td>Hanamonogatari</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>7674</td>\n",
+       "      <td>Bakuman.</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>99726</td>\n",
+       "      <td>Net-juu no Susume</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>...</th>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>97</th>\n",
+       "      <td>20832</td>\n",
+       "      <td>Overlord</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>98</th>\n",
+       "      <td>14813</td>\n",
+       "      <td>Yahari Ore no Seishun Love Comedy wa Machigatt...</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>99</th>\n",
+       "      <td>20920</td>\n",
+       "      <td>Dungeon ni Deai wo Motomeru no wa Machigatteir...</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>100</th>\n",
+       "      <td>6746</td>\n",
+       "      <td>Durarara!!</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>101</th>\n",
+       "      <td>10087</td>\n",
+       "      <td>Fate/Zero</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "<p>82 rows × 2 columns</p>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "        id                                              title\n",
+       "0    20652                                  Durarara!!x2 Shou\n",
+       "1     8425                                             Gosick\n",
+       "2    20593                                     Hanamonogatari\n",
+       "3     7674                                           Bakuman.\n",
+       "4    99726                                  Net-juu no Susume\n",
+       "..     ...                                                ...\n",
+       "97   20832                                           Overlord\n",
+       "98   14813  Yahari Ore no Seishun Love Comedy wa Machigatt...\n",
+       "99   20920  Dungeon ni Deai wo Motomeru no wa Machigatteir...\n",
+       "100   6746                                         Durarara!!\n",
+       "101  10087                                          Fate/Zero\n",
+       "\n",
+       "[82 rows x 2 columns]"
+      ]
+     },
+     "execution_count": 10,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Liste des recommendations\n",
+    "recommendation = []\n",
+    "#On parcours chaque entrées de la liste fina\n",
+    "for row in finalList.iterrows():\n",
+    "    row = pd.Series(row[1])\n",
+    "    # Récupéréation id et titre puis suppr (elles sot inutiles au model)\n",
+    "    info = {'id': row.id, 'title': row.title}\n",
+    "    row = row.drop(['id', 'title'])\n",
+    "    # Prediction\n",
+    "    if model.predict([row])[0] == 1:\n",
+    "        recommendation.append(info)\n",
+    "\n",
+    "# Transformation en DataFrame et suppression doublon\n",
+    "recommendation = pd.DataFrame(recommendation)\n",
+    "recommendation = recommendation.drop_duplicates()\n",
+    "recommendation"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Affichage resultat\n",
+    "\n",
+    "On supprime tous les anime déjà vue par l'utilisateur et on affiche la liste "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "69 recommendation(s)\n",
+      "  - Akatsuki no Yona\n",
+      "  - Akira\n",
+      "  - Baccano!\n",
+      "  - Bakuman.\n",
+      "  - Black Lagoon\n",
+      "  - Bleach\n",
+      "  - Dororo\n",
+      "  - Dr. STONE\n",
+      "  - Dragon Ball\n",
+      "  - Dragon Ball Z\n",
+      "  - Dungeon ni Deai wo Motomeru no wa Machigatteiru Darou ka\n",
+      "  - Dungeon ni Deai wo Motomeru no wa Machigatteiru Darou ka II\n",
+      "  - Durarara!!\n",
+      "  - Durarara!!x2 Shou\n",
+      "  - Enen no Shouboutai\n",
+      "  - Fairy Tail\n",
+      "  - Gintama\n",
+      "  - Gosick\n",
+      "  - Hagane no Renkinjutsushi\n",
+      "  - Hai to Gensou no Grimgar\n",
+      "  - Haikyuu!!\n",
+      "  - Haikyuu!! 2\n",
+      "  - Haikyuu!!: Karasuno Koukou VS Shiratorizawa Gakuen Koukou\n",
+      "  - Hanamonogatari\n",
+      "  - Hataraku Saibou\n",
+      "  - Hotarubi no Mori e\n",
+      "  - JoJo no Kimyou na Bouken\n",
+      "  - JoJo no Kimyou na Bouken: Diamond wa Kudakenai\n",
+      "  - JoJo no Kimyou na Bouken: Stardust Crusaders\n",
+      "  - JoJo no Kimyou na Bouken: Stardust Crusaders - Egypt-hen\n",
+      "  - Kaichou wa Maid-sama!\n",
+      "  - Katanagatari\n",
+      "  - Kekkai Sensen\n",
+      "  - Kimetsu no Yaiba\n",
+      "  - Kokoro Connect\n",
+      "  - Kono Subarashii Sekai ni Shukufuku wo! 2\n",
+      "  - Koukaku Kidoutai\n",
+      "  - Kuroko no Basket\n",
+      "  - Kyoukai no Kanata\n",
+      "  - Log Horizon\n",
+      "  - Log Horizon 2\n",
+      "  - Made in Abyss\n",
+      "  - Magi: The Kingdom of Magic\n",
+      "  - Magi: The Labyrinth of Magic\n",
+      "  - Mahouka Koukou no Rettousei\n",
+      "  - Nanatsu no Taizai: Imashime no Fukkatsu\n",
+      "  - Naruto: Shippuuden\n",
+      "  - Nekomonogatari (Kuro)\n",
+      "  - Net-juu no Susume\n",
+      "  - Nisekoi\n",
+      "  - Nisemonogatari\n",
+      "  - No Game No Life -Zero-\n",
+      "  - Noragami Aragoto\n",
+      "  - One Piece\n",
+      "  - Ookami to Koushinryou\n",
+      "  - Seishun Buta Yarou wa Bunny Girl-senpai no Yume wo Minai\n",
+      "  - Shingeki no Kyojin 3\n",
+      "  - Shingeki no Kyojin 3 Part 2\n",
+      "  - Soul Eater\n",
+      "  - Suzumiya Haruhi no Shoushitsu\n",
+      "  - Suzumiya Haruhi no Yuuutsu\n",
+      "  - Toaru Majutsu no Index\n",
+      "  - Toki wo Kakeru Shoujo\n",
+      "  - Vinland Saga\n",
+      "  - Violet Evergarden\n",
+      "  - Wotaku ni Koi wa Muzukashii\n",
+      "  - Yahari Ore no Seishun Love Comedy wa Machigatteiru.\n",
+      "  - Youjo Senki\n",
+      "  - orange\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Récupèration uniquement des anime nom present dans la liste\n",
+    "result = []\n",
+    "for row in recommendation.iterrows():\n",
+    "    row = pd.Series(row[1])\n",
+    "    if completedList[completedList.id == row.id].empty:\n",
+    "        result.append(row.title)\n",
+    "\n",
+    "# Affichage\n",
+    "result.sort()\n",
+    "print(len(result), 'recommendation(s)')\n",
+    "for anime in result:\n",
+    "    print('  -', anime)"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.6.6"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 1
+}