Aller au contenu

🐻 Meilleurs films selon IMDB⚓︎

À ce stade nous savons :

  • ouvrir un fichier csv à l'aide de Python,
  • lire son contenu dans une liste (de listes ou de dictionnaires),
  • typer les données,
  • effectuer des requêtes sur ces données à l'aide de listes en compréhension.

Présentation des données et import⚓︎

Nous allons pousser notre étude un peu plus loin lors de l'étude du fichier films.csv1. Ce fichier reprend les 517 films les mieux notés sur le site IMDB.

Les descripteurs proposés sont :

Descripteur Indice Type Python Contenu
Ranking 0 int rang du film dans le classement
Name 1 str nom du film
Year 2 int année de production
Minutes 3 int durée (en minutes)
Genres 4 str genres associés (voir remarque)
Rating 5 float note moyenne(sur 10)
Votes 6 int nombre de votes
Gross 7 float revenus générés (en M$)

Les genres

Chaque film est associé à au moins un genre, certains à trois genres...

Dans le cas où plusieurs genres sont cités, ceux-ci sont séparés par des virgules.

Voici les premières lignes du fichier :

📑 Données CSV
Ranking;Name;Year;Minutes;Genres;Rating;Votes;Gross
1;Citizen Kane;1941;119;Drama, Mystery;8.3;442770;1.59
2;The Godfather;1972;175;Crime, Drama;9.2;1849989;134.97
3;The Wizard of Oz;1939;102;Adventure, Family, Fantasy;8.1;400883;2.08

On importe les données sous la forme d'une liste de dictionnaires. Le code est le suivant :

🐍 Script Python
import csv

films = []
with open("films.csv", "r", encoding="utf-8") as fichier:
    lecteur = csv.DictReader(fichier, delimiter=";")
    for entree in lecteur:
        entree["Ranking"] = int(entree["Ranking"])
        entree["Year"] = int(entree["Year"])
        entree["Minutes"] = int(entree["Minutes"])
        entree["Rating"] = float(entree["Rating"])
        entree["Votes"] = int(entree["Votes"])
        entree["Gross"] = float(entree["Gross"])
        films.append(entree)

Import réalisé !

Dans toute la suite du TP, la liste films telle qu'importée ci-dessus sera accessible dans chaque éditeur.

Votes par genre⚓︎

Le fichier compte 25 films dont l'un des Genres est Family et 26 avec le genre Horror. On précise qu'aucun film ne possède ces deux genres.

Parmi ces deux genres, quel est celui qui a reçu le plus de votes au total (en additionnant les votes reçus par chaque film) ?

Comparaison de genres

Compléter le script ci-dessous afin de compter :

  • le nombre total de votes qu'ont reçus les films dont l'un des genres est Family (utiliser la variable total_family),

  • le nombre total de votes qu'ont reçus les films dont l'un des genres est Horror (utiliser la variable total_horror).

###
# Tests aléatoiresbksl-nlattendupy-undfamily = 8384520bksl-nlattendupy-undhorror = 7138023bksl-nlbksl-nlassert totalpy-undfamily == attendupy-undfamily, "Erreur pour le genre 'Family'"bksl-nlassert totalpy-undhorror == attendupy-undhorror, "Erreur pour le genre 'Horror'"bksl-nlbksl-nl 5/5
# --- HDR ---#bksl-nlurlpy-undfichier = "films.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlfrom js import fetchbksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlimport csvbksl-nlbksl-nlfilms = []bksl-nlwith open("films.csv", "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=";")bksl-nl for entree in lecteur:bksl-nl entree["Ranking"] = int(entree["Ranking"])bksl-nl entree["Year"] = int(entree["Year"])bksl-nl entree["Minutes"] = int(entree["Minutes"])bksl-nl entree["Rating"] = float(entree["Rating"])bksl-nl entree["Votes"] = int(entree["Votes"])bksl-nl entree["Gross"] = float(entree["Gross"])bksl-nl films.append(entree)bksl-nl# --- HDR ---#bksl-nltotalpy-undfamily = 0bksl-nltotalpy-undhorror = 0bksl-nlbksl-nl...bksl-nl bksl-nlprint(f"{totalpy-undfamily = }")bksl-nlprint(f"{totalpy-undhorror = }")bksl-nlprint(f"{(totalpy-undfamily > totalpy-undhorror) = }")bksl-nltotalpy-undfamily = 0bksl-nltotalpy-undhorror = 0bksl-nlbksl-nlfor entree in films:bksl-nl if "Family" in entree["Genres"]:bksl-nl totalpy-undfamily += entree["Votes"]bksl-nl elif "Horror" in entree["Genres"]:bksl-nl totalpy-undhorror += entree["Votes"]bksl-nl

