{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "movie recommendation.ipynb",
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "code",
      "metadata": {
        "id": "ttTnNkzqT5Q5"
      },
      "source": [
        "!pip install -q rake_nltk\n",
        "# nltk package allows to extract the key words from a text, and it even assigns scores to each word.\n",
        "# Rake extracts key words from the Plot column, so instead of using the entire sentences \n",
        "# describing the plot, consider the most relevant words in the description"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "IO2llO4TUoS-",
        "outputId": "dc54395c-4fb0-4184-d8f8-871a4b233060",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 204
        }
      },
      "source": [
        "import pandas as pd\n",
        "import numpy as np\n",
        "from rake_nltk import Rake\n",
        "from sklearn.metrics.pairwise import cosine_similarity\n",
        "from sklearn.feature_extraction.text import CountVectorizer\n",
        "\n",
        "\n",
        "df = pd.read_csv('https://query.data.world/s/uikepcpffyo2nhig52xxeevdialfl7')\n",
        "df = df[['Title','Genre','Director','Actors','Plot']]\n",
        "df.head()\n"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "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>Title</th>\n",
              "      <th>Genre</th>\n",
              "      <th>Director</th>\n",
              "      <th>Actors</th>\n",
              "      <th>Plot</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>The Shawshank Redemption</td>\n",
              "      <td>Crime, Drama</td>\n",
              "      <td>Frank Darabont</td>\n",
              "      <td>Tim Robbins, Morgan Freeman, Bob Gunton, Willi...</td>\n",
              "      <td>Two imprisoned men bond over a number of years...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>The Godfather</td>\n",
              "      <td>Crime, Drama</td>\n",
              "      <td>Francis Ford Coppola</td>\n",
              "      <td>Marlon Brando, Al Pacino, James Caan, Richard ...</td>\n",
              "      <td>The aging patriarch of an organized crime dyna...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>The Godfather: Part II</td>\n",
              "      <td>Crime, Drama</td>\n",
              "      <td>Francis Ford Coppola</td>\n",
              "      <td>Al Pacino, Robert Duvall, Diane Keaton, Robert...</td>\n",
              "      <td>The early life and career of Vito Corleone in ...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>The Dark Knight</td>\n",
              "      <td>Action, Crime, Drama</td>\n",
              "      <td>Christopher Nolan</td>\n",
              "      <td>Christian Bale, Heath Ledger, Aaron Eckhart, M...</td>\n",
              "      <td>When the menace known as the Joker emerges fro...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>12 Angry Men</td>\n",
              "      <td>Crime, Drama</td>\n",
              "      <td>Sidney Lumet</td>\n",
              "      <td>Martin Balsam, John Fiedler, Lee J. Cobb, E.G....</td>\n",
              "      <td>A jury holdout attempts to prevent a miscarria...</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "                      Title  ...                                               Plot\n",
              "0  The Shawshank Redemption  ...  Two imprisoned men bond over a number of years...\n",
              "1             The Godfather  ...  The aging patriarch of an organized crime dyna...\n",
              "2    The Godfather: Part II  ...  The early life and career of Vito Corleone in ...\n",
              "3           The Dark Knight  ...  When the menace known as the Joker emerges fro...\n",
              "4              12 Angry Men  ...  A jury holdout attempts to prevent a miscarria...\n",
              "\n",
              "[5 rows x 5 columns]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 2
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "dNBaPXCkU8jO",
        "outputId": "bc7198e6-fc69-470f-ba66-c5c5b400c1c3",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 289
        }
      },
      "source": [
        "# initializing the new column\n",
        "df['Key_words'] = \"\"\n",
        "\n",
        "for index, row in df.iterrows():\n",
        "    plot = row['Plot']\n",
        "    \n",
        "    # instantiating Rake, by default it uses english stopwords from NLTK\n",
        "    # and discards all puntuation characters as well\n",
        "    r = Rake()\n",
        "\n",
        "    # extracting the words by passing the text\n",
        "    r.extract_keywords_from_text(plot)\n",
        "\n",
        "    # getting the dictionary whith key words as keys and their scores as values\n",
        "    key_words_dict_scores = r.get_word_degrees()\n",
        "    # assigning the key words to the new column for the corresponding movie\n",
        "    row['Key_words'] = list(key_words_dict_scores.keys())\n",
        "\n",
        "# dropping the Plot column\n",
        "df.drop(columns = ['Plot'], inplace = True)\n",
        "df.head()"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "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>Title</th>\n",
              "      <th>Genre</th>\n",
              "      <th>Director</th>\n",
              "      <th>Actors</th>\n",
              "      <th>Key_words</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>The Shawshank Redemption</td>\n",
              "      <td>Crime, Drama</td>\n",
              "      <td>Frank Darabont</td>\n",
              "      <td>Tim Robbins, Morgan Freeman, Bob Gunton, Willi...</td>\n",
              "      <td>[two, imprisoned, men, bond, years, acts, even...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>The Godfather</td>\n",
              "      <td>Crime, Drama</td>\n",
              "      <td>Francis Ford Coppola</td>\n",
              "      <td>Marlon Brando, Al Pacino, James Caan, Richard ...</td>\n",
              "      <td>[reluctant, son, clandestine, empire, organize...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>The Godfather: Part II</td>\n",
              "      <td>Crime, Drama</td>\n",
              "      <td>Francis Ford Coppola</td>\n",
              "      <td>Al Pacino, Robert Duvall, Diane Keaton, Robert...</td>\n",
              "      <td>[son, family, crime, syndicate, grip, 1920s, n...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>The Dark Knight</td>\n",
              "      <td>Action, Crime, Drama</td>\n",
              "      <td>Christopher Nolan</td>\n",
              "      <td>Christian Bale, Heath Ledger, Aaron Eckhart, M...</td>\n",
              "      <td>[dark, knight, must, accept, one, gotham, abil...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>12 Angry Men</td>\n",
              "      <td>Crime, Drama</td>\n",
              "      <td>Sidney Lumet</td>\n",
              "      <td>Martin Balsam, John Fiedler, Lee J. Cobb, E.G....</td>\n",
              "      <td>[prevent, miscarriage, reconsider, evidence, j...</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "                      Title  ...                                          Key_words\n",
              "0  The Shawshank Redemption  ...  [two, imprisoned, men, bond, years, acts, even...\n",
              "1             The Godfather  ...  [reluctant, son, clandestine, empire, organize...\n",
              "2    The Godfather: Part II  ...  [son, family, crime, syndicate, grip, 1920s, n...\n",
              "3           The Dark Knight  ...  [dark, knight, must, accept, one, gotham, abil...\n",
              "4              12 Angry Men  ...  [prevent, miscarriage, reconsider, evidence, j...\n",
              "\n",
              "[5 rows x 5 columns]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 3
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "PKmG9wc6WX2B",
        "outputId": "6d987192-64ac-4dd9-e1fb-5d00fbe6eb87",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 204
        }
      },
      "source": [
        "# Everything needs to be lowercase to avoid duplications, and merge all first and last names in one unique word.\n",
        "# Also keep all in one column\n",
        "df['bag_of_keyword'] = ''\n",
        "for index, row in df.iterrows():\n",
        "  keyword = ''\n",
        "  genre = row['Genre'].split(',')\n",
        "  for i in range(len(genre)):\n",
        "    keyword += genre[i].lower()\n",
        "  director = row['Director'].replace(' ', '').lower()\n",
        "  keyword += ' ' + director\n",
        "  actors = row['Actors'].split(',')\n",
        "  for i in range(len(actors)):\n",
        "    keyword += ' ' + actors[i].replace(' ', '').lower()\n",
        "  key_words = row['Key_words']\n",
        "  for i in range(len(key_words)):\n",
        "    keyword += ' ' + key_words[i]\n",
        "  row['bag_of_keyword'] = keyword\n",
        "\n",
        "# dropping the Genre, Director, Actors and Key_words columns\n",
        "df.drop(columns = ['Genre','Director', 'Actors','Key_words'], inplace = True)\n",
        "df.head()"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "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>Title</th>\n",
              "      <th>bag_of_keyword</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>The Shawshank Redemption</td>\n",
              "      <td>crime drama frankdarabont timrobbins morganfre...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>The Godfather</td>\n",
              "      <td>crime drama francisfordcoppola marlonbrando al...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>The Godfather: Part II</td>\n",
              "      <td>crime drama francisfordcoppola alpacino robert...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>The Dark Knight</td>\n",
              "      <td>action crime drama christophernolan christianb...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>12 Angry Men</td>\n",
              "      <td>crime drama sidneylumet martinbalsam johnfiedl...</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "                      Title                                     bag_of_keyword\n",
              "0  The Shawshank Redemption  crime drama frankdarabont timrobbins morganfre...\n",
              "1             The Godfather  crime drama francisfordcoppola marlonbrando al...\n",
              "2    The Godfather: Part II  crime drama francisfordcoppola alpacino robert...\n",
              "3           The Dark Knight  action crime drama christophernolan christianb...\n",
              "4              12 Angry Men  crime drama sidneylumet martinbalsam johnfiedl..."
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 4
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "SpfNRlXknLTN",
        "outputId": "57d6349f-08dd-4df0-ae5a-575d75a15a00",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 238
        }
      },
      "source": [
        "# To detect similarities between movies we need to vectorize\n",
        "# Here CountVectorizer is used rather than TfIdfVectorizer for one simple reason: \n",
        "# We need a simple frequency counter for each word in my bag_of_keyword column.\n",
        "\n",
        "# instantiating and generating the count matrix\n",
        "count = CountVectorizer()\n",
        "count_matrix = count.fit_transform(df['bag_of_keyword'])\n",
        "\n",
        "# generating the cosine similarity matrix\n",
        "cosine_sim = cosine_similarity(count_matrix, count_matrix)\n",
        "cosine_sim\n",
        "# All the numbers on the diagonal are 1 because, of course, every movie is identical to itself. \n",
        "# The matrix is also symmetrical because the similarity between A and B is the same as the similarity between B and A."
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[1.        , 0.14638501, 0.1315587 , ..., 0.05      , 0.05      ,\n",
              "        0.05270463],\n",
              "       [0.14638501, 1.        , 0.34236839, ..., 0.048795  , 0.048795  ,\n",
              "        0.05143445],\n",
              "       [0.1315587 , 0.34236839, 1.        , ..., 0.0438529 , 0.0438529 ,\n",
              "        0.04622502],\n",
              "       ...,\n",
              "       [0.05      , 0.048795  , 0.0438529 , ..., 1.        , 0.05      ,\n",
              "        0.05270463],\n",
              "       [0.05      , 0.048795  , 0.0438529 , ..., 0.05      , 1.        ,\n",
              "        0.05270463],\n",
              "       [0.05270463, 0.05143445, 0.04622502, ..., 0.05270463, 0.05270463,\n",
              "        1.        ]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 5
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "fN88R19rkrPY",
        "outputId": "c601d120-60f5-4d9b-b144-9364a91a9444",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 187
        }
      },
      "source": [
        "# creating a Series for the movie titles so they are associated to an ordered numerical\n",
        "# list I will use in the function to match the indexes\n",
        "indices = pd.Series(df['Title'])\n",
        "# defining the function that takes in movie title \n",
        "# as input and returns the top 10 recommended movies\n",
        "def recommendations(title, cosine_sim = cosine_sim):\n",
        "    \n",
        "    # initializing the empty list of recommended movies\n",
        "    recommended_movies = []\n",
        "    \n",
        "    # gettin the index of the movie that matches the title\n",
        "    idx = indices[indices == title].index[0]\n",
        "\n",
        "    # creating a Series with the similarity scores in descending order\n",
        "    score_series = pd.Series(cosine_sim[idx]).sort_values(ascending = False)\n",
        "\n",
        "    # getting the indexes of the 10 most similar movies\n",
        "    top_10_indexes = list(score_series.iloc[1:11].index)\n",
        "    \n",
        "    # populating the list with the titles of the best 10 matching movies\n",
        "    for i in top_10_indexes:\n",
        "        recommended_movies.append(list(df['Title'])[i])\n",
        "        \n",
        "    return recommended_movies\n",
        "recommendations('The Departed')"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "['Fargo',\n",
              " 'Reservoir Dogs',\n",
              " 'Heat',\n",
              " 'The Wolf of Wall Street',\n",
              " 'Rope',\n",
              " 'Shutter Island',\n",
              " 'Goodfellas',\n",
              " 'Blood Diamond',\n",
              " 'On the Waterfront',\n",
              " 'Chinatown']"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 6
        }
      ]
    }
  ]
}