<filename>functions.py
import re

import numpy as np
import pandas as pd
import requests
import streamlit as st
from bs4 import BeautifulSoup

def weighted_rating(df):
    """
    Calculates the IMDB's Weighted Rating using the following formula:
        (v / (v+m) * R) + (m / (m+v) * C)

    where:
    - v is the number of votes for the movie;
    - m is the minimum votes required to be listed in the chart;
    - R is the average rating of the movie; And
    - C is the mean vote across the whole report
    """
    v = df['count_rating']
    m = df['minimum_no_of_ratings']
    R = df['avg_rating']
    C = df['overall_avg_rating']

    return (v / (v+m) * R) + (m / (m+v) * C)

def filtered_dataset(genre, ratings_movies_df):
    """Filters list of movies to show only movies of the chosen genre. Calculates
    the 95th quantile of No. of Ratings to keep only relevant movies.

    Args:
        genre (str): Genre name
        ratings_movies_df (pd.DataFrame): Dataframe with Movie Ratings

    Returns:
        genre_df[pd.DataFrame]: Filtered Dataframe with relevant movies for the genre
    """
    # Keep only the selected genre
    genre_df = ratings_movies_df[ratings_movies_df['genres'].str.contains(genre)]

    # Calculate the 95th quantile and the weighted rating
    minimum_no_of_ratings = genre_df['count_rating'].quantile(0.95)
    genre_df['minimum_no_of_ratings'] = minimum_no_of_ratings
    genre_df['weighted_rating'] = genre_df.apply(weighted_rating, axis=1)

    # Remove movies with not enough ratings
    genre_df = genre_df[genre_df['count_rating'] >= minimum_no_of_ratings]

    # Sorted it by weighted rating so we have the highest ratings on the top
    genre_df = genre_df.sort_values('weighted_rating', ascending=False)
    genre_df = genre_df.reset_index(drop=True)

    # Keep certain relevant columns
    genre_df = genre_df[['movieId', 'title',
                         'genres', 'count_rating',
                         'minimum_no_of_ratings', 'weighted_rating']]

    return genre_df

@st.cache(suppress_st_warning=True, show_spinner=False)
def movie_picture(imdb_id):
    """A function to find a movie's picture from IMDB

    Args:
        movie_name (str): Movie Name

    Returns:
        movie_image_link[str]: IMDB's Link to JPEG Image of the Movie
    """
    # Create IMDB movie link
    new_url = 'https://www.imdb.com/title/tt' + str(imdb_id)

    # Define headers
    HEADERS = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) '\
                         'AppleWebKit/537.36 (KHTML, like Gecko) '\
                         'Chrome/75.0.3770.80 Safari/537.36'}

    # Go Movie's Page
    movie_page = requests.get(new_url, headers=HEADERS)
    soup = BeautifulSoup(movie_page.content, 'html.parser')

    # Movie JPEG link
    movie_image_link = soup.find(class_='ipc-image').attrs['src']

    return movie_image_link

def rename_title(title):
    """Function to rename a title

    Args:
        title (str): Original Title in wrong format

    Returns:
        new_title[str]: Fixed movie title in the correct format
    """
    # Extract year from title
    year = title.strip()[-5:][:-1]

    # Confirms if it's a valid year number
    if len(re.findall("[0-9]{4}", year)) != 1:
        year = np.nan
    if year != np.nan:
        title = title[:-6].strip()

    # Create new title
    new_title = " ".join(title.split(", ")[::-1])

    return new_title

<filename>functions.py
import re

import numpy as np
import pandas as pd
import requests
import streamlit as st
from bs4 import BeautifulSoup

def weighted_rating(df):
    """
    Calculates the IMDB's Weighted Rating using the following formula:
        (v / (v+m) * R) + (m / (m+v) * C)

    where:
    - v is the number of votes for the movie;
    - m is the minimum votes required to be listed in the chart;
    - R is the average rating of the movie; And
    - C is the mean vote across the whole report
    """
    v = df['count_rating']
    m = df['minimum_no_of_ratings']
    R = df['avg_rating']
    C = df['overall_avg_rating']

    return (v / (v+m) * R) + (m / (m+v) * C)