A

On profite ici du fait que les deux genres sont incompatibles (dans cette liste de films a minima).

Si l'on souhaite comparer deux genres compatibles, on doit utiliser deux if et pas un if ... elif. C'est le cas par exemple avec les genres Adventure et Family

🐍 Script Python
total_adventure = 0
total_family = 0

for entree in films:
    if "Adventure" in entree["Genres"]:
        total_adventure += entree["Votes"]
    if "Family" in entree["Genres"]:  # (1)
        total_family += entree["Votes"]
  1. Un second if au lieu d'un elif

Z

Projection(s)⚓︎

Comment faire pour n'obtenir que les noms des films cités dans le fichier ?

On peut procéder ainsi :

🐍 Console Python
>>> [entree["Name"] for entree in films]
['Citizen Kane', 'The Godfather', 'The Wizard of Oz', 'The Shawshank Redemption', 'Pulp Fiction', ...]

Afin de généraliser le procédé, on souhaite écrire une fonction projection qui :

  • prend en argument la liste de dictionnaires à manipuler ainsi que le nom d'un descripteur,

  • renvoie la liste ne contenant que les valeurs associées à ce descripteur.

La fonction projection

Compléter le code ci-dessous en saisissant la fonction projection telle que décrite.

Attention, les résultats doivent être dans le même ordre que dans la liste initiale.

###
# Tests publicsbksl-nlassert projection(films, "Ranking")[4] == 5, "Erreur sur la projection de 'Ranking'"bksl-nlassert projection(films, "Name")[4] == "Pulp Fiction", "Erreur sur la projection de 'Name'"bksl-nlassert projection(films, "Year")[4] == 1994, "Erreur sur la projection de 'Year'"bksl-nlbksl-nl# Tests aléatoiresbksl-nldef projectionpy-undcorr(donnees, descripteur):bksl-nl return [entree[descripteur] for entree in donnees]bksl-nlbksl-nlbksl-nlfor descripteur in films[0]:bksl-nl attendu = projectionpy-undcorr(films, descripteur)bksl-nl assert projection(films, descripteur) == attendu, f"Erreur sur la projection de '{descripteur}'"bksl-nlbksl-nlneveux = [bksl-nl {1: "riri", 2: "fifi", 3: "loulou"},bksl-nl {1: "rara", 2: "fafa", 3: "laulau"},bksl-nl]bksl-nlassert projection(neveux, 1) == ["riri", "rara"], "Erreur dans un test secret"bksl-nlassert projection(neveux, 2) == ["fifi", "fafa"], "Erreur dans un test secret"bksl-nlbksl-nl 5/5
# --- HDR ---#bksl-nlurlpy-undfichier = "films.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlfrom js import fetchbksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlimport csvbksl-nlbksl-nlfilms = []bksl-nlwith open("films.csv", "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=";")bksl-nl for entree in lecteur:bksl-nl entree["Ranking"] = int(entree["Ranking"])bksl-nl entree["Year"] = int(entree["Year"])bksl-nl entree["Minutes"] = int(entree["Minutes"])bksl-nl entree["Rating"] = float(entree["Rating"])bksl-nl entree["Votes"] = int(entree["Votes"])bksl-nl entree["Gross"] = float(entree["Gross"])bksl-nl films.append(entree)bksl-nl# --- HDR ---#bksl-nldef projection(donnees, descripteur):bksl-nl """Renvoie la liste des valeurs de ce descripteur"""bksl-nl passbksl-nlbksl-nlbksl-nlassert projection(films, "Ranking")[4] == 5, "Erreur sur la projection de 'Ranking'"bksl-nlassert projection(films, "Name")[4] == "Pulp Fiction", "Erreur sur la projection de 'Name'"bksl-nlassert projection(films, "Year")[4] == 1994, "Erreur sur la projection de 'Year'"bksl-nlbksl-nldef projection(donnees, descripteur):bksl-nl """Renvoie la liste des valeurs de ce descripteur"""bksl-nl return [entree[descripteur] for entree in donnees]bksl-nl bksl-nlbksl-nl

A

Z

La fonction projection_multiple

On souhaite désormais récupérer les données associées à plusieurs descripteurs : la fonction projection_multiple prend en argument la liste des données et un tuple contenant les descripteurs à conserver.

Par exemple projection_multiple(films, ("Name", "Year", "Rating")) renverra la liste des tuples formés du nom, de l'année de production et de la note de de chaque film.

🐍 Console Python
>>> projection_multiple(films, ("Name", "Year", "Rating"))
[('Citizen Kane', 1941, 8.3), ('The Godfather', 1972, 9.2), ('The Wizard of Oz', 1939, 8.1), ...]
Aide

