From 13ff9a3ef4d046dc502f5fb4268041166d8fbbe7 Mon Sep 17 00:00:00 2001 From: Teo Baldi <teo.baldi@student.uclouvain.be> Date: Mon, 29 May 2023 15:44:18 +0000 Subject: [PATCH] complete assignement coding 1 - notebook --- analytics.ipynb | 1129 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1116 insertions(+), 13 deletions(-) diff --git a/analytics.ipynb b/analytics.ipynb index 2214de9..cc6c307 100644 --- a/analytics.ipynb +++ b/analytics.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -21,7 +21,13 @@ "# third parties imports\n", "import numpy as np \n", "import pandas as pd\n", + "import random as rd\n", + "\n", "# -- add new imports here --\n", + "import re\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "from scipy.sparse import csr_matrix\n", "\n", "# local imports\n", "from constants import Constant as C\n", @@ -29,6 +35,23 @@ "from loaders import load_items" ] }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "movieId\n" + ] + } + ], + "source": [ + "print(C.ITEM_ID_COL)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -39,20 +62,272 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ - "# -- load the items and display the Dataframe" + "# -- load the items and display the Dataframe\n", + "df_items = load_items()" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 4, "metadata": {}, - "outputs": [], + "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>title</th>\n", + " <th>genres</th>\n", + " </tr>\n", + " <tr>\n", + " <th>movieId</th>\n", + " <th></th>\n", + " <th></th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>3</th>\n", + " <td>Grumpier Old Men (1995)</td>\n", + " <td>Comedy|Romance</td>\n", + " </tr>\n", + " <tr>\n", + " <th>15</th>\n", + " <td>Cutthroat Island (1995)</td>\n", + " <td>Action|Adventure|Romance</td>\n", + " </tr>\n", + " <tr>\n", + " <th>34</th>\n", + " <td>Babe (1995)</td>\n", + " <td>Children|Drama</td>\n", + " </tr>\n", + " <tr>\n", + " <th>59</th>\n", + " <td>Confessional, The (Confessionnal, Le) (1995)</td>\n", + " <td>Drama|Mystery</td>\n", + " </tr>\n", + " <tr>\n", + " <th>64</th>\n", + " <td>Two if by Sea (1996)</td>\n", + " <td>Comedy|Romance</td>\n", + " </tr>\n", + " <tr>\n", + " <th>...</th>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " </tr>\n", + " <tr>\n", + " <th>148652</th>\n", + " <td>The Ridiculous 6 (2015)</td>\n", + " <td>Comedy|Western</td>\n", + " </tr>\n", + " <tr>\n", + " <th>151307</th>\n", + " <td>The Lovers and the Despot</td>\n", + " <td>(no genres listed)</td>\n", + " </tr>\n", + " <tr>\n", + " <th>152173</th>\n", + " <td>Michael Jackson's Thriller (1983)</td>\n", + " <td>Horror</td>\n", + " </tr>\n", + " <tr>\n", + " <th>160440</th>\n", + " <td>The Maid's Room (2014)</td>\n", + " <td>Thriller</td>\n", + " </tr>\n", + " <tr>\n", + " <th>160656</th>\n", + " <td>Tallulah (2016)</td>\n", + " <td>Drama</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "<p>912 rows × 2 columns</p>\n", + "</div>" + ], + "text/plain": [ + " title \\\n", + "movieId \n", + "3 Grumpier Old Men (1995) \n", + "15 Cutthroat Island (1995) \n", + "34 Babe (1995) \n", + "59 Confessional, The (Confessionnal, Le) (1995) \n", + "64 Two if by Sea (1996) \n", + "... ... \n", + "148652 The Ridiculous 6 (2015) \n", + "151307 The Lovers and the Despot \n", + "152173 Michael Jackson's Thriller (1983) \n", + "160440 The Maid's Room (2014) \n", + "160656 Tallulah (2016) \n", + "\n", + " genres \n", + "movieId \n", + "3 Comedy|Romance \n", + "15 Action|Adventure|Romance \n", + "34 Children|Drama \n", + "59 Drama|Mystery \n", + "64 Comedy|Romance \n", + "... ... \n", + "148652 Comedy|Western \n", + "151307 (no genres listed) \n", + "152173 Horror \n", + "160440 Thriller \n", + "160656 Drama \n", + "\n", + "[912 rows x 2 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# -- display relevant informations that can be extracted from the dataset\n", + "display(df_items)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of movies : 912\n" + ] + } + ], + "source": [ + "# Number of movies in the dataset\n", + "n_movies = len(df_items)\n", + "print(f\"Number of movies : \",n_movies)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "MINIMUM AND MAXIMUN YEAR\n", + "°The minimum year : 1921\n", + "°The maximum year : 2016\n" + ] + } + ], + "source": [ + "import re\n", + "\n", + "#EXTRACT THE DATE OF EACH MOVIE (creation of a list and a dico) \n", + "dates = []\n", + "dico = {}\n", + "for title in df_items.iloc[:, 0]:\n", + " match = re.search(r'\\((\\d{4})[\\s-]*\\d*[\\s-]*\\d*\\)', title) \n", + " if match :\n", + " dates.append(int(match.group(1)))\n", + " dico[title] = int(match.group(1))\n", + " else : \n", + " #print(title) #movies with no date\n", + " dico[title] = \"/\"\n", + " \n", + "#print(dates)\n", + "#print(len(dates))\n", + "#print(dico)\n", + "\n", + "# TESTS\n", + "#print(f\"TESTS...\")\n", + "#for key,value in dico.items():\n", + " #if key == \"Stranger Things\" :\n", + " #print(value)\n", + " #if key == \"Fawlty Towers (1975-1979)\" :\n", + " #print(value)\n", + " \n", + "#---------------------------------------------------------------\n", + "# MINIMUM AND MAXIMUN YEAR\n", + "print(f\"\\nMINIMUM AND MAXIMUN YEAR\")\n", + "min_year = min(dates)\n", + "max_year = max(dates)\n", + "print(f\"°The minimum year : \", min_year)\n", + "print(f\"°The maximum year : \", max_year)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "°There are 20 different genres of movies.\n", + "°Here is the genres list :\n", + " -Comedy (307 movies)\n", + " -Romance (141 movies)\n", + " -Action (149 movies)\n", + " -Adventure (110 movies)\n", + " -Children (64 movies)\n", + " -Drama (454 movies)\n", + " -Mystery (64 movies)\n", + " -Thriller (169 movies)\n", + " -Crime (110 movies)\n", + " -Sci-Fi (73 movies)\n", + " -Documentary (50 movies)\n", + " -Fantasy (68 movies)\n", + " -War (32 movies)\n", + " -Horror (91 movies)\n", + " -Western (21 movies)\n", + " -Animation (45 movies)\n", + " -Musical (38 movies)\n", + " -Film-Noir (11 movies)\n", + " -IMAX (13 movies)\n", + " -(no genres listed) (3 movies)\n" + ] + } + ], "source": [ - "# -- display relevant informations that can be extracted from the dataset" + "list_genres = []\n", + "for genres in df_items.iloc[:,1]:\n", + " liste = genres.split(\"|\") #with the focntion split, a new list is created\n", + " for i in liste :\n", + " if i not in list_genres :\n", + " list_genres.append(i)\n", + "print(f\"°There are\", len(list_genres), \"different genres of movies.\")\n", + "\n", + "print(f\"°Here is the genres list :\") \n", + "for g in list_genres :\n", + " count = 0 #some films have several genres\n", + " for row in df_items.iloc[:, 1]:\n", + " if g in row :\n", + " count += 1\n", + " print(\" -\" + g + \" (\" + str(count) + \" movies)\")" ] }, { @@ -65,28 +340,856 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ - "# -- load the items and display the Dataframe" + "# -- load the items and display the Dataframe\n", + "df_ratings = load_ratings()" + ] + }, + { + "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>userId</th>\n", + " <th>movieId</th>\n", + " <th>rating</th>\n", + " <th>timestamp</th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>0</th>\n", + " <td>15</td>\n", + " <td>34</td>\n", + " <td>3.0</td>\n", + " <td>997938310</td>\n", + " </tr>\n", + " <tr>\n", + " <th>1</th>\n", + " <td>15</td>\n", + " <td>95</td>\n", + " <td>1.5</td>\n", + " <td>1093028331</td>\n", + " </tr>\n", + " <tr>\n", + " <th>2</th>\n", + " <td>15</td>\n", + " <td>101</td>\n", + " <td>4.0</td>\n", + " <td>1134522072</td>\n", + " </tr>\n", + " <tr>\n", + " <th>3</th>\n", + " <td>15</td>\n", + " <td>123</td>\n", + " <td>4.0</td>\n", + " <td>997938358</td>\n", + " </tr>\n", + " <tr>\n", + " <th>4</th>\n", + " <td>15</td>\n", + " <td>125</td>\n", + " <td>3.5</td>\n", + " <td>1245362506</td>\n", + " </tr>\n", + " <tr>\n", + " <th>...</th>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " </tr>\n", + " <tr>\n", + " <th>5291</th>\n", + " <td>665</td>\n", + " <td>3908</td>\n", + " <td>1.0</td>\n", + " <td>1046967201</td>\n", + " </tr>\n", + " <tr>\n", + " <th>5292</th>\n", + " <td>665</td>\n", + " <td>4052</td>\n", + " <td>4.0</td>\n", + " <td>992838277</td>\n", + " </tr>\n", + " <tr>\n", + " <th>5293</th>\n", + " <td>665</td>\n", + " <td>4351</td>\n", + " <td>4.0</td>\n", + " <td>992837743</td>\n", + " </tr>\n", + " <tr>\n", + " <th>5294</th>\n", + " <td>665</td>\n", + " <td>4643</td>\n", + " <td>4.0</td>\n", + " <td>997239207</td>\n", + " </tr>\n", + " <tr>\n", + " <th>5295</th>\n", + " <td>665</td>\n", + " <td>5502</td>\n", + " <td>4.0</td>\n", + " <td>1046967596</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "<p>5296 rows × 4 columns</p>\n", + "</div>" + ], + "text/plain": [ + " userId movieId rating timestamp\n", + "0 15 34 3.0 997938310\n", + "1 15 95 1.5 1093028331\n", + "2 15 101 4.0 1134522072\n", + "3 15 123 4.0 997938358\n", + "4 15 125 3.5 1245362506\n", + "... ... ... ... ...\n", + "5291 665 3908 1.0 1046967201\n", + "5292 665 4052 4.0 992838277\n", + "5293 665 4351 4.0 992837743\n", + "5294 665 4643 4.0 997239207\n", + "5295 665 5502 4.0 1046967596\n", + "\n", + "[5296 rows x 4 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# -- display relevant informations that can be extracted from the dataset\n", + "display(df_ratings)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "°Total number of ratings : 5296\n", + "°Number of unique users/raters : 107\n", + "°Number of unique movies : 834\n", + "°Average number of ratings per user: 49.5\n", + "°Average number of ratings per movie: 6.35\n" + ] + } + ], + "source": [ + "# Number of ratings in the dataset\n", + "n_ratings = len(df_ratings)\n", + "print(f\"°Total number of ratings : \", n_ratings)\n", + "\n", + "#----------------------------------------------\n", + "\n", + "# Number of unique users (= number of raters)\n", + "unique_users = df_ratings['userId'].nunique()\n", + "print(f\"°Number of unique users/raters : \", unique_users)\n", + "\n", + "#----------------------------------------------\n", + "\n", + "# Number of unique movies (in the ratings matrix) (= number of rated movies)\n", + "unique_movies = df_ratings['movieId'].nunique()\n", + "print(f\"°Number of unique movies : \", unique_movies)\n", + "\n", + "#----------------------------------------------\n", + "print(f\"°Average number of ratings per user: {round(n_ratings/unique_users, 2)}\")\n", + "print(f\"°Average number of ratings per movie: {round(n_ratings/unique_movies, 2)}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": true, + "jupyter": { + "outputs_hidden": true + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The movie(s) with the most ratings is/are :\n", + " - 1240 with 75 ratings\n", + " - 1210 with 75 ratings\n", + "\n", + "The movie(s) with the less ratings is/are :\n", + " - 2128 with 1 ratings\n", + " - 2481 with 1 ratings\n", + " - 70751 with 1 ratings\n", + " - 34002 with 1 ratings\n", + " - 2674 with 1 ratings\n", + " - 66200 with 1 ratings\n", + " - 78967 with 1 ratings\n", + " - 57418 with 1 ratings\n", + " - 34608 with 1 ratings\n", + " - 41714 with 1 ratings\n", + " - 78111 with 1 ratings\n", + " - 74089 with 1 ratings\n", + " - 76763 with 1 ratings\n", + " - 43635 with 1 ratings\n", + " - 60135 with 1 ratings\n", + " - 4927 with 1 ratings\n", + " - 3302 with 1 ratings\n", + " - 4383 with 1 ratings\n", + " - 5521 with 1 ratings\n", + " - 4831 with 1 ratings\n", + " - 87383 with 1 ratings\n", + " - 5646 with 1 ratings\n", + " - 4716 with 1 ratings\n", + " - 6671 with 1 ratings\n", + " - 6684 with 1 ratings\n", + " - 7300 with 1 ratings\n", + " - 4606 with 1 ratings\n", + " - 7354 with 1 ratings\n", + " - 7881 with 1 ratings\n", + " - 7883 with 1 ratings\n", + " - 7921 with 1 ratings\n", + " - 8003 with 1 ratings\n", + " - 2631 with 1 ratings\n", + " - 8853 with 1 ratings\n", + " - 4082 with 1 ratings\n", + " - 64321 with 1 ratings\n", + " - 8903 with 1 ratings\n", + " - 25842 with 1 ratings\n", + " - 26180 with 1 ratings\n", + " - 26271 with 1 ratings\n", + " - 97168 with 1 ratings\n", + " - 26564 with 1 ratings\n", + " - 26732 with 1 ratings\n", + " - 26731 with 1 ratings\n", + " - 26835 with 1 ratings\n", + " - 1854 with 1 ratings\n", + " - 30712 with 1 ratings\n", + " - 4106 with 1 ratings\n", + " - 2767 with 1 ratings\n", + " - 96565 with 1 ratings\n", + " - 96530 with 1 ratings\n", + " - 124859 with 1 ratings\n", + " - 118326 with 1 ratings\n", + " - 116887 with 1 ratings\n", + " - 109042 with 1 ratings\n", + " - 106542 with 1 ratings\n", + " - 103543 with 1 ratings\n", + " - 103502 with 1 ratings\n", + " - 99992 with 1 ratings\n", + " - 98279 with 1 ratings\n", + " - 95508 with 1 ratings\n", + " - 2032 with 1 ratings\n", + " - 92198 with 1 ratings\n", + " - 92048 with 1 ratings\n", + " - 89427 with 1 ratings\n", + " - 86028 with 1 ratings\n", + " - 80590 with 1 ratings\n", + " - 43558 with 1 ratings\n", + " - 7895 with 1 ratings\n", + " - 7245 with 1 ratings\n", + " - 4662 with 1 ratings\n", + " - 127319 with 1 ratings\n", + " - 132157 with 1 ratings\n", + " - 135536 with 1 ratings\n", + " - 136654 with 1 ratings\n", + " - 140739 with 1 ratings\n", + " - 127728 with 1 ratings\n", + " - 108795 with 1 ratings\n", + " - 99615 with 1 ratings\n", + " - 99609 with 1 ratings\n", + " - 98933 with 1 ratings\n", + " - 60086 with 1 ratings\n", + " - 8453 with 1 ratings\n", + " - 7260 with 1 ratings\n", + " - 6033 with 1 ratings\n", + " - 1903 with 1 ratings\n", + " - 57845 with 1 ratings\n", + " - 8273 with 1 ratings\n", + " - 6679 with 1 ratings\n", + " - 6022 with 1 ratings\n", + " - 160440 with 1 ratings\n", + " - 143255 with 1 ratings\n", + " - 142997 with 1 ratings\n", + " - 139915 with 1 ratings\n", + " - 59 with 1 ratings\n", + " - 1654 with 1 ratings\n", + " - 96849 with 1 ratings\n", + " - 127114 with 1 ratings\n", + " - 304 with 1 ratings\n", + " - 219 with 1 ratings\n", + " - 160656 with 1 ratings\n", + " - 151307 with 1 ratings\n", + " - 147845 with 1 ratings\n", + " - 142258 with 1 ratings\n", + " - 140247 with 1 ratings\n", + " - 136018 with 1 ratings\n", + " - 128606 with 1 ratings\n", + " - 118898 with 1 ratings\n", + " - 1044 with 1 ratings\n", + " - 109205 with 1 ratings\n", + " - 108076 with 1 ratings\n", + " - 105355 with 1 ratings\n", + " - 104339 with 1 ratings\n", + " - 104321 with 1 ratings\n", + " - 103444 with 1 ratings\n", + " - 98611 with 1 ratings\n", + " - 98473 with 1 ratings\n", + " - 97817 with 1 ratings\n", + " - 697 with 1 ratings\n", + " - 775 with 1 ratings\n", + " - 980 with 1 ratings\n", + " - 1349 with 1 ratings\n", + " - 5223 with 1 ratings\n", + " - 46772 with 1 ratings\n", + " - 27441 with 1 ratings\n", + " - 5182 with 1 ratings\n", + " - 4401 with 1 ratings\n", + " - 4319 with 1 ratings\n", + " - 3487 with 1 ratings\n", + " - 1928 with 1 ratings\n", + " - 4003 with 1 ratings\n", + " - 3960 with 1 ratings\n", + " - 3939 with 1 ratings\n", + " - 3662 with 1 ratings\n", + " - 3661 with 1 ratings\n", + " - 3041 with 1 ratings\n", + " - 2855 with 1 ratings\n", + " - 2091 with 1 ratings\n", + " - 1998 with 1 ratings\n", + " - 1550 with 1 ratings\n", + " - 1369 with 1 ratings\n", + " - 889 with 1 ratings\n", + " - 73344 with 1 ratings\n", + " - 112070 with 1 ratings\n", + " - 106870 with 1 ratings\n", + " - 5038 with 1 ratings\n", + " - 4608 with 1 ratings\n", + " - 5122 with 1 ratings\n", + " - 89300 with 1 ratings\n", + " - 85316 with 1 ratings\n", + " - 152173 with 1 ratings\n", + " - 114766 with 1 ratings\n", + " - 96815 with 1 ratings\n", + " - 6414 with 1 ratings\n", + " - 90357 with 1 ratings\n", + " - 88272 with 1 ratings\n", + " - 48972 with 1 ratings\n", + " - 40833 with 1 ratings\n", + " - 6940 with 1 ratings\n", + " - 5696 with 1 ratings\n", + " - 2817 with 1 ratings\n", + " - 5841 with 1 ratings\n", + " - 1624 with 1 ratings\n", + " - 8871 with 1 ratings\n", + " - 8019 with 1 ratings\n", + " - 966 with 1 ratings\n", + " - 9005 with 1 ratings\n", + " - 8745 with 1 ratings\n", + " - 8057 with 1 ratings\n", + " - 6356 with 1 ratings\n", + " - 408 with 1 ratings\n", + " - 3531 with 1 ratings\n", + " - 54785 with 1 ratings\n", + " - 6665 with 1 ratings\n", + " - 32797 with 1 ratings\n", + " - 32892 with 1 ratings\n", + " - 6114 with 1 ratings\n", + " - 4863 with 1 ratings\n", + " - 4500 with 1 ratings\n", + " - 44613 with 1 ratings\n", + " - 1181 with 1 ratings\n", + " - 5773 with 1 ratings\n", + " - 6103 with 1 ratings\n", + " - 8253 with 1 ratings\n", + " - 69746 with 1 ratings\n", + " - 63826 with 1 ratings\n", + " - 136592 with 1 ratings\n", + " - 36289 with 1 ratings\n", + " - 106441 with 1 ratings\n", + " - 68959 with 1 ratings\n", + " - 83506 with 1 ratings\n", + " - 69685 with 1 ratings\n", + " - 33558 with 1 ratings\n", + " - 56069 with 1 ratings\n", + " - 8790 with 1 ratings\n", + " - 98829 with 1 ratings\n", + " - 26422 with 1 ratings\n", + " - 118082 with 1 ratings\n", + " - 1750 with 1 ratings\n", + " - 5343 with 1 ratings\n", + " - 1564 with 1 ratings\n", + " - 31422 with 1 ratings\n", + " - 25962 with 1 ratings\n", + " - 6559 with 1 ratings\n", + " - 2835 with 1 ratings\n", + " - 56095 with 1 ratings\n", + " - 70159 with 1 ratings\n", + " - 2552 with 1 ratings\n", + " - 72104 with 1 ratings\n", + " - 95858 with 1 ratings\n", + " - 6920 with 1 ratings\n", + " - 5440 with 1 ratings\n", + " - 3657 with 1 ratings\n", + " - 2173 with 1 ratings\n", + " - 3240 with 1 ratings\n", + " - 92681 with 1 ratings\n", + " - 80615 with 1 ratings\n", + " - 1826 with 1 ratings\n", + " - 57951 with 1 ratings\n", + " - 51698 with 1 ratings\n", + " - 56336 with 1 ratings\n", + " - 27899 with 1 ratings\n", + " - 72683 with 1 ratings\n", + " - 126106 with 1 ratings\n", + " - 8840 with 1 ratings\n", + " - 7407 with 1 ratings\n", + " - 6739 with 1 ratings\n", + " - 6579 with 1 ratings\n", + " - 2210 with 1 ratings\n", + " - 8722 with 1 ratings\n", + " - 145307 with 1 ratings\n", + " - 120392 with 1 ratings\n", + " - 47714 with 1 ratings\n", + " - 110110 with 1 ratings\n", + " - 6203 with 1 ratings\n", + " - 6794 with 1 ratings\n", + " - 4371 with 1 ratings\n", + " - 4077 with 1 ratings\n", + " - 3799 with 1 ratings\n", + " - 1896 with 1 ratings\n", + " - 25839 with 1 ratings\n", + " - 49394 with 1 ratings\n", + " - 34129 with 1 ratings\n", + " - 133195 with 1 ratings\n", + " - 57038 with 1 ratings\n", + " - 56869 with 1 ratings\n", + " - 49299 with 1 ratings\n", + " - 48165 with 1 ratings\n", + " - 5560 with 1 ratings\n", + " - 5568 with 1 ratings\n", + " - 65088 with 1 ratings\n", + " - 112911 with 1 ratings\n", + " - 71525 with 1 ratings\n", + " - 51939 with 1 ratings\n", + " - 33646 with 1 ratings\n", + " - 5092 with 1 ratings\n", + " - 2824 with 1 ratings\n", + " - 27075 with 1 ratings\n", + " - 80599 with 1 ratings\n", + " - 74486 with 1 ratings\n", + " - 460 with 1 ratings\n", + " - 26915 with 1 ratings\n", + " - 2839 with 1 ratings\n", + " - 78316 with 1 ratings\n", + " - 5054 with 1 ratings\n", + " - 3737 with 1 ratings\n", + " - 939 with 1 ratings\n", + " - 54787 with 1 ratings\n", + " - 53999 with 1 ratings\n", + " - 6800 with 1 ratings\n", + " - 4200 with 1 ratings\n", + " - 6757 with 1 ratings\n", + " - 82167 with 1 ratings\n", + " - 27815 with 1 ratings\n", + " - 7316 with 1 ratings\n", + " - 98369 with 1 ratings\n", + " - 93498 with 1 ratings\n", + " - 89047 with 1 ratings\n", + " - 84160 with 1 ratings\n", + " - 54281 with 1 ratings\n", + " - 4688 with 1 ratings\n", + " - 130490 with 1 ratings\n", + " - 4350 with 1 ratings\n", + " - 25901 with 1 ratings\n", + " - 74156 with 1 ratings\n", + " - 72479 with 1 ratings\n", + " - 71490 with 1 ratings\n", + " - 94939 with 1 ratings\n", + " - 8142 with 1 ratings\n", + " - 5826 with 1 ratings\n", + " - 100517 with 1 ratings\n", + " - 104726 with 1 ratings\n", + " - 6211 with 1 ratings\n", + " - 5796 with 1 ratings\n", + " - 148652 with 1 ratings\n", + " - 112767 with 1 ratings\n", + " - 54910 with 1 ratings\n", + " - 27857 with 1 ratings\n", + " - 26025 with 1 ratings\n", + " - 140755 with 1 ratings\n", + "\n", + "----------------------------------------------------\n", + "\n", + "°The lowest rated movie :\n", + " title genres\n", + "movieId \n", + "5521 Principal, The (1987) Action|Crime|Drama\n", + "With 1 rating(s)\n", + "\n", + "°The best rated movie :\n", + " title genres\n", + "movieId \n", + "1564 For Roseanna (Roseanna's Grave) (1997) Comedy|Drama|Romance\n", + "With 1 rating(s)\n" + ] + } + ], + "source": [ + "# Number of ratings of the most rated movie(s)\n", + "value_counts = df_ratings['movieId'].value_counts()\n", + "\n", + "max_occ = value_counts.max()\n", + "max_indexes = []\n", + "for index, count in value_counts.iteritems():\n", + " if count == max_occ:\n", + " max_indexes.append(index)\n", + "print(\"The movie(s) with the most ratings is/are :\")\n", + "for index in max_indexes:\n", + " print(f\" -\", index, \"with\", max_occ, \"ratings\")\n", + " \n", + "# Number of ratings of the less rated movie(s)\n", + "min_occ = value_counts.min()\n", + "min_indexes = []\n", + "for index, count in value_counts.iteritems():\n", + " if count == min_occ:\n", + " min_indexes.append(index)\n", + "print(\"\\nThe movie(s) with the less ratings is/are :\")\n", + "for index in min_indexes:\n", + " print(f\" -\", index, \"with\", min_occ, \"ratings\")\n", + "\n", + "print(\"\\n----------------------------------------------------\")\n", + "\n", + "# Best and lowest rated movie (based on the average)\n", + "mean_ratings = df_ratings.groupby('movieId')[['rating']].mean()\n", + "lowest_rated = mean_ratings['rating'].idxmin()\n", + "print(f\"\\n°The lowest rated movie :\")\n", + "print(df_items[df_items.index == lowest_rated])\n", + "nbr_ratings = 0\n", + "for id in df_ratings.iloc[:,1] :\n", + " if id == lowest_rated :\n", + " nbr_ratings += 1\n", + "print(\"With\", nbr_ratings, \"rating(s)\")\n", + "\n", + "print(f\"\\n°The best rated movie :\")\n", + "best_rated = mean_ratings['rating'].idxmax()\n", + "print(df_items[df_items.index == best_rated])\n", + "nbr_ratings = 0\n", + "for id in df_ratings.iloc[:,1] :\n", + " if id == best_rated :\n", + " nbr_ratings += 1\n", + "print(\"With\", nbr_ratings, \"rating(s)\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "°All the possible rating values, from smallest value to value highest : [0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0]\n", + "°Number of rated movies per rating value :\n", + "3.0 (1049 movies)\n", + "1.5 (109 movies)\n", + "4.0 (1458 movies)\n", + "3.5 (633 movies)\n", + "0.5 (64 movies)\n", + "1.0 (223 movies)\n", + "2.0 (469 movies)\n", + "2.5 (289 movies)\n", + "5.0 (650 movies)\n", + "4.5 (352 movies)\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkQAAAHICAYAAACvevVkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAABDn0lEQVR4nO3deVyVdf7//+cBZHEBRGUrRKcMlxQnF8Tc5RMu42hjKck4ZoyWA5XZp8xvubUxmplppNmMS2VjTqapUya5QBpuGOWelVspkCHgMgLC9fujH+fTkUVE4By4Hvfb7brdPO/rfZ3r9TrXQZ9e13UOFsMwDAEAAJiYk70LAAAAsDcCEQAAMD0CEQAAMD0CEQAAMD0CEQAAMD0CEQAAMD0CEQAAMD0CEQAAMD0CEQAAMD0CEVCGbdu2yWKxaMaMGXbZf4sWLdSiRQubsRkzZshisWjbtm12qenEiROyWCx68MEH7bL/qlBQUKAZM2aoVatWcnNzk8Vi0dq1a+1dVpWw9/ujKtWF9xpqFxd7FwBUpxMnTqhly5Y2Yx4eHvL29labNm109913a8yYMbrtttuqfN99+vRRUlKSattvxykOYSdOnLBrHdXl1Vdf1cyZM9WrVy+NGDFC9erVU+vWre1dlinV9fcaahcCEUzhtttu05///GdJUl5enjIzM7V792698MILevnll/X000/rpZdeksVisW7TtWtXHT58WE2bNrVLzZs3b7bLfstzyy236PDhw/Ly8rJ3KZW2YcMGNWzYUImJiXJ1dbV3OVUqLi5OUVFRat68ub1LuWl14b2G2oVABFO4/fbbS730tX37do0ePVrx8fFydnbWCy+8YF1Xv359u545qI6zVjerLpxNOXPmjJo0aVLnwpAkNW3a1G4BvqrVhfcaahfuIYKp9ejRQxs3bpSbm5tmz56t06dPW9eVdQ/RsWPHNHbsWLVs2VJubm7y8fFRaGioJk6caL08ZrFYlJSUZP1z8VJ8P8Rv7484fPiw7r33XjVp0kQWi8V6+aC0e4h+65///Kfat28vd3d33XLLLXriiSd04cIFmznl3Qd17T0axY9PnjypkydP2tRdvH1593WcPHlSMTExuuWWW+Tq6qpbb71VMTExOnXqVIm5ffr0kcVisd7P06JFC7m5uemOO+7Qm2++WWbPZVm6dKnCwsLUsGFDNWzYUGFhYVq2bJnNnOL7a44fP27TX3mvcTGLxaI+ffrop59+0qhRo9S0aVM1atRIgwcP1g8//CBJOnz4sIYNGyYfHx81atRI9913nzIyMkp9vvXr16tv377y8vKSh4eHQkNDNXfuXF29etU65+TJk3JyclK/fv1KfY6CggI1bdpUQUFBKioqsumxtHuIvvnmG0VFRSkgIECurq4KDg7Wo48+ql9++eW6/Rcrfk9mZ2crLi5OQUFBcnFxsb7WqampiouL05133mntrX379vr73/+ugoIC6/PczHutMu+dc+fOafz48fL19VX9+vXVpUsXrVmzRsuWLZPFYinxXtm6dasGDhyowMBAubm5yc/PTz179tTixYsr/Fqh9uEMEUwvJCREI0aM0Lvvvqu1a9fq0UcfLXPumTNn1LVrV126dEmDBw/WyJEjdenSJR07dkxvvvmm5syZIxcXF02fPl3Lli3TyZMnNX36dOv2HTt2tHm+7777Tt26dVP79u314IMP6pdffqnQmYu5c+dq8+bNGjlypAYPHqzPP/9c8+bN086dO5WcnKx69erd8Ovg7e2t6dOna968eZKkiRMnWtf16dOn3G2//fZb9ejRQz///LOGDBmidu3a6cCBA1qyZInWr1+v7du364477iix3QMPPKDdu3dr4MCBcnZ21qpVqxQbG6t69epp3LhxFar7scce04IFC3TLLbcoJiZGkrR69WqNHTtWX331lV5//XWbHq7tz9vbu0L7OX/+vHr06CF/f3+NGTNG3377rTZs2KAjR47o448/Vs+ePdWpUyc99NBDSk1N1erVq5WVlaUtW7bYPM/cuXP15JNPysfHR6NGjVKDBg20bt06Pfnkk/riiy/00UcfyWKxKDg4WL169VJSUpJ+/PFH3XrrrTbP88knn+iXX37R5MmT5eRU/v9t161bpxEjRsjJyUlDhw5VUFCQDh06pDfeeEOfffaZdu3apcaNG1fodcjLy1O/fv108eJF/fGPf5SLi4v8/PwkSW+//bbWr1+vXr16adCgQbp8+bK2bdumKVOmaM+ePVq9erX1Na/se61YRd87Fy9eVO/evXXo0CF1795dvXr10o8//qioqChFRkaWeN7//Oc/GjJkiLy9vTV06FAFBATo559/1tdff613331X48ePr1B9qIUMoA47fvy4IcmIjIwsd94///lPQ5IxevRo69jWrVsNScb06dOtY/PnzzckGfPmzSvxHL/88ovN4969extl/YgV1yXJmDZtWqlzgoODjeDgYJux6dOnG5IMV1dX4+uvv7aOFxUVGaNGjTIkGXPmzCm3h2trGDNmzHX3e71t+vbta0gy3nrrLZvxhIQEQ5LRr18/m/Hi1yYsLMzIycmxjh85csRwcXExQkJCSt3/tZKSkgxJRps2bYzs7GzreFZWlnHHHXcYkozk5OQK91eW4mP1xBNP2IxPmDDBkGR4e3vbvCeKioqMQYMGGZKM1NRU6/h3331nuLi4GL6+vsapU6es41euXDF69OhhSDLeeecd6/g//vEPQ5Ixa9asEjUNHz7ckGQcOHDAOlb8/ti6dat17Ny5c4anp6dxyy23GCdOnLB5jn/961+GJCMuLq5Cr0NwcLD15+ny5csl1p88edK4evWqzVhRUZHx0EMPGZKM7du3l3i+G32v3eh757nnnjMkGePHj7cZ//zzz63HdenSpdbxP/3pT4YkIy0trURN586dK7VW1A1cMgMkBQYGSvr11HpFeHh4lBjz8fG54f36+/vr2WefveHt/vKXv6hDhw7WxxaLRS+//LKcnZ1LnP6vbqdOndLWrVvVtm3bEmd1HnnkEbVu3VpbtmyxuRxZLD4+Xp6entbHISEhuvvuu3X06NESl/9Ks3z5ckm/Xir67c23jRs3tp6Zq6rXo2HDhnrxxRdtxh544AFJUpMmTfTYY49Zxy0Wi6KioiRJX3/9tXX8/fff19WrV/Xkk08qKCjIOu7m5qZZs2aVqPe+++6Tu7u73nvvPZv9Zmdna8OGDerYsaPatWtXbt3vvPOOcnNzFR8fr+DgYJt1UVFRuuuuu7Ry5crrtW9j9uzZpf4MNG/eXM7OzjZjFotFsbGxkqTPP//8hvZTnoq+d9577z25urrq+eeft9m+f//+uueee8p8/tL6a9KkSRVUDkfFJTPgBgwZMkRTpkxRbGysNm/erAEDBqh379763e9+V6nnCw0NrdTNvT179iwxFhwcrKCgIB08eFD5+fk1dtNwWlqaJKl37942n9KTJCcnJ/Xq1UtHjhxRWlqaTQiQpE6dOpV4vuJLQ9nZ2WrUqFG5+/7qq68klX6ZpW/fvjb13axWrVqpfv36NmMBAQGSpA4dOpTovXjdmTNnKlRveHi43N3dber18vLSH//4R61atUpff/21QkNDJUn//ve/lZeXp9GjR1+37p07d0qSdu3ape+//77E+itXrujcuXM6d+5chW7Idnd3V/v27Utdl5+frzfeeEMrV67UkSNHdPHiRZuvnfjta3GzKvLeyc3N1YkTJ9S2bVvrZb3fuvvuu7Vp0yabsaioKH300Ufq1q2bRo0apf79+6tnz5515mZ1lI1ABOj//qJu1qxZufNatGihnTt3asaMGfrkk0+0atUqSVLr1q31/PPP6/7777+h/Zb2l/TNbOfn56cTJ07owoULNfa/2dzc3HJrKg4GxfN+67f/wy/m4vLrX0uFhYUV2reTk1Opx83Pz08Wi6XU/VZGebWWt+63NxOX91pZLBb5+fnpp59+shkfPXq0Vq1apffee88aiN599105Oztr1KhR1607KytLkpSQkFDuvEuXLlXoH31fX98S4a/Yfffdp/Xr1+uOO+7QyJEj5evrq3r16ik7O1uvv/668vLyrvv8FVWR907x6+3r61vqc5R2HO6//36tXbtWc+fO1aJFi5SQkCCLxaK+ffvq1VdfLXEfIOoOLpkBkvVTOV26dLnu3DvvvFMffvihsrKylJKSomnTpik9PV0jR47Ujh07bmi/Zf3Dcj1lfXopIyNDFovFemal+Gbb3356qVhOTk6l9n2t4n+YyqopPT3dZl5V8vT0VFFRkX7++ecS6zIzM2UYRrXst7LKe60Mw1BGRkaJegcMGKBmzZrpX//6l4qKinTixAlt375dERER8vf3r/A+9+/fL8MwylyuvZxWlrLes3v27NH69esVGRmpQ4cO6e2339ZLL72kGTNmWC8f1rTi3jMzM0tdX9Z7dujQoUpKStL58+f16aef6q9//au2bdumAQMGKDs7u7rKhZ0RiGB63377rVatWiU3Nzfde++9Fd6uXr166tatm2bOnKn58+fLMAxt2LDBur74XoqKnOm4UV988UWJsZMnT+r06dNq166d9XJZ8SeHrj3rIP3f5ZtrOTs731DNxf9jTk5OLvGt3IZhKDk52WZeVfr9738vSaV+zLx4zJH+R19evbt27dKVK1dK1Ovi4qKoqCj99NNP2rp1q1asWCHDMKxfNHo9YWFhkqSUlJSbqv16ii/HDR48uMR9RKW9X6Ubf6/dKE9PT7Vo0ULfffddqaHoyy+/LHf7Ro0aacCAAVq8eLEefPBBZWRkaNeuXdVVLuyMQART27FjhyIjI5WXl6dnnnlGt9xyS7nzU1NTS70EU/w/TXd3d+tY8U3Wpd1MfLPeeecdffPNN9bHhmHo//2//6fCwkKb720JCQlRo0aNtG7dOuulk+J6r71B+Ld1nzt3TleuXKlQLc2bN1ffvn118OBBLVmyxGbd4sWLdfjwYfXr16/E/UNVYcyYMZKkmTNn2hyXnJwczZw502aOIxg1apRcXFw0d+5cm/tp8vPzNXnyZEkq9Tueiu8Vevfdd/Xuu++qQYMGFQ7vY8eOVaNGjfTss8/q4MGDJdZfvnzZep/RzSg+w7R9+3ab8YMHDyo+Pr7UbW70vVYZ0dHRys/Pt/n6C+nXUPrZZ5+VmJ+cnFxqSCsOVL/9GUfdwj1EMIXvvvvO+oVv+fn51l/dsX//fjk7O+u5554r8Rdmad5991299dZb6tWrl2677TZ5enrq0KFD+uSTT+Tj46OxY8da5/br108ffvihhg8froEDB8rd3V2hoaEaMmTITfcTGRmp8PBwRUVFqVmzZtq8ebP27t2rbt262XyPkqurqx599FG9/PLLuuuuuzR06FBduHBB69evV+/evUu9ybZfv37au3evBg4cqJ49e8rV1VW9evVSr169yqxn4cKF6tGjh8aNG6f169erbdu2OnjwoNatW6dmzZpp4cKFN91zaXr16qVHH31UCxYs0J133qnhw4fLMAytXr1aP/74ox577LFy665pt912m2bNmqUnn3xSHTp00IgRI9SgQQOtX79eR48e1dChQ0s989OlSxeFhITo/fffV0FBgUaPHq0GDRpUaJ/Fl9vuv/9+hYaGasCAAWrdurXy8vJ04sQJJSUlqXv37tq4ceNN9da1a1d17dpVq1at0tmzZ9WtWzedOnVK69at0+DBg/Xhhx+W2KYy77UbNXnyZK1evVqLFi3SgQMH1LNnT/34449atWqVhgwZovXr19t8j9Njjz2mM2fOqEePHmrRooUsFou2b9+u3bt3q1u3burRo0eV1QYHU/Of9Adqzm+/76d48fDwMAICAoy+ffsaU6dONb777rtSty3tO3x27txpPPzww8add95peHt7Gx4eHkarVq2MuLg44+TJkzbbFxQUGE8//bTRvHlzw8XFxeY7Vcr6jpXfKu97iLZu3Wq8/fbbRrt27Qw3NzcjICDAePzxx43c3NwS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FxenqKgoBQYGSpJGjRolV1dXxcTE6ODBg/rggw/0+uuva9KkSXbqGgAAOBq7fux+79696tu3r/VxcUgZM2aMli1bpqefflqXLl3S+PHjlZ2drR49emjjxo1yd3e3brNixQrFxcWpf//+cnJy0vDhwzV//nzrei8vL23atEmxsbHq1KmTmjZtqmnTpvGRewAAYGUxDMOwdxGOLjc3V15eXsrJyeF+IsAkQudMt3cJ5fr6f2fau4QaNfZTxz2rv3TgXHuXgDLcyL/fDnsPEQAAQE0hEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANMjEAEAANOrVCDq16+fsrOzS4zn5uaqX79+N1sTAABAjapUINq2bZvy8/NLjF+5ckVffPHFTRcFAABQk1xuZPI333xj/fOhQ4eUnp5ufVxYWKiNGzfqlltuqbrqAAAAasANBaKOHTvKYrHIYrGUemnMw8NDCxYsqLLiAAAAasINXTI7fvy4vv/+exmGod27d+v48ePW5aefflJubq4eeuihKiuusLBQU6dOVcuWLeXh4aHbbrtNL7zwggzDsM4xDEPTpk1TQECAPDw8FBERoWPHjtk8T1ZWlqKjo+Xp6Slvb2/FxMTo4sWLVVYnAACo3W7oDFFwcLAkqaioqFqKudasWbO0cOFCLV++XO3atdPevXs1duxYeXl56bHHHpMkzZ49W/Pnz9fy5cvVsmVLTZ06VZGRkTp06JDc3d0lSdHR0Tp79qwSExNVUFCgsWPHavz48Xr//fdrpA8AAODYbigQ/daxY8e0detWZWZmlghI06ZNu+nCJOnLL7/U0KFDNXjwYElSixYt9K9//Uu7d++W9OvZoXnz5um5557T0KFDJUnvvPOO/Pz8tHbtWkVFRenw4cPauHGj9uzZo86dO0uSFixYoEGDBmnOnDkKDAyskloBAEDtValA9Pbbb2vChAlq2rSp/P39ZbFYrOssFkuVBaLu3btr8eLF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tm1biWNhsViUnp5eMwWXIj4+Xl26dFGjRo3k6+urYcOG6ejRo9fd7t///rdat24td3d3tW/fXp988kkNVFu2yvThaD8bCxcuVIcOHaxfLBceHq5PP/203G0c7ThIN96Hox2H0vz973+XxWLRxIkTy53niMfjtyrShyMejxkzZpSoqXXr1uVuY89jQSCqIR988IEmTZqk6dOna9++fQoNDVVkZKQyMzPL3MbT01Nnz561LidPnqzBiku6dOmSQkNDlZCQUKH5x48f1+DBg9W3b1+lpaVp4sSJ+utf/6rPPvusmist3432Uezo0aM2x8PX17eaKry+pKQkxcbGaufOnUpMTFRBQYHuueceXbp0qcxtvvzySz3wwAOKiYnRV199pWHDhmnYsGE6cOBADVZuqzJ9SI71s3Hrrbfq73//u1JTU7V3717169dPQ4cO1cGDB0ud74jHQbrxPiTHOg7X2rNnj9566y116NCh3HmOejyKVbQPyTGPR7t27Wxq2r59e5lz7X4squbXp+J6unbtasTGxlofFxYWGoGBgUZ8fHyp85cuXWp4eXnVUHU3TpKxZs2acuc8/fTTRrt27WzGRo4caURGRlZjZTemIn1s3brVkGScP3++RmqqjMzMTEOSkZSUVOacESNGGIMHD7YZCwsLMx5++OHqLq/CKtKHo/9sGIZhNG7c2PjHP/5R6rracByKldeHIx+HCxcuGK1atTISExON3r17G48//niZcx35eNxIH454PKZPn26EhoZWeL69jwVniGpAfn6+UlNTFRERYR1zcnJSRESEUlJSytzu4sWLCg4OVlBQ0HX/p+aIUlJSbHqWpMjIyHJ7dmQdO3ZUQECA/ud//kc7duywdzk2cnJyJEk+Pj5lzqkNx6MifUiO+7NRWFiolStX6tKlSwoPDy91Tm04DhXpQ3Lc4xAbG6vBgweXeJ1L48jH40b6kBzzeBw7dkyBgYH63e9+p+joaJ06darMufY+FgSiGnDu3DkVFhaW+DUhfn5+Zd6HEhISoiVLlujjjz/We++9p6KiInXv3l0//vhjTZRcJdLT00vtOTc3V//973/tVNWNCwgI0KJFi7R69WqtXr1aQUFB6tOnj/bt22fv0iT9+ouKJ06cqLvvvlt33nlnmfPKOh72vBfqtyrahyP+bOzfv18NGzaUm5ubHnnkEa1Zs0Zt27Ytda4jH4cb6cMRj4MkrVy5Uvv27VN8fHyF5jvq8bjRPhzxeISFhWnZsmXauHGjFi5cqOPHj6tnz566cOFCqfPtfSxM9as7apPw8HCb/5l1795dbdq00VtvvaUXXnjBjpWZT0hIiEJCQqyPu3fvru+//16vvfaa3n33XTtW9qvY2FgdOHCg3GvztUFF+3DEn42QkBClpaUpJydHH374ocaMGaOkpKQyw4SjupE+HPE4nD59Wo8//rgSExPtfkPxzahMH454PAYOHGj9c4cOHRQWFqbg4GCtWrVKMTExdqmpPASiGtC0aVM5OzsrIyPDZjwjI0P+/v4Veo569erp97//vb777rvqKLFa+Pv7l9qzp6enPDw87FRV1ejatatDBJC4uDht2LBBycnJuvXWW8udW9bxqOh7sDrdSB/XcoSfDVdXV91+++2SpE6dOmnPnj16/fXX9dZbb5WY68jH4Ub6uJYjHIfU1FRlZmbqrrvuso4VFhYqOTlZb7zxhvLy8uTs7GyzjSMej8r0cS1HOB7X8vb21h133FFmTfY+FlwyqwGurq7q1KmTNm/ebB0rKirS5s2by70+/1uFhYXav3+/AgICqqvMKhceHm7TsyQlJiZWuGdHlpaWZtdjYRiG4uLitGbNGm3ZskUtW7a87jaOeDwq08e1HPFno6ioSHl5eaWuc8TjUJby+riWIxyH/v37a//+/UpLS7MunTt3VnR0tNLS0koNEY54PCrTx7Uc4Xhc6+LFi/r+++/LrMnux6JGbt2GsXLlSsPNzc1YtmyZcejQIWP8+PGGt7e3kZ6ebhiGYYwePdp45plnrPNnzpxpfPbZZ8b3339vpKamGlFRUYa7u7tx8OBBe7VgXLhwwfjqq6+Mr776ypBkzJ071/jqq6+MkydPGoZhGM8884wxevRo6/wffvjBqF+/vvHUU08Zhw8fNhISEgxnZ2dj48aN9mrBMIwb7+O1114z1q5daxw7dszYv3+/8fjjjxtOTk7G559/bq8WjAkTJhheXl7Gtm3bjLNnz1qXy5cvW+dc+57asWOH4eLiYsyZM8c4fPiwMX36dKNevXrG/v377dGCYRiV68PRfjaeeeYZIykpyTh+/LjxzTffGM8884xhsViMTZs2lVq/Ix4Hw7jxPhztOJTl2k9n1Zbjca3r9eGIx+PJJ580tm3bZhw/ftzYsWOHERERYTRt2tTIzMw0DMPxjgWBqAYtWLDAaN68ueHq6mp07drV2Llzp3Vd7969jTFjxlgfT5w40TrXz8/PGDRokLFv3z47VP1/ij9+fu1SXPeYMWOM3r17l9imY8eOhqurq/G73/3OWLp0aY3Xfa0b7WPWrFnGbbfdZri7uxs+Pj5Gnz59jC1bttin+P9fafVLsnl9r31PGYZhrFq1yrjjjjsMV1dXo127dsZ//vOfmi38GpXpw9F+Nh566CEjODjYcHV1NZo1a2b079/fGiIMo3YcB8O48T4c7TiU5dogUVuOx7Wu14cjHo+RI0caAQEBhqurq3HLLbcYI0eONL777jvrekc7FhbDMIyaORcFAADgmLiHCAAAmB6BCAAAmB6BCAAAmB6BCAAAmB6BCAAAmB6BCAAAmB6BCAAAmB6BCIDptWjRQvPmzbN3GQDsiEAEwDSWLVsmb2/vEuN79uzR+PHja74gAA6D33YPoE7Iz8+Xq6trpbZt1qxZFVcDoLbhDBGAWqlPnz6Ki4vTxIkT1bRpU0VGRmru3Llq3769GjRooKCgIP3tb3/TxYsXJUnbtm3T2LFjlZOTI4vFIovFohkzZkgqecnMYrHoH//4h+69917Vr19frVq10rp162z2v27dOrVq1Uru7u7q27evli9fLovFouzs7Bp6BQBUJQIRgFpr+fLlcnV11Y4dO7Ro0SI5OTlp/vz5OnjwoJYvX64tW7bo6aefliR1795d8+bNk6enp86ePauzZ8/qf//3f8t87pkzZ2rEiBH65ptvNGjQIEVHRysrK0uSdPz4cd13330aNmyYvv76az388MN69tlna6RnANWDS2YAaq1WrVpp9uzZ1schISHWP7do0UIvvviiHnnkEb355ptydXWVl5eXLBaL/P39r/vcDz74oB544AFJ0ssvv6z58+dr9+7dGjBggN566y2FhITolVdese73wIEDeumll6q4QwA1hUAEoNbq1KmTzePPP/9c8fHxOnLkiHJzc3X16lVduXJFly9fVv369W/ouTt06GD9c4MGDeTp6anMzExJ0tGjR9WlSxeb+V27dq1kFwAcAZfMANRaDRo0sP75xIkT+sMf/qAOHTpo9erVSk1NVUJCgqRfb7i+UfXq1bN5bLFYVFRUdHMFA3BYnCECUCekpqaqqKhIr776qpycfv2/3qpVq2zmuLq6qrCw8Kb3FRISok8++cRmbM+ePTf9vADshzNEAOqE22+/XQUFBVqwYIF++OEHvfvuu1q0aJHNnBYtWujixYvavHmzzp07p8uXL1dqXw8//LCOHDmiyZMn69tvv9WqVau0bNkySb+eSQJQ+xCIANQJoaGhmjt3rmbNmqU777xTK1asUHx8vM2c7t2765FHHtHIkSPVrFkzmxuyb0TLli314Ycf6qOPPlKHDh20cOFC66fM3NzcbroXADXPYhiGYe8iAKC2e+mll7Ro0SKdPn3a3qUAqATuIQKASnjzzTfVpUsXNWnSRDt27NArr7yiuLg4e5cFoJIIRABQCceOHdOLL76orKwsNW/eXE8++aSmTJli77IAVBKXzAAAgOlxUzUAADA9AhEAADA9AhEAADA9AhEAADA9AhEAADA9AhEAADA9AhEAADA9AhEAADA9AhEAADC9/w9PjhpDTshxNgAAAABJRU5ErkJggg==\n", + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "°Number of movies that were not rated at all : 78\n" + ] + } + ], + "source": [ + "# All the possible rating values, from smallest value to value highest.\n", + "list_ratings_values = []\n", + "for i in df_ratings.iloc[:, 2]:\n", + " if i not in list_ratings_values :\n", + " list_ratings_values.append(i)\n", + "print(f\"°All the possible rating values, from smallest value to value highest :\", sorted(list_ratings_values))\n", + "\n", + "print(f\"°Number of rated movies per rating value :\")\n", + "for value in list_ratings_values :\n", + " count = 0\n", + " for rating in df_ratings.iloc[:, 2]:\n", + " if rating == value :\n", + " count += 1\n", + " print(str(value) + \" (\" + str(count) + \" movies)\")\n", + " \n", + "sns.countplot(x=\"rating\", data=df_ratings, palette=\"viridis\")\n", + "plt.title(\"Distribution of movie ratings\", fontsize=14)\n", + "plt.show()\n", + "\n", + "#----------------------------------------------\n", + "\n", + "# Number of movies that were not rated at all\n", + "not_rated_movies = n_movies - unique_movies #total movies - rated movies \n", + "print(f\"°Number of movies that were not rated at all :\", not_rated_movies)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 3 - Long-tail property" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1240 75\n", + "858 72\n", + "527 71\n", + "500 61\n", + "1208 60\n", + "590 59\n", + "1073 57\n", + "2987 56\n", + "2011 54\n", + "1225 50\n", + "923 45\n", + "6333 43\n", + "2804 41\n", + "1219 40\n", + "4979 37\n", + "1250 36\n", + "899 34\n", + "2717 33\n", + "784 32\n", + "2006 31\n", + "3504 30\n", + "6537 29\n", + "1345 28\n", + "8528 27\n", + "2724 26\n", + "3101 25\n", + "2881 24\n", + "1172 23\n", + "2087 22\n", + "3 21\n", + "2942 20\n", + "1945 19\n", + "6323 18\n", + "2739 17\n", + "2146 16\n", + "56782 15\n", + "125 14\n", + "1515 13\n", + "3264 12\n", + "4467 11\n", + "109374 10\n", + "3701 9\n", + "2995 8\n", + "1264 7\n", + "1821 6\n", + "1942 5\n", + "8620 4\n", + "4191 3\n", + "2500 2\n", + "2128 1\n", + "Name: movieId, dtype: int64\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAG0CAYAAAAozc0BAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAABZsklEQVR4nO3dd1xT9+I+8CcBEmbC3nuouBWrIk7A4mrdtta6V62KtevW+7ut9t7e2vVt3au2aK12aNVqW2tb3Io4cdRRNihLQbbMnN8fhFwpoIiBk8Dzfr3yavPJyTkPYeTxnM85kQiCIICIiIhID0nFDkBERETUWCwyREREpLdYZIiIiEhvscgQERGR3mKRISIiIr3FIkNERER6i0WGiIiI9BaLDBEREektFhkiIiLSWywyJLojR45AIpFg165dom7/yJEjmrFp06bB09OzWbbv6emJadOmae5v2bIFEokE586da5btDxw4EAMHDmyWbTVWZmYmxo0bBxsbG0gkEqxYsUKUHMuWLYNEIhFl2wCwbds2tGvXDkZGRrC0tBQth65KSkqCRCLBli1bxI5CzYhFhpqERCJp0O3B8qDvrl27hmXLliEpKUnsKLXocraGWLx4MQ4ePIglS5Zg27ZtGDJkSJNtq7i4GMuWLdO5n80bN25g2rRp8PHxweeff45NmzaJHYlIJxiKHYBapm3bttW4/9VXX+H333+vNe7v74/r1683Z7QG+fzzz6FSqR7rOdeuXcO7776LgQMHPtbenJs3b0Iqbdp/Uzws22+//dak29aGQ4cOYeTIkXj99debfFvFxcV49913AaDWnqp//etfeOutt5o8Q12OHDkClUqFlStXwtfXV5QMus7DwwP379+HkZGR2FGoGbHIUJN48cUXa9w/ffo0fv/991rjAHSyyDT1H0JBEFBSUgITExPI5fIm3dajyGQyUbffEFlZWY0+lFJRUQGVSqWVr9PQ0BCGhuL82czKygKAR74OD/5stTYSiQTGxsZix6BmxkNLpDNUKhX++9//wtXVFcbGxggJCUFcXFyt5aKjozFkyBAolUqYmppiwIABOHnyZIO2cevWLYwaNQpmZmawt7fH4sWLUVpaWmu5uubIfPvttwgICICFhQUUCgU6deqElStXAqia1zJ+/HgAwKBBg2odOvP09MSIESNw8OBB9OjRAyYmJti4caPm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\n", + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#The distribution of rating frequencies\n", + "\n", + "value_counts1 = df_ratings.iloc[:,1].value_counts() #ratings number of each movie \n", + "#print(value_counts1)\n", + "value_counts2 = value_counts1.drop_duplicates() #handling the possible ties\n", + "print(value_counts2)\n", + "\n", + "plt.plot(value_counts2.values)\n", + "plt.title(\"The distribution of rating frequencies\")\n", + "plt.ylabel(\"Popularity\")\n", + "plt.xlabel(\"Movies\")\n", + "plt.xticks([])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 4 - Matrix sparsity" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of rated movies : 834\n", + "Number of raters : 107\n", + "Number of cells in the sparsity matrix : 89238\n", + "Total number of ratings : 5296\n", + "The value of the ratings matrix sparsity 0.94\n" + ] + } + ], "source": [ - "# -- display relevant informations that can be extracted from the dataset" + "#Sparsity\n", + "\n", + "print(f\"Number of rated movies :\", unique_movies) \n", + "\n", + "print(f\"Number of raters :\", unique_users)\n", + "\n", + "nbr_cells = unique_movies*unique_users\n", + "print(f\"Number of cells in the sparsity matrix :\", nbr_cells)\n", + "\n", + "nbr_specified_ratings = n_ratings\n", + "print(f\"Total number of ratings :\", nbr_specified_ratings)\n", + "\n", + "sparsity = 1 - (nbr_specified_ratings/nbr_cells)\n", + "print(f\"The value of the ratings matrix sparsity\", round(sparsity, 2))" ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAsAAAAKsCAYAAADiGQvOAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAABjX0lEQVR4nO3de3gV5bn//08AOZRDMAgJWIKIKHgCRMWArVZjkWrVr1irpS2KytYCFdGqbLfisfHw/VbBKuxaN9gqonbjsbtQRcVDIyqilaqASjEqAXeRBFACkvn9wc8FiTnNWs/M8zwz79d15bq2a01m7ucww93sdd8rLwiCQAAAAEBKtLIdAAAAABAnEmAAAACkCgkwAAAAUoUEGAAAAKlCAgwAAIBUIQEGAABAqpAAAwAAIFVIgAEAAJAqJMAAAABIFRJgAAAApAoJ8G7uuusu7bPPPmrfvr2GDRumV1991XZIRr3wwgv64Q9/qF69eikvL0+PPfZYnfeDINA111yjnj17qkOHDiotLdWqVavsBGtIWVmZjjjiCHXu3Fk9evTQaaedphUrVtQ5ZuvWrZowYYK6deumTp06afTo0Vq3bp2liHM3c+ZMHXrooerSpYu6dOmikpIS/eUvf8m8n7TxNuTmm29WXl6eJk+enHktaeO+9tprlZeXV+dnwIABmfeTNt7dffLJJ/rpT3+qbt26qUOHDjrkkEP0+uuvZ95P2rNsn332+cZa5+XlacKECZKSudY7duzQ1Vdfrb59+6pDhw7q16+fbrjhBgVBkDkmaessSZs2bdLkyZPVp08fdejQQcOHD9drr72WeT8JYzaRi2zYsEFjxoxRly5d1LVrV5133nnavHlzuEACBEEQBPPmzQvatm0b/Nd//Vfwj3/8I7jggguCrl27BuvWrbMdmjH/8z//E1x11VXB/PnzA0nBo48+Wuf9m2++OcjPzw8ee+yx4K233gpOOeWUoG/fvsGXX35pJ2ADRo4cGcyePTtYvnx58OabbwY/+MEPguLi4mDz5s2ZYy688MKgd+/ewaJFi4LXX389OOqoo4Lhw4dbjDo3TzzxRPDnP/85WLlyZbBixYrg3//934M99tgjWL58eRAEyRtvfa+++mqwzz77BIceemhw8cUXZ15P2rinTZsWHHTQQcHatWszP5999lnm/aSN92sbNmwI+vTpE5xzzjnBkiVLgg8//DBYuHBh8P7772eOSdqzbP369XXW+emnnw4kBc8991wQBMlc65tuuino1q1b8NRTTwWrV68OHnnkkaBTp07B9OnTM8ckbZ2DIAjOPPPM4MADDwwWL14crFq1Kpg2bVrQpUuX4OOPPw6CIBljNpGLnHjiicGgQYOCV155JXjxxReD/fbbLzj77LNDxUEC/P878sgjgwkTJmT+e8eOHUGvXr2CsrIyi1FFp/6mq62tDYqKioLbbrst89rGjRuDdu3aBQ8++KCFCKOxfv36QFKwePHiIAh2jnGPPfYIHnnkkcwx7777biApKC8vtxWmcXvuuWfw+9//PvHj3bRpU9C/f//g6aefDo455phMApzEcU+bNi0YNGhQg+8lcbxfu+KKK4Kjjz660ffT8Cy7+OKLg379+gW1tbWJXeuTTjopGDduXJ3XTj/99GDMmDFBECRznb/44ougdevWwVNPPVXn9cMOOyy46qqrEjnmbHKRd955J5AUvPbaa5lj/vKXvwR5eXnBJ5980uJr8xEISdu2bdPSpUtVWlqaea1Vq1YqLS1VeXm5xcjis3r1alVWVtaZg/z8fA0bNixRc1BVVSVJKigokCQtXbpU27dvrzPuAQMGqLi4OBHj3rFjh+bNm6ctW7aopKQk8eOdMGGCTjrppDrjk5K7zqtWrVKvXr207777asyYMfroo48kJXe8kvTEE0/o8MMP149+9CP16NFDQ4YM0T333JN5P+nPsm3btun+++/XuHHjlJeXl9i1Hj58uBYtWqSVK1dKkt566y299NJLGjVqlKRkrvNXX32lHTt2qH379nVe79Chg1566aVEjrm+loyxvLxcXbt21eGHH545prS0VK1atdKSJUtafK025sL21//+7/9qx44dKiwsrPN6YWGh3nvvPUtRxauyslKSGpyDr9/zXW1trSZPnqwRI0bo4IMPlrRz3G3btlXXrl3rHOv7uN9++22VlJRo69at6tSpkx599FEdeOCBevPNNxM5XkmaN2+e3njjjTqfl/taEtd52LBhmjNnjg444ACtXbtW1113nb7zne9o+fLliRzv1z788EPNnDlTU6ZM0b//+7/rtdde0y9/+Uu1bdtWY8eOTfyz7LHHHtPGjRt1zjnnSErm3pakK6+8UtXV1RowYIBat26tHTt26KabbtKYMWMkJfPfrM6dO6ukpEQ33HCDBg4cqMLCQj344IMqLy/Xfvvtl8gx19eSMVZWVqpHjx513m/Tpo0KCgpCzQMJMFJjwoQJWr58uV566SXboUTugAMO0Jtvvqmqqir96U9/0tixY7V48WLbYUWmoqJCF198sZ5++ulv/PUkqb7+S5gkHXrooRo2bJj69Omjhx9+WB06dLAYWbRqa2t1+OGH69e//rUkaciQIVq+fLlmzZqlsWPHWo4uevfee69GjRqlXr162Q4lUg8//LAeeOABzZ07VwcddJDefPNNTZ48Wb169Ur0Ov/xj3/UuHHjtPfee6t169Y67LDDdPbZZ2vp0qW2Q0scPgIhaa+99lLr1q2/UTW7bt06FRUVWYoqXl+PM6lzMHHiRD311FN67rnn9O1vfzvzelFRkbZt26aNGzfWOd73cbdt21b77befhg4dqrKyMg0aNEjTp09P7HiXLl2q9evX67DDDlObNm3Upk0bLV68WDNmzFCbNm1UWFiYyHHvrmvXrtp///31/vvvJ3adJalnz5468MAD67w2cODAzMc/kvwsW7NmjZ555hmdf/75mdeSuta/+tWvdOWVV+qss87SIYccop/97Ge65JJLVFZWJim569yvXz8tXrxYmzdvVkVFhV599VVt375d++67b2LHvLuWjLGoqEjr16+v8/5XX32lDRs2hJoHEmDtTBaGDh2qRYsWZV6rra3VokWLVFJSYjGy+PTt21dFRUV15qC6ulpLlizxeg6CINDEiRP16KOP6tlnn1Xfvn3rvD906FDtsccedca9YsUKffTRR16Pu77a2lrV1NQkdrzHH3+83n77bb355puZn8MPP1xjxozJ/N9JHPfuNm/erA8++EA9e/ZM7DpL0ogRI77RynDlypXq06ePpOQ+yyRp9uzZ6tGjh0466aTMa0ld6y+++EKtWtVNUVq3bq3a2lpJyV5nSerYsaN69uypzz//XAsXLtSpp56a+DFLLVvXkpISbdy4sc5fxZ999lnV1tZq2LBhLb9YziV8CTFv3rygXbt2wZw5c4J33nknGD9+fNC1a9egsrLSdmjGbNq0KVi2bFmwbNmyQFLwm9/8Jli2bFmwZs2aIAh2th7p2rVr8Pjjjwd///vfg1NPPdW79ir1XXTRRUF+fn7w/PPP12kj9MUXX2SOufDCC4Pi4uLg2WefDV5//fWgpKQkKCkpsRh1bq688spg8eLFwerVq4O///3vwZVXXhnk5eUFf/3rX4MgSN54G7N7F4ggSN64L7300uD5558PVq9eHbz88stBaWlpsNdeewXr168PgiB54/3aq6++GrRp0ya46aabglWrVgUPPPBA8K1vfSu4//77M8ck8Vm2Y8eOoLi4OLjiiiu+8V4S13rs2LHB3nvvnWmDNn/+/GCvvfYKLr/88swxSVznBQsWBH/5y1+CDz/8MPjrX/8aDBo0KBg2bFiwbdu2IAiSMWYTuciJJ54YDBkyJFiyZEnw0ksvBf3796cNWi7uvPPOoLi4OGjbtm1w5JFHBq+88ortkIx67rnnAknf+Bk7dmwQBDvbj1x99dVBYWFh0K5du+D4448PVqxYYTfoHDU0XknB7NmzM8d8+eWXwS9+8Ytgzz33DL71rW8F/+f//J9g7dq19oLO0bhx44I+ffoEbdu2Dbp37x4cf/zxmeQ3CJI33sbUT4CTNu4f//jHQc+ePYO2bdsGe++9d/DjH/+4Ti/cpI13d08++WRw8MEHB+3atQsGDBgQ/O53v6vzfhKfZQsXLgwkNTiOJK51dXV1cPHFFwfFxcVB+/btg3333Te46qqrgpqamswxSVznhx56KNh3332Dtm3bBkVFRcGECROCjRs3Zt5PwphN5CL/+te/grPPPjvo1KlT0KVLl+Dcc88NNm3aFCqOvCDY7WtVAAAAgITjM8AAAABIFRJgAAAApAoJMAAAAFKFBBgAAACpQgIMAACAVCEBBgAAQKqQAAMAACBVSIDrqamp0bXXXquamhrbocSGMadHGsfNmNMhjWOW0jluxpweUY6bL8Kop7q6Wvn5+aqqqlKXLl1shxMLxpyOMUvpHDdjZsxJlsZxM+Z0jFmKdtz8BRgAAACpkpgE+K677tI+++yj9u3ba9iwYXr11VdthwQAAAAHtbEdgAkPPfSQpkyZolmzZmnYsGG64447NHLkSK1YsUI9evRo9vdra2v16aefqnPnztq0aZOknX92T4uvx8qYky+N42bM6ZDGMUvpHDdjTo+qqipJO/M00xLxGeBhw4bpiCOO0G9/+1tJOyeqd+/emjRpkq688spmf//jjz9W7969ow4TAAAAIX3wwQfad999jZ7T+78Ab9u2TUuXLtXUqVMzr7Vq1UqlpaUqLy9v0Tk6d+4sSaqoqEjVh8sBAABcVV1drd69e6tbt27Gz+19Avy///u/2rFjhwoLC+u8XlhYqPfee6/B36mpqanTUuPrjz106dIldAI87YnleuqttTp5UE9dd8rBIaPP7fyNvRf163GweW1TkjCGsMKOOZv9beracYwhCbFGHZOp8/j0vErCs8Hkv01Rx5RNPLb+fXXx3+PGxBlrXl6ekfPsLjFFcGGUlZUpPz8/85PLxx+eemut/rVlm556a63BCFt2/sbei/r1ONi8tilJGENYYceczf42dW1T58nmuj7FGnVMps7j0/MqCc8Gk/82RR1TNvHY+vfVxX+PG+NTrA3xPgHea6+91Lp1a61bt67O6+vWrVNRUVGDvzN16lRVVVVlfioqKrK+/smDeqpbx7Y6eVDPrM+R7fkbey/q1+Ng89qmJGEMYYUdczb729S1TZ0nm+v6FGvUMZk6j0/PqyQ8G0z+2xR1TNnEY+vfVxf/PW6MT7E2JDFFcEceeaTuvPNOSTuL4IqLizVx4sQWFcGltcE0AACAq6LMz7z/DLAkTZkyRWPHjtXhhx+uI488UnfccYe2bNmic88913ZoAAAAcEwiEuAf//jH+uyzz3TNNdeosrJSgwcP1oIFC75RGAcAAAB4/xngr02cOFFr1qxRTU2NlixZomHDhtkOCYCHpj2xXENveFrTnlhuO5Rm+RRr1Hyai2xiTcL4bI3BZDymxuDTeiZVYhJgADDBlwpmya9Yo+bTXNjsHBIH17oDmIzHVpcTmEcCDAC78aWCWfIr1qj5NBc2O4fEwbXuACbjsdXlBOYlogtErugCAQAA4JYo8zP+AgwAAIBUIQEGAABAqpAA1xO2MtPm8abOZapC1sWq1jSOwaY49ret17MZgym2xmaTi+sQls11iPoaJu/dqGPKJp4kP3+i7mThy/OHBLieqL/T3eTxps5lqkLWxarWNI7Bpjj2t63XsxmDKbbGZpOL6xCWzXWI+hom792oY8omniQ/f6LuZOHL84cEuJ6ov9Pd5PGmzmWqQtbFqtY0jsGmOPa3rdezGYMptsZmk4vrEJbNdYj6Gibv3ahjyiaeJD9/ou5k4cvzhy4QogsEAACAa+gCAQAAABhCAgwAAIBUIQHOkWtVjUBapbGymefPLj6tg8nK/STsARfvXV+6QJiUhL0UBglwjlyragTSKo2VzTx/dvFpHUxW7idhD7h47/rSBcKkJOylMEiAc+RaVSOQVmmsbOb5s4tP62Cycj8Je8DFe9eXLhAmJWEvhUEXCNEFAgAAwDV0gQAAAAAMIQEGAABAqpAA5yjJVZNJHlscoq5sTjpTlfVRn8dkRX9Yad0bDcmmoj+Oa5s43kUmOyhkc40wx8fRcSEJXSDCMrmeNsZNApyjJFdNJnlscYi6sjnpTFXWR30ekxX9YaV1bzQkm4r+OK5t4ngXmeygkM01whwfR8eFJHSBCMvketoYNwlwjpJcNZnkscUh6srmpDNVWR/1eUxW9IeV1r3RkGwq+uO4tonjXWSyg0I21whzfBwdF5LQBSIsk+tpY9x0gRBdIAAAAFxDFwgAAADAEBJgAAAApAoJcI58qtgE0Lw03tMujjmNnRWQHnSCsY8EOEc+VWwCaF4a72kXx5zGzgpIDzrB2EcCnCOfKjYBNC+N97SLY05jZwWkB51g7KMLhOgCAQAA4Bq6QAAAAACGkAADAAAgVUiAPUYVKWBeGu+HNI7Zpmzm27U1MjmGqP8tszl3YWNybZ2TjATYY1SRAual8X5I45htyma+XVsjk2OI+t8ym3MXNibX1jnJSIA9RhUpYF4a74c0jtmmbObbtTUyOYao/y2zOXdhY3JtnZOMLhCiCwQAAIBr6AIBAAAAGEICDAAAgFQhAQYAAECqkAC3kK32LaZ/J8rzmBR1TC6OOQlMzqutPeDT3nDxGWArJp/WzUVJmL847mlT+zLJuYMvz1YS4Bay1b7F9O9EeR6Too7JxTEngcl5tbUHfNobLj4DbMXk07q5KAnzF8c9bWpfJjl38OXZSgLcQrbat5j+nSjPY1LUMbk45iQwOa+29oBPe8PFZ4CtmHxaNxclYf7iuKdN7csk5w6+PFtpgybaoAEAALiGNmgAAACAISTAAAAASBUS4BzRrQCIBnu/ecwRbHFx75nsPuDLv+0uroMvSIBzRLcCIBrs/eYxR7DFxb1nsvuAL/+2u7gOviABzhHdCoBosPebxxzBFhf3nsnuA7782+7iOviCLhCiCwQAAIBr6AIBAAAAGEICDAAAgFQhAc4RFZhANLi3EAb7BSa7QETNxZii5tqYSYBzRAUmEA3uLYTBfoHJLhBRczGmqLk2ZhLgHFGBCUSDewthsF9gsgtE1FyMKWqujdn5LhAvvPCCbrvtNi1dulRr167Vo48+qtNOOy3zfhAEmjZtmu655x5t3LhRI0aM0MyZM9W/f/8WX4MuEAAAAG5JdReILVu2aNCgQbrrrrsafP/WW2/VjBkzNGvWLC1ZskQdO3bUyJEjtXXr1pgjBQAAgA/a2A6gOaNGjdKoUaMafC8IAt1xxx36j//4D5166qmSpD/84Q8qLCzUY489prPOOivOUAEAAOAB5/8C3JTVq1ersrJSpaWlmdfy8/M1bNgwlZeXN/p7NTU1qq6urvMDAACSJ47uA651ODApbHcNX7pxeJ0AV1ZWSpIKCwvrvF5YWJh5ryFlZWXKz8/P/PTu3TvSOAEAgB1xdB9wrcOBSWG7a/jSjcPrBDhbU6dOVVVVVeanoqLCdkgAACACcXQfcK3DgUlhu2v40o3D+S4Qu8vLy6vTBeLDDz9Uv379tGzZMg0ePDhz3DHHHKPBgwdr+vTpLTovXSAAAADckuouEE3p27evioqKtGjRosxr1dXVWrJkiUpKSixGBgAAAFc53wVi8+bNev/99zP/vXr1ar355psqKChQcXGxJk+erBtvvFH9+/dX3759dfXVV6tXr151egUDAAAAX3P+L8Cvv/66hgwZoiFDhkiSpkyZoiFDhuiaa66RJF1++eWaNGmSxo8fryOOOEKbN2/WggUL1L59+1jic62qsSlhY/VpbIApcVQ2m7q3fKm2joPNMdt8ttoat8l9b+t+aOq6UXc+sPmc8Wm+o+R8AnzssccqCIJv/MyZM0fSzs8FX3/99aqsrNTWrVv1zDPPaP/9948tPteqGpsSNlafxgaYEkdls6l7y5dq6zjYHLPNZ6utcZvc97buh6auG3XnA5vPGZ/mO0rOJ8Cuc62qsSlhY/VpbIApcVQ2m7q3fKm2joPNMdt8ttoat8l9b+t+aOq6UXc+sPmc8Wm+o+RVF4io0AUCAADALXSBAAAAAAwhAQYAAECqkAA7Lo3V3PCXzep2W5X4PnUf8EmSu9b4FKtPXOyKQky5xRQlEmDHpbGaG/6yWd1uqxLfp+4DPkly1xqfYvWJi11RiCm3mKJEAuy4NFZzw182q9ttVeL71H3AJ0nuWuNTrD5xsSsKMeUWU5ToAiG6QAAAALiGLhAAAACAISTAAAAASBUSYMfF8d3ZVCTDlCTsJZPfbx81F2OyJZsx25qnJKyPzY4vYc/DPdqymEydx8UxN4QE2HFxfHc2FckwJQl7yeT320fNxZhsyWbMtuYpCetjs+NL2PNwj7YsJlPncXHMDSEBdlwc351NRTJMScJeMvn99lFzMSZbshmzrXlKwvrY7PgS9jzcoy2LydR5XBxzQ+gCIbpAAAAAuIYuEAAAAIAhJMAAAABIFRLgelyrUoxDHGP2ZV5drGxGy9AVJXtpHDPqSvKzz7V44AYS4Hpcq1KMQxxj9mVeXaxsRsvQFSV7aRwz6krys8+1eOAGEuB6XKtSjEMcY/ZlXl2sbEbL0BUle2kcM+pK8rPPtXjgBrpAiC4QAAAArqELBAAAAGAICTAAAABShQQYAAAAqUICnCPaqwDRsHVv+XRP+xRr1GzOBetQV9j5iLqFoYt7w2astIzciQQ4R7RXAaJh697y6Z72Kdao2ZwL1qGusPMRdQtDF/eGzVhpGbkTCXCOaK8CRMPWveXTPe1TrFGzOResQ11h5yPqFoYu7g2bsdIycifaoIk2aAAAAK6hDRoAAABgCAkwAAAAUoUEGIiI7xWycWhqjpg/P7Fu6eDiOvvUWcHF+Yuaa2MmAQYi4nuFbByamiPmz0+sWzq4uM4+dVZwcf6i5tqYSYCBiPheIRuHpuaI+fMT65YOLq6zT50VXJy/qLk2ZrpAiC4QAAAArqELBAAAAGAICTAAAABShQTYca5VTSYF8+o+1qh5SZ6jsBX9SZ4LF/k03y7G6mJMaUMC7DjXqiaTgnl1H2vUvCTPUdiK/iTPhYt8mm8XY3UxprQhAXaca1WTScG8uo81al6S5yhsRX+S58JFPs23i7G6GFPa0AVCdIEAAABwDV0gAAAAAENIgAEAAJAqJMA5SkIlZxLGAJjC/QD4yacOIaZicnFsviABzlESKjmTMAbAFO4HwE8+dQgxFZOLY/MFCXCOklDJmYQxAKZwPwB+8qlDiKmYXBybL+gCIbpAAAAAuIYuEAAAAIAhJMAAAABIFRLgeqiobF6S58jk2Jgn968R9XV92QMuxuliTEkWdr6bOj4J927UfIo1qUiA66GisnlJniOTY2Oe3L9G1Nf1ZQ+4GKeLMSVZ2Plu6vgk3LtR8ynWpCIBroeKyuYleY5Mjo15cv8aUV/Xlz3gYpwuxpRkYee7qeOTcO9GzadYk8rpLhBlZWWaP3++3nvvPXXo0EHDhw/XLbfcogMOOCBzzNatW3XppZdq3rx5qqmp0ciRI3X33XersLCwxdehCwQAAIBbUtsFYvHixZowYYJeeeUVPf3009q+fbu+//3va8uWLZljLrnkEj355JN65JFHtHjxYn366ac6/fTTLUYNAAAAlzn9F+D6PvvsM/Xo0UOLFy/Wd7/7XVVVVal79+6aO3euzjjjDEnSe++9p4EDB6q8vFxHHXVUi87LX4ABAADcktq/ANdXVVUlSSooKJAkLV26VNu3b1dpaWnmmAEDBqi4uFjl5eWNnqempkbV1dV1flyV5Gr7bPD96bmJetwmK8lN/o4tPsUKmOLavnctHol/y1zgTQJcW1uryZMna8SIETr44IMlSZWVlWrbtq26du1a59jCwkJVVlY2eq6ysjLl5+dnfnr37h1l6DlJcrV9Nvj+9NxEPW6TleQmf8cWn2IFTHFt37sWj8S/ZS7wJgGeMGGCli9frnnz5uV8rqlTp6qqqirzU1FRYSDCaCS52j4bfH96bqIet8lKcpO/Y4tPsQKmuLbvXYtH4t8yF3jxGeCJEyfq8ccf1wsvvKC+fftmXn/22Wd1/PHH6/PPP6/zV+A+ffpo8uTJuuSSS1p0fj4DDAAA4JbUfgY4CAJNnDhRjz76qJ599tk6ya8kDR06VHvssYcWLVqUeW3FihX66KOPVFJSEne4AAAA8EAb2wE0ZcKECZo7d64ef/xxde7cOfO53vz8fHXo0EH5+fk677zzNGXKFBUUFKhLly6aNGmSSkpKWtwBAgAAAOni9F+AZ86cqaqqKh177LHq2bNn5uehhx7KHHP77bfr5JNP1ujRo/Xd735XRUVFmj9/vsWok4Pq0twwf7lh/oD4xNHBJWouxoRdXFsfpxPgIAga/DnnnHMyx7Rv31533XWXNmzYoC1btmj+/PkqKiqyF3SCUF2aG+YvN8wfEJ84OrhEzcWYsItr6+N0Agy7qC7NDfOXG+YPiE8cHVyi5mJM2MW19fGiC0TU6AIBAADgltR2gQAAAABMIwEGAABAqpAA5yjqqkbXqiaBpPPpnvMp1qjZnIvGrh329WyuYYtr8Uhuzncce8MWn2JtCAlwjqKuanStahJIOp/uOZ9ijZrNuWjs2mFfz+YatrgWj+TmfMexN2zxKdaGkADnKOqqRteqJoGk8+me8ynWqNmci8auHfb1bK5hi2vxSG7Odxx7wxafYm0IXSBEFwgAAADX0AUCAAAAMIQEGAAAAKlCAgwAAIBUIQEGgN2YbO3jS5sgX+JsShLGgGi4uDeibrOG5pEAA8BuTLb28aVNkC9xNiUJY0A0XNwbUbdZQ/NIgAFgNyZb+/jSJsiXOJuShDEgGi7ujajbrKF5tEETbdAAAABcQxs0AAAAwBASYAAAAKQKCTAAJ9mqbqaqGsgN9xB8QAIMwEm2qpupqgZywz0EH5AAA3CSrepmqqqB3HAPwQd0gRBdIAAAAFxDFwgAAADAEBJgAAAApAoJcI6irnalmtZfrF1uws6fqfk2uW6+PB9c3Ku21j8bPsXaGJNjoIPLLo3FFPb1JHBtbCTAOYq62pVqWn+xdrkJO3+m5tvkuvnyfHBxr9pa/2z4FGtjTI6BDi67NBZT2NeTwLWxkQDnKOpqV6pp/cXa5Sbs/Jmab5Pr5svzwcW9amv9s+FTrI0xOQY6uOzSWExhX08C18ZGFwjRBQIAAMA1dIEAAAAADCEBBgAAQKqQALeQrYrNOKomXavMjAPz6gYXK8l9kuQuEIhXEjpZNMbF5z33rn0kwC1kq2IzjqpJ1yoz48C8usHFSnKfJLkLBOKVhE4WjXHxec+9ax8JcAvZqtiMo2rStcrMODCvbnCxktwnSe4CgXgloZNFY1x83nPv2kcXCNEFAgAAwDV0gQAAAAAMIQEGAABAqpAA54gKTGAXk/eDrXvLp3vap1ij5tNc+BRrNtJ479rqFIXskQDniApMYBeT94Ote8une9qnWKPm01z4FGs20njv2uoUheyRAOeICkxgF5P3g617y6d72qdYo+bTXPgUazbSeO/a6hSF7NEFQnSBAAAAcA1dIAAAAABDSIABAACQKiTAjqOC1F8+VUK7uM/CxmSqCtunuaDyfBefxuxitxST94mt/Wryuq7FFMee8ekeMoEE2HFUkPrLp0poF/dZ2JhMVWH7NBdUnu/i05hd7JZi8j6xtV9NXte1mOLYMz7dQyaQADuOClJ/+VQJ7eI+CxuTqSpsn+aCyvNdfBqzi91STN4ntvaryeu6FlMce8ane8gEukCILhAAAACuoQsEAAAAYAgJMAAAAFKFBBiAk3zqomEL1dxuiKOinzVtns0uELa6cZgU9bVd28MkwACc5FMXDVuo5nZDHBX9rGnzbHaBsNWNw6Sor+3aHiYBBuAkn7po2EI1txviqOhnTZtnswuErW4cJkV9bdf2sNNdIGbOnKmZM2fqn//8pyTpoIMO0jXXXKNRo0ZJkrZu3apLL71U8+bNU01NjUaOHKm7775bhYWFoa5DFwgAAAC3pLYLxLe//W3dfPPNWrp0qV5//XUdd9xxOvXUU/WPf/xDknTJJZfoySef1COPPKLFixfr008/1emnn245agAAALjM6b8AN6SgoEC33XabzjjjDHXv3l1z587VGWecIUl67733NHDgQJWXl+uoo45q8Tn5CzAAAIBbUvsX4N3t2LFD8+bN05YtW1RSUqKlS5dq+/btKi0tzRwzYMAAFRcXq7y83GKkAAAAcJnzCfDbb7+tTp06qV27drrwwgv16KOP6sADD1RlZaXatm2rrl271jm+sLBQlZWVTZ6zpqZG1dXVdX6+Ruul5vkUa1gmx5bkeQorCW2fXIvHJPZ9NJI8Fz6NzadYER/nE+ADDjhAb775ppYsWaKLLrpIY8eO1TvvvJPTOcvKypSfn5/56d27d+Y9Wi81z6dYwzI5tiTPU1hJaPvkWjwmse+jkeS58GlsPsWK+DifALdt21b77befhg4dqrKyMg0aNEjTp09XUVGRtm3bpo0bN9Y5ft26dSoqKmrynFOnTlVVVVXmp6KiIvMerZea51OsYZkcW5LnKawktH1yLR6T2PfRSPJc+DQ2n2JFfLwrgjvuuONUXFys6dOnq3v37nrwwQc1evRoSdKKFSs0YMAAiuAAAAA8F2V+1sbo2QybOnWqRo0apeLiYm3atElz587V888/r4ULFyo/P1/nnXeepkyZooKCAnXp0kWTJk1SSUlJqOQXAAAA6eJ0Arx+/Xr9/Oc/19q1a5Wfn69DDz1UCxcu1AknnCBJuv3229WqVSuNHj26zhdhAAAAAI3x7iMQUcjlT+zTnliup95aq5MH9dR1pxxsPLaoz490Yb82z6cxxBGrL/NhM86w1/ZlTk2z9fyxeZ+4uNYuxtQY+gA7LOrqUqpXYRL7tXk+jSGOWH2ZD5txhr22L3Nqmq3nj837xMW1djEmG0iAcxR1dSnVqzCJ/do8n8YQR6y+zIfNOMNe25c5Nc3W88fmfeLiWrsYkw18BEJ0gQAAAHANH4EAAAAADCEBBgAAQKqQAOeI7xgHomHr3uKedgPrAFPi2Ethr9HY8T7te59ibQgJcI6opgSiYeve4p52A+sAU1zsluJT14jG+BRrQ0iAc0Q1JRANW/cW97QbWAeY4mK3FJ+6RjTGp1gbQhcI0QUCAADANXSBAAAAAAwhAQYAAECqkADD+0pOVzGvubFVJW3y/L7sARfjdDGmsJIwBqAxvu9vEmB4X8npKuY1N7aqpE2e35c94GKcLsYUVhLGADTG9/1NAgzvKzldxbzmxlaVtMnz+7IHXIzTxZjCSsIYgMb4vr/pAiG6QAAAALiGLhAAAACAISTAAAAASBUS4Bz5XgUJuMrWvcU97Seb6xb22knYY02NwdZ8+LQHksxWB5+wSIBz5HsVJOAqW/cW97SfbK5b2GsnYY81NQZb8+HTHkgyWx18wiIBzpHvVZCAq2zdW9zTfrK5bmGvnYQ91tQYbM2HT3sgyWx18AmLLhCiCwQAAIBr6AIBAAAAGEICDAAAgFQhAc6Ra1WNcAd7Izd0gUi3JHdWyCZW18bnWjyS3e4DYa/t4vylDQlwjlyraoQ72Bu5oQtEuiW5s0I2sbo2Ptfikex2Hwh7bRfnL21IgHPkWlUj3MHeyA1dINItyZ0VsonVtfG5Fo9kt/tA2Gu7OH9pQxcI0QUCAADANXSBAAAAAAwhAQYAAECqkADXk8bKzCRXW9uUxnkyOeYkdIGIegwu7jFTMfFcilcS5tunjgu27hOTfN8zJMD1pLEyM8nV1jalcZ5MjjkJXSCiHoOLe8xUTDyX4pWE+fap44Kt+8Qk3/cMCXA9aazMTHK1tU1pnCeTY05CF4iox+DiHjMVE8+leCVhvn3quGDrPjHJ9z1DFwjRBQIAAMA1dIEAAAAADCEBBgAAQKqQAOfItarGbCRhDC5iXnNDFwj758+GizFFzafuA40xWdHv2rhdiycp6AKRcq5VNWYjCWNwEfOaG7pA2D9/NlyMKWo+dR9ojMmKftfG7Vo8SUEXiJRzraoxG0kYg4uY19zQBcL++bPhYkxR86n7QGNMVvS7Nm7X4kkKukAkAF0gAAAA3EIXCAAAAMAQEmAAAACkCgkwAAAAUoUEGIBz7Wlc5NMc+RQrYAr7vi7f25RFjQQYgHPtaVzk0xz5FCtgCvu+Lt/blEWNBBiAc+1pXOTTHPkUK2AK+74u39uURY02aKINGgAAgGtogwYAAAAYQgIMAACAVCEBzlESqiZNjcGnufApVpNcG3dT8ZiqYI66EtrmnLq2npK954mL6+Di+jTG5Hy7tnbsDffZmA8S4BwloWrS1Bh8mgufYjXJtXE3FY+pCuaoK6Ftzqlr6ynZe564uA4urk9jTM63a2vH3nCfjfnwKgG++eablZeXp8mTJ2de27p1qyZMmKBu3bqpU6dOGj16tNatWxdbTEmomjQ1Bp/mwqdYTXJt3E3FY6qCOepKaJtz6tp6SvaeJy6ug4vr0xiT8+3a2rE33GdjPrzpAvHaa6/pzDPPVJcuXfS9731Pd9xxhyTpoosu0p///GfNmTNH+fn5mjhxolq1aqWXX365xeemCwQAAIBbUt8FYvPmzRozZozuuece7bnnnpnXq6qqdO+99+o3v/mNjjvuOA0dOlSzZ8/W3/72N73yyisWIwYAAICrvEiAJ0yYoJNOOkmlpaV1Xl+6dKm2b99e5/UBAwaouLhY5eXlcYcJAAAADzifAM+bN09vvPGGysrKvvFeZWWl2rZtq65du9Z5vbCwUJWVlY2es6amRtXV1XV+mmOrkjOOysg0VqPGsZ629obJ6mxTbMZqq5tENnyKNWxMSRZ2HbKZo6jXOo4uED49f6K+hk/PmaRyOgGuqKjQxRdfrAceeEDt27c3dt6ysjLl5+dnfnr37t3s79iq5IyjMjKN1ahxrKetvWGyOtsUm7Ha6iaRDZ9iDRtTkoVdh2zmKOq1jqMLhE/Pn6iv4dNzJqmcToCXLl2q9evX67DDDlObNm3Upk0bLV68WDNmzFCbNm1UWFiobdu2aePGjXV+b926dSoqKmr0vFOnTlVVVVXmp6KiotlYbFVyxlEZmcZq1DjW09beMFmdbYrNWG11k8iGT7GGjSnJwq5DNnMU9VrH0QXCp+dP1Nfw6TmTVE53gdi0aZPWrFlT57Vzzz1XAwYM0BVXXKHevXure/fuevDBBzV69GhJ0ooVKzRgwACVl5frqKOOatF16AIBAADglijzszZGz2ZY586ddfDBB9d5rWPHjurWrVvm9fPOO09TpkxRQUGBunTpokmTJqmkpKTFyS8AAADSxekEuCVuv/12tWrVSqNHj1ZNTY1Gjhypu+++23ZYAAAAcJTTnwFuyPPPP5/5EgxJat++ve666y5t2LBBW7Zs0fz585v8/K9pPnWBiPr72V2sLHUxJrSMrf2XhA4hNq+b5LGZ4lOsjTHZycJmTGHP5WLXjaivHUdMNniXALvGpy4QUX8/u4uVpS7GhJaxtf+S0CHE5nWTPDZTfIq1MSY7WdiMKey5XOy6EfW144jJBhLgHPnUBSLq72d3sbLUxZjQMrb2XxI6hNi8bpLHZopPsTbGZCcLmzGFPZeLXTeivnYcMdngdBeIuNAFAgAAwC1R5mf8BRgAAACpQgIMAACAVCEBzpHvVZCAq+gm0DyfYg0ryWND8iSha1LUXBszCXCOfK+CBFxFN4Hm+RRrWEkeG5InCV2ToubamEmAc+R7FSTgKroJNM+nWMNK8tiQPEnomhQ118ZMFwjRBQIAAMA1dIEAAAAADCEBBgAAQKqQAKNRrlVsAk3h++3Tzea62ewAQLeUXVzcA3SHcBcJMBrlWsUm0BS+3z7dbK6bzQ4AdEvZxcU9QHcId5EAo1GuVWwCTeH77dPN5rrZ7ABAt5RdXNwDdIdwF10gRBcIAAAA19AFAgAAADCEBBgAAACpQgIMwCtRV0n7VIVNhTls8WkvuRgrXWvsIwEG4JWoq6R9qsKmwhy2+LSXXIyVrjX2kQAD8ErUVdI+VWFTYQ5bfNpLLsZK1xr76AIhukAAAAC4hi4QAAAAgCEkwAAAAEgVEuAcUZGOxrB2uWH+mufiHNmqbndxLpLMxfluLCZiRUNIgHNERToaw9rlhvlrnotzZKu63cW5SDIX57uxmIgVDSEBzhEV6WgMa5cb5q95Ls6Rrep2F+ciyVyc78ZiIlY0hC4QogsEAACAa+gCAQAAABhCAgwAAIBUIQEGAABAqpAAO46WKEgrW3vfp3vOp1ijxlzEq6n5du3edXFv2GoXGAcXY2oICbDjaImCtLK1932653yKNWrMRbyamm/X7l0X94atdoFxcDGmhpAAO46WKEgrW3vfp3vOp1ijxlzEq6n5du3edXFv2GoXGAcXY2oIbdBEGzQAAADX0AYNAAAAMIQEGAAAAKlCAlxP2OpFU8f7UjWZdCbXIclrGsfYor4Xoz5PNteI+tpxXDfqdchmDK7NazbxuPY8cXHPhD1/kp9jps9l4/xRIwGuJ2z1oqnjfamaTDqT65DkNY1jbFHfi1GfJ5trRH3tOK4b9TpkMwbX5jWbeFx7nri4Z8KeP8nPMdPnsnH+qGWVAN93333685//nPnvyy+/XF27dtXw4cO1Zs0aY8HZELZ60dTxvlRNJp3JdUjymsYxtqjvxajPk801or52HNeNeh2yGYNr85pNPK49T1zcM2HPn+TnmOlz2Th/1LLqAnHAAQdo5syZOu6441ReXq7S0lLdfvvteuqpp9SmTRvNnz8/ilgjQxcIAAAAt0SZn7XJ5pcqKiq03377SZIee+wxjR49WuPHj9eIESN07LHHmowPAAAAMCqrj0B06tRJ//rXvyRJf/3rX3XCCSdIktq3b68vv/zSXHQAAACAYVklwCeccILOP/98nX/++Vq5cqV+8IMfSJL+8Y9/aJ999jEZn/N8r4IE4C8Xnz9JrujHLi7Ot4t7w8WYTPF9DFklwHfddZeGDx+uzz77TP/93/+tbt26SZKWLl2qs88+22iArvO9ChKAv1x8/iS5oh+7uDjfLu4NF2MyxfcxhE6Av/rqK82YMUNXXHGFHn/8cZ144omZ96677jpdddVVRgN0ne9VkAD85eLzJ8kV/djFxfl2cW+4GJMpvo8hqy4QnTp10vLlyxPzcQe6QAAAALglyvwsq49AHH/88Vq8eLHRQAAAAIA4ZNUGbdSoUbryyiv19ttva+jQoerYsWOd90855RQjwQEAAACmZfURiFatGv/DcV5ennbs2JFTUHHL5U/s055YrqfeWquTB/XUdaccHFGE8BF7IzfMH3yRxr2axjFnw8V5cjGmxjj3EYja2tpGf3xLfnPlexUkosPeyA3zB1+kca+mcczZcHGeXIzJhqwS4N1t3brVRBze8r0KEtFhb+SG+YMv0rhX0zjmbLg4Ty7GZENWH4HYsWOHfv3rX2vWrFlat26dVq5cqX333VdXX3219tlnH5133nlGgrv22mt13XXX1XntgAMO0HvvvSdpZ/J96aWXat68eaqpqdHIkSN19913q7CwMNR16AIBAADgFuc+AnHTTTdpzpw5uvXWW9W2bdvM6wcffLB+//vfGwtOkg466CCtXbs28/PSSy9l3rvkkkv05JNP6pFHHtHixYv16aef6vTTTzd6fQAAACRLVl0g/vCHP+h3v/udjj/+eF144YWZ1wcNGpT566wpbdq0UVFR0Tder6qq0r333qu5c+fquOOOkyTNnj1bAwcO1CuvvKKjjjrKaBwAAABIhqz+AvzJJ59ov/32+8brtbW12r59e85B7W7VqlXq1auX9t13X40ZM0YfffSRpJ1fu7x9+3aVlpZmjh0wYICKi4tVXl7e5DlrampUXV1d5ydbtr733rdrIB1M7iVb+zKN94OLY3YxJrSMa2vnWjySmzGlTVYJ8IEHHqgXX3zxG6//6U9/0pAhQ3IO6mvDhg3TnDlztGDBAs2cOVOrV6/Wd77zHW3atEmVlZVq27atunbtWud3CgsLVVlZ2eR5y8rKlJ+fn/np3bt31jHa+t57366BdDC5l2ztyzTeDy6O2cWY0DKurZ1r8UhuxpQ2WSXA11xzjSZOnKhbbrlFtbW1mj9/vi644ALddNNNuuaaa4wFN2rUKP3oRz/SoYceqpEjR+p//ud/tHHjRj388MM5nXfq1KmqqqrK/FRUVGR9Llvfe+/bNZAOJveSrX2ZxvvBxTG7GBNaxrW1cy0eyc2Y0iarLhCS9OKLL+r666/XW2+9pc2bN+uwww7TNddco+9///umY6zjiCOOUGlpqU444QQdf/zx+vzzz+v8FbhPnz6aPHmyLrnkkhafky4QAAAAbokyP8uqCE6SvvOd7+jpp582GUuzNm/erA8++EA/+9nPNHToUO2xxx5atGiRRo8eLUlasWKFPvroI5WUlMQaFwAAAPyRVQJcUVGhvLw8ffvb35Ykvfrqq5o7d64OPPBAjR8/3lhwl112mX74wx+qT58++vTTTzVt2jS1bt1aZ599tvLz83XeeedpypQpKigoUJcuXTRp0iSVlJTQAQIAAACNyuozwD/5yU/03HPPSZIqKytVWlqqV199VVdddZWuv/56Y8F9/PHHOvvss3XAAQfozDPPVLdu3fTKK6+oe/fukqTbb79dJ598skaPHq3vfve7Kioq0vz5841dH4D/wlZbU53tJ5vr1ti1w75u+ly+MDUGF+eC54+7skqAly9friOPPFKS9PDDD+uQQw7R3/72Nz3wwAOaM2eOseDmzZunTz/9VDU1Nfr44481b9489evXL/N++/btddddd2nDhg3asmWL5s+f32DPYADpFbbamupsP9lct8auHfZ10+fyhakxuDgXPH/clVUCvH37drVr106S9Mwzz+iUU06RtLMP79q1LBoAd4SttqY62082162xa4d93fS5fGFqDC7OBc8fd2XVBWLYsGH63ve+p5NOOknf//739corr2jQoEF65ZVXdMYZZ+jjjz+OItbI0AUCAADALVHmZ1n9BfiWW27Rf/7nf+qYY47R2WefrUGDBkmSnnjiicxHIwAAAAAXZd0HeMeOHaqurtaee+6Zee2f//ynvvWtb6lHjx7GAowDfwEGAABw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AQAAAMTB2S/CAAAAAKJAAgwAAIBUIQEGAABAqpAAA0AK5OXl6bHHHrMdBgA4gQQYACw455xzlJeXpwsvvPAb702YMEF5eXk655xzjF1v7dq1GjVqlLHzAYDPSIABwJLevXtr3rx5+vLLLzOvbd26VXPnzlVxcbHRaxUVFaWuhRIANIYEGAAsOeyww9S7d2/Nnz8/89r8+fNVXFysIUOGZF6rqanRL3/5S/Xo0UPt27fX0Ucfrddee02SVFtbq29/+9uaOXNmnXMvW7ZMrVq10po1ayR98yMQFRUVOvPMM9W1a1cVFBTo1FNP1T//+c/M+88//7yOPPJIdezYUV27dtWIESMy5wIA35EAA4BF48aN0+zZszP//V//9V8699xz6xxz+eWX67//+79133336Y033tB+++2nkSNHasOGDWrVqpXOPvvsb3wh0AMPPKARI0aoT58+37jm9u3bNXLkSHXu3FkvvviiXn75ZXXq1Eknnniitm3bpq+++kqnnXaajjnmGP39739XeXm5xo8fr7y8vGgmAQBiRgIMABb99Kc/1UsvvaQ1a9ZozZo1evnll/XTn/408/6WLVs0c+ZM3XbbbRo1apQOPPBA3XPPPerQoYPuvfdeSdKYMWP08ssv66OPPpK086/C8+bN05gxYxq85kMPPaTa2lr9/ve/1yGHHKKBAwdq9uzZ+uijj/T888+rurpaVVVVOvnkk9WvXz8NHDhQY8eONf6xDACwhQQYACzq3r27TjrpJM2ZM0ezZ8/WSSedpL322ivz/gcffKDt27drxIgRmdf22GMPHXnkkXr33XclSYMHD9bAgQMzfwVevHix1q9frx/96EcNXvOtt97S+++/r86dO6tTp07q1KmTCgoKtHXrVn3wwQcqKCjQOeeco5EjR+qHP/yhpk+frrVr10Y4CwAQLxJgALBs3LhxmjNnju677z6NGzcuq3OMGTMmkwDPnTtXJ554orp169bgsZs3b9bQoUP15ptv1vlZuXKlfvKTn0iSZs+erfLycg0fPlwPPfSQ9t9/f73yyivZDRAAHEMCDACWff3Z268/m7u7fv36qW3btnr55Zczr23fvl2vvfaaDjzwwMxrP/nJT7R8+XItXbpUf/rTnxr9+IO0s/hu1apV6tGjh/bbb786P/n5+ZnjhgwZoqlTp+pvf/ubDj744G98zhgAfEUCDACWtW7dWu+++67eeecdtW7dus57HTt21EUXXaRf/epXWrBggd555x1dcMEF+uKLL3Teeedljttnn300fPhwnXfeedqxY4dOOeWURq83ZswY7bXXXjr11FP14osvavXq1Xr++ef1y1/+Uh9//LFWr16tqVOnqry8XGvWrNFf//pXrVq1SgMHDoxsDgAgTm1sBwAAkLp06dLoezfffLNqa2v1s5/9TJs2bdLhhx+uhQsXas8996xz3JgxY/SLX/xCP//5z9WhQ4dGz/etb31LL7zwgq644gqdfvrp2rRpk/bee28df/zx6tKli7788ku99957uu+++/Svf/1LPXv21IQJE/Rv//ZvxsYLADblBUEQ2A4CAAAAiAsfgQAAAECqkAADAAAgVUiAAQAAkCokwAAAAEgVEmAAAACkCgkwAAAAUoUEGAAAAKlCAgwAAIBUIQEGAABAqpAAAwAAIFVIgAEAAJAqJMAAAABIlf8PeNWa51pRWwYAAAAASUVORK5CYII=\n", + "text/plain": [ + "<Figure size 800x800 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Non-zero values matrix\n", + "\n", + "\"\"\" This first part of the code comes from the following website : https://www.jillcates.com/pydata-workshop/html/tutorial.html \"\"\"\n", + "def create_X(df):\n", + " \"\"\"\n", + " Generates a sparse matrix from ratings dataframe.\n", + "\n", + " Args:\n", + " df: pandas dataframe containing 3 columns (userId, movieId, rating)\n", + "\n", + " Returns:\n", + " X: sparse matrix\n", + " user_mapper: dict that maps user id's to user indices\n", + " user_inv_mapper: dict that maps user indices to user id's\n", + " movie_mapper: dict that maps movie id's to movie indices\n", + " movie_inv_mapper: dict that maps movie indices to movie id's\n", + " \"\"\"\n", + " M = df['userId'].nunique()\n", + " N = df['movieId'].nunique()\n", + "\n", + " user_mapper = dict(zip(np.unique(df[\"userId\"]), list(range(M))))\n", + " movie_mapper = dict(zip(np.unique(df[\"movieId\"]), list(range(N))))\n", + "\n", + " user_inv_mapper = dict(zip(list(range(M)), np.unique(df[\"userId\"])))\n", + " movie_inv_mapper = dict(zip(list(range(N)), np.unique(df[\"movieId\"])))\n", + "\n", + " user_index = [user_mapper[i] for i in df['userId']]\n", + " item_index = [movie_mapper[i] for i in df['movieId']]\n", + "\n", + " X = csr_matrix((df[\"rating\"], (user_index,item_index)), shape=(M,N))\n", + "\n", + " return X, user_mapper, movie_mapper, user_inv_mapper, movie_inv_mapper\n", + "\n", + "X, user_mapper, movie_mapper, user_inv_mapper, movie_inv_mapper = create_X(df_ratings)\n", + "\n", + "\n", + "plt.figure(figsize=(8,8))\n", + "plt.spy(X[:100, :100], markersize=1)\n", + "plt.xlabel('Movies')\n", + "plt.ylabel('Users')\n", + "plt.xticks(range(0, 101, 10))\n", + "plt.yticks(range(0, 101, 10))\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "mlsmm2156", + "display_name": "Python 3", "language": "python", - "name": "mlsmm2156" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -98,7 +1201,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.9" + "version": "3.7.6" } }, "nbformat": 4, -- GitLab