def filtered_dataset(genre, ratings_movies_df):
    """Filters list of movies to show only movies of the chosen genre. Calculates
    the 95th quantile of No. of Ratings to keep only relevant movies.

    Args:
        genre (str): Genre name
        ratings_movies_df (pd.DataFrame): Dataframe with Movie Ratings

    Returns:
        genre_df[pd.DataFrame]: Filtered Dataframe with relevant movies for the genre
    """
    # Keep only the selected genre
    genre_df = ratings_movies_df[ratings_movies_df['genres'].str.contains(genre)]

    # Calculate the 95th quantile and the weighted rating
    minimum_no_of_ratings = genre_df['count_rating'].quantile(0.95)
    genre_df['minimum_no_of_ratings'] = minimum_no_of_ratings
    genre_df['weighted_rating'] = genre_df.apply(weighted_rating, axis=1)

    # Remove movies with not enough ratings
    genre_df = genre_df[genre_df['count_rating'] >= minimum_no_of_ratings]

    # Sorted it by weighted rating so we have the highest ratings on the top
    genre_df = genre_df.sort_values('weighted_rating', ascending=False)
    genre_df = genre_df.reset_index(drop=True)

    # Keep certain relevant columns
    genre_df = genre_df[['movieId', 'title',
                         'genres', 'count_rating',
                         'minimum_no_of_ratings', 'weighted_rating']]

    return genre_df

@st.cache(suppress_st_warning=True, show_spinner=False)
def movie_picture(imdb_id):
    """A function to find a movie's picture from IMDB

    Args:
        movie_name (str): Movie Name

    Returns:
        movie_image_link[str]: IMDB's Link to JPEG Image of the Movie
    """
    # Create IMDB movie link
    new_url = 'https://www.imdb.com/title/tt' + str(imdb_id)

    # Define headers
    HEADERS = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) '\
                         'AppleWebKit/537.36 (KHTML, like Gecko) '\
                         'Chrome/75.0.3770.80 Safari/537.36'}

    # Go Movie's Page
    movie_page = requests.get(new_url, headers=HEADERS)
    soup = BeautifulSoup(movie_page.content, 'html.parser')

    # Movie JPEG link
    movie_image_link = soup.find(class_='ipc-image').attrs['src']

    return movie_image_link

def rename_title(title):
    """Function to rename a title

    Args:
        title (str): Original Title in wrong format

    Returns:
        new_title[str]: Fixed movie title in the correct format
    """
    # Extract year from title
    year = title.strip()[-5:][:-1]

    # Confirms if it's a valid year number
    if len(re.findall("[0-9]{4}", year)) != 1:
        year = np.nan
    if year != np.nan:
        title = title[:-6].strip()

    # Create new title
    new_title = " ".join(title.split(", ")[::-1])

    return new_title

Calculates the IMDB's Weighted Rating using the following formula:         (v / (v+m) * R) + (m / (m+v) * C)      where:     - v is the number of votes for the movie;     - m is the minimum votes required to be listed in the chart;     - R is the average rating of the movie; And     - C is the mean vote across the whole report Filters list of movies to show only movies of the chosen genre. Calculates     the 95th quantile of No. of Ratings to keep only relevant movies.      Args:         genre (str): Genre name         ratings_movies_df (pd.DataFrame): Dataframe with Movie Ratings      Returns:         genre_df[pd.DataFrame]: Filtered Dataframe with relevant movies for the genre # Keep only the selected genre # Calculate the 95th quantile and the weighted rating # Remove movies with not enough ratings # Sorted it by weighted rating so we have the highest ratings on the top # Keep certain relevant columns A function to find a movie's picture from IMDB      Args:         movie_name (str): Movie Name      Returns:         movie_image_link[str]: IMDB's Link to JPEG Image of the Movie # Create IMDB movie link # Define headers # Go Movie's Page # Movie JPEG link Function to rename a title      Args:         title (str): Original Title in wrong format      Returns:         new_title[str]: Fixed movie title in the correct format # Extract year from title # Confirms if it's a valid year number # Create new title