Nous avons vu comment créer des listes en compréhension. Il est aussi possible de créer des tuples en compréhension :

🐍 Console Python
>>> tuple(2 * k for k in range(3))
(0, 2, 4)
>>> [tuple(k * lettre for k in range(3)) for lettre in "ab"]
[('', 'a', 'aa'), ('', 'b', 'bb')]

Compléter le code ci-dessous en saisissant la fonction projection_multiple telle que décrite.

###
# Testsbksl-nlassert projectionpy-undmultiple(films, ("Name", "Year", "Rating"))[0] == ("Citizen Kane", 1941, 8.3), "Erreur"bksl-nlbksl-nlbksl-nl# Tests supplémentairesbksl-nlfrom random import sample, randrangebksl-nlbksl-nlbksl-nldef projectionpy-undmultiplepy-undcorr(donnees, descripteurs):bksl-nl return [tuple(entree[d] for d in descripteurs) for entree in donnees]bksl-nlbksl-nlbksl-nlcles = list(films[0].keys())bksl-nlfor py-und in range(5):bksl-nl descripteurs = sample(cles, randrange(1, len(cles)))bksl-nl attendu = projectionpy-undmultiplepy-undcorr(films, descripteurs)bksl-nl assert projectionpy-undmultiple(films, descripteurs) == attendu, f"Erreur sur la projection de '{descripteurs}'"bksl-nlbksl-nl 5/5
# --- HDR ---#bksl-nlurlpy-undfichier = "films.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlfrom js import fetchbksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlimport csvbksl-nlbksl-nlfilms = []bksl-nlwith open("films.csv", "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=";")bksl-nl for entree in lecteur:bksl-nl entree["Ranking"] = int(entree["Ranking"])bksl-nl entree["Year"] = int(entree["Year"])bksl-nl entree["Minutes"] = int(entree["Minutes"])bksl-nl entree["Rating"] = float(entree["Rating"])bksl-nl entree["Votes"] = int(entree["Votes"])bksl-nl entree["Gross"] = float(entree["Gross"])bksl-nl films.append(entree)bksl-nl# --- HDR ---#bksl-nldef projectionpy-undmultiple(donnees, descripteurs):bksl-nl """Renvoie les valeurs de ces descripteurs"""bksl-nl passbksl-nlbksl-nlbksl-nlassert projectionpy-undmultiple(films, ("Name", "Year", "Rating"))[0] == ("Citizen Kane", 1941, 8.3), "Erreur"bksl-nlbksl-nldef projectionpy-undmultiple(donnees, descripteurs):bksl-nl """Renvoie les valeurs de ces descripteurs"""bksl-nl return [tuple(entree[d] for d in descripteurs) for entree in donnees]bksl-nl

A

Z

Sommes et moyennes⚓︎

Quel est le montant total rapporté par l'ensemble de ces films ? Et le montant moyen ? Pour le savoir il faut dans un premier temps additionner les revenus générés.

Écrivons une fonction pour cela.

La fonction somme

Compléter le code ci-dessous en saisissant la fonction somme qui :

  • prend en argument la liste de dictionnaires à manipuler ainsi que le nom d'un descripteur,

  • renvoie la somme de toutes les valeurs associées à ce descripteur.

Remarque

Vous observerez que l'on ne teste pas la stricte égalité des résultats car les valeurs manipulées sont des flottants et qu'il y a des erreurs d'arrondis.

