<jupyter_start><jupyter_text>In this Bite we are going to parse a csv movie dataset to identify the directors with the highest rated movies.Write get_movies_by_director: use csv.DictReader to convert movie_metadata.csv into a (default)dict of lists of Movie namedtuples. Convert/filter the data:Only extract director_name, movie_title, title_year and imdb_score.Type conversions: title_year -> int / imdb_score -> floatDiscard any movies older than 1960.Here is an extract:....{ '<NAME>': [    Movie(title='Midnight in Paris', year=2011, score=7.7),    Movie(title='The Curse of the Jade Scorpion', year=2001, score=6.8),    Movie(title='To Rome with Love', year=2012, score=6.3),  ....    ], ...}Write the calc_mean_score helper that takes a list of Movie namedtuples and calculates the mean IMDb score, returning the score rounded to 1 decimal place.Complete get_average_scores which takes the directors data structure returned by get_movies_by_director (see 1.) and returns a list of tuples (director, average_score) ordered by highest score in descending order. Only take directors into account with >= MIN_MOVIESSee the tests for more info. This could be tough one, but we really hope you learn a thing or two. Good luck and keep calm and code in Python!<jupyter_code>import csv
from collections import defaultdict, namedtuple
import os
from urllib.request import urlretrieve

BASE_URL = "http://projects.bobbelderbos.com/pcc/movies/"
TMP = "/tmp"

fname = "movie_metadata.csv"
remote = os.path.join(BASE_URL, fname)
local = os.path.join(TMP, fname)
urlretrieve(remote, local)

MOVIE_DATA = local
MIN_MOVIES = 4
MIN_YEAR = 1960

Movie = namedtuple("Movie", "title year score")


def get_movies_by_director():
    """Extracts all movies from csv and stores them in a dict,
    where keys are directors, and values are a list of movies,
    use the defined Movie namedtuple"""

    movies = []
    movies_dict = {}

    with open(MOVIE_DATA, newline="") as csvfile:
        myreader = csv.reader(csvfile, delimiter=",")
        for row in myreader:
            movies.append(row)

    # build the dictionary
    movies_dict = defaultdict(list)

    for movie in movies:
        # clean the data, remove the label row
        # and all the entries with an empty director, year
        try:
            notclean = Movie(movie[11], int(movie[23]), float(movie[25]))
        except:
            # the data is not clean, either failed because
            # year is empty or score is a string, discard
            notclean = Movie("", -1, 0)

        if movie[1] in ["director_name", ""]:
            pass
        elif notclean.year < MIN_YEAR:
            pass
        else:
            movies_dict[movie[1]].append(notclean)

    return movies_dict


def calc_mean_score(movies):
    """Helper method to calculate mean of list of Movie namedtuples,
       round the mean to 1 decimal place"""

    total_score = float(0)
    for movie in movies:
        total_score += movie.score
    mean_score = round(total_score / len(movies), 1)

    return mean_score


def get_average_scores(directors):
    """Iterate through the directors dict (returned by get_movies_by_director),
       return a list of tuples (director, average_score) ordered by highest
       score in descending order. Only take directors into account
       with >= MIN_MOVIES"""

    result = []

    for director in directors.keys():
        # discard entries with leass than MIN_MOVIES
        if len(directors[director]) >= MIN_MOVIES:
            # get the mean score
            mean_score = calc_mean_score(directors[director])
            result.append((director, mean_score))

    return sorted(result, key=lambda tup: tup[1], reverse=True)

import csv
from collections import defaultdict, namedtuple
import os
from urllib.request import urlretrieve

BASE_URL = 'http://projects.bobbelderbos.com/pcc/movies/'
TMP = '/tmp'

fname = 'movie_metadata.csv'
remote = os.path.join(BASE_URL, fname)
local = os.path.join(TMP, fname)
urlretrieve(remote, local)

MOVIE_DATA = local
MIN_MOVIES = 4
MIN_YEAR = 1960

Movie = namedtuple('Movie', 'title year score')


def get_movies_by_director():
    """Extracts all movies from csv and stores them in a dict,
    where keys are directors, and values are a list of movies,
    use the defined Movie namedtuple"""

    movies = []
    movies_dict = {}

    with open(MOVIE_DATA, newline="") as csvfile:
        myreader = csv.reader(csvfile, delimiter=",")
        for row in myreader:
            movies.append(row)

    # build the dictionary
    movies_dict = defaultdict(list)

#     for movie in movies:
#         # clean the data, remove the label row
#         # and all the entries with an empty director, year
#         try:
#             notclean = Movie(movie[11], int(movie[23]), float(movie[25]))
#         except:
#             # the data is not clean, either failed because
#             # year is empty or score is a string, discard
#             notclean = Movie("", -1, 0)

#         if movie[1] in ["director_name", ""]:
#             pass
#         elif notclean.year < MIN_YEAR:
#             pass
#         else:
#             movies_dict[movie[1]].append(notclean)

    return movies_dict

get_movies_by_director()
help(defaultdict)
help(csv)
help(os.path)<jupyter_output>Help on module posixpath:

NAME
    posixpath - Common operations on Posix pathnames.

MODULE REFERENCE
    https://docs.python.org/3.6/library/posixpath
    
    The following documentation is automatically generated from the Python
    source files.  It may be incomplete, incorrect or include features that
    are considered implementation detail and may vary between Python
    implementations.  When in doubt, consult the module reference at the
    location listed above.

DESCRIPTION
    Instead of importing this module directly, import os and refer to
    this module as os.path.  The "os.path" name is an alias for this
    module on Posix systems; on other systems (e.g. Mac, Windows),
    os.path provides the same operations in a manner specific to that
    platform, and is an alias to another module (e.g. macpath, ntpath).
    
    Some of this can actually be useful on non-Posix systems too, e.g.
    for manipulation of the pathname component of URLs.

FUNCTIONS
    abspath(path)[...]
{'fraction_non_alphanumeric': 0.08511650023775559, 'fraction_numerical': 0.009510223490252021, 'mean_word_length': 3.1080729166666665, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 10, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '169605', 'license': 'MIT', 'n_tokens_mistral': 1912, 'n_tokens_neox': 1801, 'n_words': 687, 'path': 'bitesofpy/30.ipynb', 'repo_name': 'Anthlis/azure_ipynb', 'size': '6314'}