import numpy as np
import pandas as pd

"""
Explanation: Recommender Systems
In this project, we build a movie recommender system. We read a dataset of movie ratings by users, then we select other movies that a specific user would be interesting in based on his previous choice.
End of explanation
"""


column_names = ['user_id', 'item_id', 'rating', 'timestamp']
df = pd.read_csv('u.data', sep='\t', names=column_names)

df.head()

"""
Explanation: Read the data
End of explanation
"""


movie_titles = pd.read_csv("Movie_Id_Titles")
movie_titles.head()

"""
Explanation: Get movie titles
End of explanation
"""


df = pd.merge(df,movie_titles,on='item_id')
df.head()

"""
Explanation: Merged dataframes
End of explanation
"""


import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('white')
%matplotlib inline

"""
Explanation: Exploratory Data Analysis
End of explanation
"""


df.groupby('title')['rating'].mean().sort_values(ascending=False).head()

df.groupby('title')['rating'].count().sort_values(ascending=False).head()

ratings = pd.DataFrame(df.groupby('title')['rating'].mean())
ratings.head()

"""
Explanation: Create a ratings dataframe with average rating and number of ratings
End of explanation
"""


ratings['num of ratings'] = pd.DataFrame(df.groupby('title')['rating'].count())
ratings.head()

"""
Explanation: Number of ratings column
End of explanation
"""


plt.figure(figsize=(10,4))
ratings['num of ratings'].hist(bins=70)

plt.figure(figsize=(10,4))
ratings['rating'].hist(bins=70)

sns.jointplot(x='rating',y='num of ratings',data=ratings,alpha=0.5)

"""
Explanation: Data Visualization: Histogram
End of explanation
"""


moviemat = df.pivot_table(index='user_id',columns='title',values='rating')
moviemat.head()

"""
Explanation: Recommending Similar Movies
End of explanation
"""


ratings.sort_values('num of ratings',ascending=False).head(10)

"""
Explanation: Most rated movies
End of explanation
"""


ratings.head()

"""
Explanation: We choose two movies: starwars, a sci-fi movie. And Liar Liar, a comedy.
End of explanation
"""


starwars_user_ratings = moviemat['Star Wars (1977)']
liarliar_user_ratings = moviemat['Liar Liar (1997)']
starwars_user_ratings.head()

"""
Explanation: Now let's grab the user ratings for those two movies:
End of explanation
"""


similar_to_starwars = moviemat.corrwith(starwars_user_ratings)
similar_to_liarliar = moviemat.corrwith(liarliar_user_ratings)

"""
Explanation: Using corrwith() method to get correlations between two pandas series:
End of explanation
"""


corr_starwars = pd.DataFrame(similar_to_starwars,columns=['Correlation'])
corr_starwars.dropna(inplace=True)
corr_starwars.head()

corr_starwars.sort_values('Correlation',ascending=False).head(10)

"""
Explanation: Clear data by removing NaN values and using a DataFrame instead of a series
End of explanation
"""


corr_starwars = corr_starwars.join(ratings['num of ratings'])
corr_starwars.head()

"""
Explanation: Filtering out movies that have less than 100 reviews (this value was chosen based off the histogram). This is needed to get more accurate results
End of explanation
"""


corr_starwars[corr_starwars['num of ratings']>100].sort_values('Correlation',ascending=False).head()

"""
Explanation: Now sort the values
End of explanation
"""


corr_liarliar = pd.DataFrame(similar_to_liarliar,columns=['Correlation'])
corr_liarliar.dropna(inplace=True)
corr_liarliar = corr_liarliar.join(ratings['num of ratings'])
corr_liarliar[corr_liarliar['num of ratings']>100].sort_values('Correlation',ascending=False).head()

"""
Explanation: The same for the comedy Liar Liar:
End of explanation
"""