###
# Tests publicsbksl-nlassert abs(somme(films, "Gross") - 33072.07) < 10py-strpy-str-6, "Erreur sur la somme de 'Gross'"bksl-nlbksl-nl# Tests aléatoiresbksl-nldef sommepy-undcorr(donnees, descripteur):bksl-nl return sum([entree[descripteur] for entree in donnees])bksl-nlbksl-nlbksl-nlfor descripteur in ["Year", "Rating", "Votes", "Minutes", "Gross"]:bksl-nl attendu = sommepy-undcorr(films, descripteur)bksl-nl assert abs(somme(films, descripteur) - attendu) < 10py-strpy-str-3, f"Erreur sur la somme de '{descripteur}'"bksl-nlbksl-nlentiers = [bksl-nl {1: 0, 2: 1, 3: 5},bksl-nl {1: 0, 2: 1, 3: 5},bksl-nl]bksl-nlassert somme(entiers, 1) == 0, "Erreur dans un test secret"bksl-nlassert somme(entiers, 2) == 2, "Erreur dans un test secret"bksl-nlassert somme(entiers, 3) == 10, "Erreur dans un test secret"bksl-nlbksl-nl 5/5
# --- HDR ---#bksl-nlurlpy-undfichier = "films.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlfrom js import fetchbksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlimport csvbksl-nlbksl-nlfilms = []bksl-nlwith open("films.csv", "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=";")bksl-nl for entree in lecteur:bksl-nl entree["Ranking"] = int(entree["Ranking"])bksl-nl entree["Year"] = int(entree["Year"])bksl-nl entree["Minutes"] = int(entree["Minutes"])bksl-nl entree["Rating"] = float(entree["Rating"])bksl-nl entree["Votes"] = int(entree["Votes"])bksl-nl entree["Gross"] = float(entree["Gross"])bksl-nl films.append(entree)bksl-nl# --- HDR ---#bksl-nldef somme(donnees, descripteur):bksl-nl """Renvoie la somme des valeurs de ce descripteur"""bksl-nl passbksl-nlbksl-nlbksl-nlassert abs(somme(films, "Gross") - 33072.07) < 10py-strpy-str-6, "Erreur sur la somme de 'Gross'"bksl-nlbksl-nldef somme(donnees, descripteur):bksl-nl """Renvoie la somme des valeurs de ce descripteur"""bksl-nl total = 0bksl-nl for entree in donnees:bksl-nl total += entree[descripteur]bksl-nl return totalbksl-nlbksl-nl

A

Il existe plusieurs solutions alternatives :

  • avec la fonction projection :
🐍 Script Python
def somme(donnees, descripteur):
    """Renvoie la somme des valeurs de ce descripteur"""
    total = 0
    for valeur in projection(donnees, descripteur):
        total += valeur
    return total
  • avec la fonction sum de Python :
🐍 Script Python
def somme(donnees, descripteur):
    """Renvoie la somme des valeurs de ce descripteur"""
    return sum([entree[descripteur] for entree in donnees])
  • avec la fonction projection et la fonction sum :
🐍 Script Python
def somme(donnees, descripteur):
    """Renvoie la somme des valeurs de ce descripteur"""
    return sum(projection(donnees, descripteur))

Z

Il est désormais possible de calculer la moyenne des valeurs d'un descripteurs. Là encore, écrivons une fonction pour cela.

La fonction moyenne

Compléter le code ci-dessous en saisissant la fonction moyenne qui :

  • prend en argument la liste de dictionnaires à manipuler ainsi que le nom d'un descripteur,

  • renvoie la moyenne de toutes les valeurs associées à ce descripteur.

Remarque

Une version de la fonction somme précédente est fournie. Vous pouvez l'utiliser dans votre code.

###
# Tests publicsbksl-nlassert abs(moyenne(films, "Gross") - 63.97) < 10py-strpy-str-3, "Erreur sur la moyenne de 'Gross'"bksl-nlbksl-nl# Tests aléatoiresbksl-nldef moyennepy-undcorr(donnees, descripteur):bksl-nl return sum([entree[descripteur] for entree in donnees]) / len(donnees)bksl-nlbksl-nlbksl-nlfor descripteur in ["Year", "Rating", "Votes", "Minutes", "Gross"]:bksl-nl attendu = moyennepy-undcorr(films, descripteur)bksl-nl assert abs(moyenne(films, descripteur) - attendu) < 10py-strpy-str-2, f"Erreur sur la moyenne de '{descripteur}'"bksl-nlbksl-nlentiers = [bksl-nl {1: 0, 2: 1, 3: 5},bksl-nl {1: 0, 2: 1, 3: 5},bksl-nl]bksl-nlassert moyenne(entiers, 1) == 0, "Erreur dans un test secret"bksl-nlassert moyenne(entiers, 2) == 1, "Erreur dans un test secret"bksl-nlassert moyenne(entiers, 3) == 5, "Erreur dans un test secret"bksl-nlbksl-nl 5/5
# --- HDR ---#bksl-nlurlpy-undfichier = "films.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlfrom js import fetchbksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlimport csvbksl-nlbksl-nlfilms = []bksl-nlwith open("films.csv", "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=";")bksl-nl for entree in lecteur:bksl-nl entree["Ranking"] = int(entree["Ranking"])bksl-nl entree["Year"] = int(entree["Year"])bksl-nl entree["Minutes"] = int(entree["Minutes"])bksl-nl entree["Rating"] = float(entree["Rating"])bksl-nl entree["Votes"] = int(entree["Votes"])bksl-nl entree["Gross"] = float(entree["Gross"])bksl-nl films.append(entree)bksl-nl# --- HDR ---#bksl-nldef somme(donnees, descripteur):bksl-nl """Renvoie la somme des valeurs de ce descripteur"""bksl-nl return sum([entree[descripteur] for entree in donnees])bksl-nlbksl-nlbksl-nldef moyenne(donnees, descripteur):bksl-nl """Renvoie la moyenne des valeurs de ce descripteur"""bksl-nl passbksl-nlbksl-nlbksl-nlassert abs(moyenne(films, "Minutes") - 122.57) < 10py-strpy-str-2, "Erreur sur la moyenne de 'Minutes'"bksl-nlbksl-nldef moyenne(donnees, descripteur):bksl-nl """Renvoie la moyenne des valeurs de ce descripteur"""bksl-nl return somme(donnees, descripteur) / len(donnees)bksl-nlbksl-nl

A

Z

La fonction moyenne est donc valide. Pourtant l'appel moyenne(films, "Gross") renvoie un résultat faux !

En effet, pour certains films le revenu total est inconnu. Néanmoins, afin de proposer un fichier csv valide, sans valeurs manquantes, la valeur -1.0 a été ajoutée dans ce cas. C'est le cas par exemple pour le 19ème film du classement (« Les 400 coups » de François Truffaut) :

🐍 Console Python
>>> projection_multiple(films, ("Name", "Gross"))[18]
('The 400 Blows', -1.0)

Pouvez-vous calculer la moyenne des revenus générés par les films pour lesquels les revenus sont connus ?

Revenu moyen des films

Calculer le revenu moyen des films proposés. Il ne faut pas tenir compte des films pour lesquels cette valeur est inconnue (-1.0 dans le fichier).

Votre variable contenant la bonne valeur doit s'appeler moyenne_valide afin de pouvoir passer les tests avec succès.

Les fonctions somme et moyenne sont déjà chargées.

###
# Tests aléatoiresbksl-nlassert abs(moyennepy-undvalide - 74.8218284424379) < 10py-strpy-str-3, "Erreur de calcul"bksl-nlbksl-nl 5/5
# --- HDR ---#bksl-nlurlpy-undfichier = "films.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlfrom js import fetchbksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlimport csvbksl-nlbksl-nlfilms = []bksl-nlwith open("films.csv", "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=";")bksl-nl for entree in lecteur:bksl-nl entree["Ranking"] = int(entree["Ranking"])bksl-nl entree["Year"] = int(entree["Year"])bksl-nl entree["Minutes"] = int(entree["Minutes"])bksl-nl entree["Rating"] = float(entree["Rating"])bksl-nl entree["Votes"] = int(entree["Votes"])bksl-nl entree["Gross"] = float(entree["Gross"])bksl-nl films.append(entree)bksl-nl# --- HDR ---#bksl-nldef somme(donnees, descripteur):bksl-nl """Renvoie la somme des valeurs de ce descripteur"""bksl-nl return sum([entree[descripteur] for entree in donnees])bksl-nlbksl-nlbksl-nldef moyenne(donnees, descripteur):bksl-nl """Renvoie la moyenne des valeurs de ce descripteur"""bksl-nl return somme(donnees, descripteur) / len(donnees)bksl-nlbksl-nlbksl-nl# Compléter le codebksl-nl...bksl-nlmoyennepy-undvalide = ...bksl-nlbksl-nlprint(moyennepy-undvalide)bksl-nlrevenuspy-undvalides = [entree for entree in films if entree["Gross"] > 0]bksl-nlbksl-nlmoyennepy-undvalide = moyenne(revenuspy-undvalides, "Gross")bksl-nl

A

Z

La meilleure année ?⚓︎

Quelle année a vu se produire le plus de films présents dans ce classement ? Nous allons compter le nombre de films produits chaque année.

Une approche naïve consisterait à effectuer de nombreuses requêtes, une par année : « quels sont les films produits en 1900 ? », « quels sont les films produits en 1901 ? », etc.

Cette approche présente plusieurs inconvénients :

  • quelles sont les années à chercher ? On a fait l'hypothèse que les films ont été produits à partir de 1900 mais c'est vraisemblablement incorrect...

  • Python doit lire l'ensemble des données à chaque requête ! Donc 100 lectures des 517 films si l'on teste tout le XX-ème siècle...

Une approche plus efficace consiste à utiliser un dictionnaire dont les clés sont les années et les valeurs le nombre de films produits cette année-ci. On peut procéder ainsi :

  • initialement le dictionnaire est vide,
  • on parcourt l'ensemble des films. Pour chacun :
  • si son année de production n'est pas présente dans le dictionnaire, on l'ajoute (en tant que clé) avec la valeur 1 (c'est la première fois que l'on rencontre cette valeur)
  • si l'année est déjà dans le dictionnaire on incrémente simplement la valeur associée.
Films par années

Compléter le script ci-dessous permettant de compléter le dictionnaire annee_films associant à chaque année présente dans la liste des films le nombre de films produits cette année-ci.

###
# Testsbksl-nlattendu = {bksl-nl 1941: 3,bksl-nl 1972: 4,bksl-nl 1939: 4,bksl-nl 1994: 8,bksl-nl 1942: 4,bksl-nl 1949: 3,bksl-nl 1980: 7,bksl-nl 1993: 8,bksl-nl 1979: 5,bksl-nl 1990: 3,bksl-nl 1952: 3,bksl-nl 1960: 4,bksl-nl 1968: 5,bksl-nl 1999: 8,bksl-nl 1976: 5,bksl-nl 1954: 5,bksl-nl 1959: 6,bksl-nl 1957: 9,bksl-nl 1964: 6,bksl-nl 1958: 4,bksl-nl 1966: 6,bksl-nl 1931: 3,bksl-nl 1974: 6,bksl-nl 2008: 9,bksl-nl 1982: 11,bksl-nl 1977: 3,bksl-nl 1950: 5,bksl-nl 1981: 3,bksl-nl 1985: 5,bksl-nl 1962: 5,bksl-nl 1975: 8,bksl-nl 2013: 10,bksl-nl 1920: 1,bksl-nl 1940: 7,bksl-nl 2001: 9,bksl-nl 1956: 4,bksl-nl 2015: 9,bksl-nl 2016: 10,bksl-nl 1927: 2,bksl-nl 2003: 10,bksl-nl 1936: 2,bksl-nl 1986: 6,bksl-nl 1934: 2,bksl-nl 1944: 2,bksl-nl 1991: 5,bksl-nl 1971: 4,bksl-nl 1922: 1,bksl-nl 1937: 2,bksl-nl 1969: 5,bksl-nl 1965: 4,bksl-nl 1933: 2,bksl-nl 1995: 11,bksl-nl 1938: 3,bksl-nl 1935: 4,bksl-nl 1948: 4,bksl-nl 1930: 1,bksl-nl 1967: 6,bksl-nl 1951: 6,bksl-nl 1955: 4,bksl-nl 2014: 14,bksl-nl 1926: 1,bksl-nl 1970: 3,bksl-nl 1946: 5,bksl-nl 1997: 8,bksl-nl 1945: 2,bksl-nl 1953: 5,bksl-nl 2007: 8,bksl-nl 1988: 7,bksl-nl 1996: 5,bksl-nl 2018: 7,bksl-nl 2010: 9,bksl-nl 1916: 1,bksl-nl 1925: 2,bksl-nl 1963: 3,bksl-nl 2002: 8,bksl-nl 1998: 11,bksl-nl 1984: 7,bksl-nl 1961: 5,bksl-nl 1978: 5,bksl-nl 2006: 8,bksl-nl 2011: 8,bksl-nl 2004: 11,bksl-nl 2012: 9,bksl-nl 1943: 1,bksl-nl 1989: 5,bksl-nl 1921: 1,bksl-nl 1928: 1,bksl-nl 1983: 2,bksl-nl 1992: 3,bksl-nl 2000: 7,bksl-nl 1973: 6,bksl-nl 2005: 7,bksl-nl 1987: 7,bksl-nl 2009: 10,bksl-nl 1947: 1,bksl-nl 2017: 8,bksl-nl 1924: 1,bksl-nl 1932: 1,bksl-nl}bksl-nlbksl-nlbksl-nlassert anneepy-undfilms == attendu, "Erreur de calcul"bksl-nl 5/5
# --- HDR ---#bksl-nlurlpy-undfichier = "films.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlfrom js import fetchbksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlimport csvbksl-nlbksl-nlfilms = []bksl-nlwith open("films.csv", "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=";")bksl-nl for entree in lecteur:bksl-nl entree["Ranking"] = int(entree["Ranking"])bksl-nl entree["Year"] = int(entree["Year"])bksl-nl entree["Minutes"] = int(entree["Minutes"])bksl-nl entree["Rating"] = float(entree["Rating"])bksl-nl entree["Votes"] = int(entree["Votes"])bksl-nl entree["Gross"] = float(entree["Gross"])bksl-nl films.append(entree)bksl-nl# --- HDR ---#bksl-nlanneepy-undfilms = {}bksl-nlbksl-nl# Compléter le codebksl-nlbksl-nlprint(anneepy-undfilms)bksl-nlanneepy-undfilms = {}bksl-nlbksl-nlfor entree in films:bksl-nl if entree["Year"] not in anneepy-undfilms:bksl-nl anneepy-undfilms[entree["Year"]] = 1bksl-nl else:bksl-nl anneepy-undfilms[entree["Year"]] += 1bksl-nlbksl-nl

A

On pourrait aussi utiliser la fonction projection :

🐍 Script Python
annee_films = {}

for annee in projection(films, "Year"):
    if annee not in annee_films:
        annee_films[annee] = 1
    else:
        annee_films[annee] += 1

Z

Il reste à déterminer l'année durant laquelle le plus de films ont été produits.

La meilleure année

On a chargé en mémoire le dictionnaire annee_films associant à chaque année le nombre de films produits cette année-ci.

Déterminer l'année (nommée annee_maxi) durant laquelle le plus de films ont été produits.

Pas d'égalité !

Une année sort du lot, il n'y a pas d'ex-aequo.

###
attendu = max([(k, v) for k, v in anneepy-undfilms.items()], key=lambda couple: couple[1])[0]bksl-nlbksl-nlassert anneepy-undmaxi == attendu, "Erreur de calcul"bksl-nlbksl-nl 5/5
# --- HDR ---#bksl-nlurlpy-undfichier = "films.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlfrom js import fetchbksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlimport csvbksl-nlbksl-nlfilms = []bksl-nlwith open("films.csv", "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=";")bksl-nl for entree in lecteur:bksl-nl entree["Ranking"] = int(entree["Ranking"])bksl-nl entree["Year"] = int(entree["Year"])bksl-nl entree["Minutes"] = int(entree["Minutes"])bksl-nl entree["Rating"] = float(entree["Rating"])bksl-nl entree["Votes"] = int(entree["Votes"])bksl-nl entree["Gross"] = float(entree["Gross"])bksl-nl films.append(entree)bksl-nlbksl-nlanneepy-undfilms = {bksl-nl 1941: 3,bksl-nl 1972: 4,bksl-nl 1939: 4,bksl-nl 1994: 8,bksl-nl 1942: 4,bksl-nl 1949: 3,bksl-nl 1980: 7,bksl-nl 1993: 8,bksl-nl 1979: 5,bksl-nl 1990: 3,bksl-nl 1952: 3,bksl-nl 1960: 4,bksl-nl 1968: 5,bksl-nl 1999: 8,bksl-nl 1976: 5,bksl-nl 1954: 5,bksl-nl 1959: 6,bksl-nl 1957: 9,bksl-nl 1964: 6,bksl-nl 1958: 4,bksl-nl 1966: 6,bksl-nl 1931: 3,bksl-nl 1974: 6,bksl-nl 2008: 9,bksl-nl 1982: 11,bksl-nl 1977: 3,bksl-nl 1950: 5,bksl-nl 1981: 3,bksl-nl 1985: 5,bksl-nl 1962: 5,bksl-nl 1975: 8,bksl-nl 2013: 10,bksl-nl 1920: 1,bksl-nl 1940: 7,bksl-nl 2001: 9,bksl-nl 1956: 4,bksl-nl 2015: 9,bksl-nl 2016: 10,bksl-nl 1927: 2,bksl-nl 2003: 10,bksl-nl 1936: 2,bksl-nl 1986: 6,bksl-nl 1934: 2,bksl-nl 1944: 2,bksl-nl 1991: 5,bksl-nl 1971: 4,bksl-nl 1922: 1,bksl-nl 1937: 2,bksl-nl 1969: 5,bksl-nl 1965: 4,bksl-nl 1933: 2,bksl-nl 1995: 11,bksl-nl 1938: 3,bksl-nl 1935: 4,bksl-nl 1948: 4,bksl-nl 1930: 1,bksl-nl 1967: 6,bksl-nl 1951: 6,bksl-nl 1955: 4,bksl-nl 2014: 14,bksl-nl 1926: 1,bksl-nl 1970: 3,bksl-nl 1946: 5,bksl-nl 1997: 8,bksl-nl 1945: 2,bksl-nl 1953: 5,bksl-nl 2007: 8,bksl-nl 1988: 7,bksl-nl 1996: 5,bksl-nl 2018: 7,bksl-nl 2010: 9,bksl-nl 1916: 1,bksl-nl 1925: 2,bksl-nl 1963: 3,bksl-nl 2002: 8,bksl-nl 1998: 11,bksl-nl 1984: 7,bksl-nl 1961: 5,bksl-nl 1978: 5,bksl-nl 2006: 8,bksl-nl 2011: 8,bksl-nl 2004: 11,bksl-nl 2012: 9,bksl-nl 1943: 1,bksl-nl 1989: 5,bksl-nl 1921: 1,bksl-nl 1928: 1,bksl-nl 1983: 2,bksl-nl 1992: 3,bksl-nl 2000: 7,bksl-nl 1973: 6,bksl-nl 2005: 7,bksl-nl 1987: 7,bksl-nl 2009: 10,bksl-nl 1947: 1,bksl-nl 2017: 8,bksl-nl 1924: 1,bksl-nl 1932: 1,bksl-nl}bksl-nl# --- HDR ---#bksl-nlanneepy-undmaxi = Nonebksl-nlmaxi = 0bksl-nlbksl-nl# Compléter le codebksl-nlbksl-nlprint(anneepy-undmaxi)bksl-nlprint([entree["Name"] for entree in films if entree["Year"] == anneepy-undmaxi])bksl-nlanneepy-undmaxi = Nonebksl-nlmaxi = 0bksl-nlbksl-nlfor annee in anneepy-undfilms:bksl-nl if anneepy-undfilms[annee] > maxi:bksl-nl maxi = anneepy-undfilms[annee]bksl-nl anneepy-undmaxi = anneebksl-nl

A

On pourrait aussi parcourir les items du dictionnaire :

🐍 Script Python
annee_maxi = None
maxi = 0

for annee, nombre in annee_films.items():
    if nombre > maxi:
        maxi = nombre
        annee_maxi = annee

Z

Le meilleur genre ?⚓︎

Quel genre de film est cité le plus de fois ? Facile, il suffit de compter les apparitions de chaque genre comme l'on vient de compter les années.

Mais les genres sont mal présentés : chaque film est associé à un, deux ou trois genres, si besoin séparés par des virgules, avec des espaces derrière les virgules...

🐍 Console Python
>>> films[3]["Genres"]
'Drama'
>>> films[4]["Genres"]
'Crime, Drama'
>>> films[5]["Genres"]
'Drama, Romance, War'
Pouvez-vous déterminer le genre le plus présent ?

Le meilleur genre

Déterminer le genre le plus représenté dans les films.

La variable contenant ce genre sera nommée meilleur_genre

Astuce

On rappelle que la méthode str.split découpe une chaîne de caractères à chaque apparition de l'argument et renvoie la liste des chaînes obtenues.

Par exemple "31/5/2007".split("/") renvoie ['31', '5', '2007'].

###
attendu = "Drama"bksl-nlbksl-nlassert meilleurpy-undgenre == attendu, "Erreur de calcul"bksl-nlbksl-nl 5/5
# --- HDR ---#bksl-nlurlpy-undfichier = "films.csv"bksl-nlencodage = "utf-8"bksl-nlbksl-nlfrom js import fetchbksl-nlbksl-nlreponse = await fetch(f"../{urlpy-undfichier}")bksl-nlcontenu = await reponse.text()bksl-nlbksl-nlwith open(file=urlpy-undfichier, mode="w", encoding=encodage) as fichier:bksl-nl fichier.write(contenu)bksl-nlbksl-nlimport csvbksl-nlbksl-nlfilms = []bksl-nlwith open("films.csv", "r", encoding="utf-8") as fichier:bksl-nl lecteur = csv.DictReader(fichier, delimiter=";")bksl-nl for entree in lecteur:bksl-nl entree["Ranking"] = int(entree["Ranking"])bksl-nl entree["Year"] = int(entree["Year"])bksl-nl entree["Minutes"] = int(entree["Minutes"])bksl-nl entree["Rating"] = float(entree["Rating"])bksl-nl entree["Votes"] = int(entree["Votes"])bksl-nl entree["Gross"] = float(entree["Gross"])bksl-nl films.append(entree)bksl-nlbksl-nl# --- HDR ---#bksl-nldef projection(donnees, descripteur):bksl-nl """Renvoie la liste des valeurs de ce descripteur"""bksl-nl return [entree[descripteur] for entree in donnees]bksl-nlbksl-nldicopy-undgenres = {}bksl-nlmeilleurpy-undgenre = Nonebksl-nlmaxi = 0bksl-nlbksl-nl# Compléter le codebksl-nlbksl-nlprint(meilleurpy-undgenre)bksl-nlprint(maxi)bksl-nlprint([entree["Name"] for entree in films if meilleurpy-undgenre in entree["Genres"]])bksl-nlbksl-nldicopy-undgenres = {}bksl-nlmeilleurpy-undgenre = Nonebksl-nlmaxi = 0bksl-nlbksl-nlfor genres in projection(films, "Genres"):bksl-nl souspy-undgenres = genres.split(", ")bksl-nl for genre in souspy-undgenres:bksl-nl if genre not in dicopy-undgenres:bksl-nl dicopy-undgenres[genre] = 1bksl-nl else:bksl-nl dicopy-undgenres[genre] += 1bksl-nl if dicopy-undgenres[genre] > maxi:bksl-nl meilleurpy-undgenre = genrebksl-nl maxi = dicopy-undgenres[meilleurpy-undgenre]bksl-nlbksl-nl

A

Z