"""
<img src='https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcSj_mAsgRbFgy9KRI54xceXq-g8sN9an4ETmBalpMdpDsa9LBKC' width=1000>
<div align="center"><font size="3">Source: Google</font></div>


"""
"""
<font color='#315dad' size=5>Netflix - Trivia's</font><br>

* Netflix was originally called "kibble."
* It's technically been around longer than Google. 
* Netflix is responsible for 15% of the world's internet traffic.
* The streaming service once hosted its own awards ceremony, The Flixies
* You can take a test to become a translator for Netflix.
"""
"""
<font color='#31a04b' size=4>Interesting??? Now let's get started</font><br>
"""
"""
<font color='#2e2a28' size=4>This kernel will always be a work in progress. Kindly upvote it if you find it useful! Thanks</font><br>
"""
"""
## Table of Content:

* Objective

* Data manipulation
    *  Data loading
    *  Data viz 
    *  Data processing
    
* Recommendation systems
"""
"""
<font color='#00000' size=5>Objective:</font><br>
"""
"""
<p>Learn from data and recommend best TV shows to users, based on self & others behaviour </p>
"""
"""
<font color='#671a1a' size=5>Streaming libraries:</font><br>
"""
'''Import basic modules.'''
import pandas as pd
import numpy as np


'''Customize visualization
Seaborn and matplotlib visualization.'''
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("whitegrid")
%matplotlib inline

'''Plotly visualization .'''
import plotly.offline as py
from plotly.offline import iplot, init_notebook_mode
import plotly.graph_objs as go
py.init_notebook_mode(connected = True) # Required to use plotly offline in jupyter notebook

import cufflinks as cf #importing plotly and cufflinks in offline mode  
import plotly.offline  
cf.go_offline()  
cf.set_config_file(offline=False, world_readable=True)

'''Display markdown formatted output like bold, italic bold etc.'''
from IPython.display import Markdown,HTML
import matplotlib.gridspec as gridspec # to do the grid of plots

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import linear_kernel
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity

def bold(string):
    display(Markdown(string))
netdata=pd.read_csv('../input/netflix-shows/netflix_titles_nov_2019.csv')
netdata["date_added"] = pd.to_datetime(netdata['date_added'])
netdata['year_added'] = netdata['date_added'].dt.year
netdata['month_added'] = netdata['date_added'].dt.month

netdata['season_count'] = netdata.apply(lambda x : x['duration'].split(" ")[0] if "Season" in x['duration'] else "", axis = 1)
netdata['duration'] = netdata.apply(lambda x : x['duration'].split(" ")[0] if "Season" not in x['duration'] else "", axis = 1)
netdata['duration'] =netdata.apply(lambda x : '0' if x['duration']=='' else x['duration'],axis=1)
netdata['duration'] =  netdata['duration'].astype(float)
"""
<font color='#dcc77d' size=5>Binging:</font><br>
"""
display(HTML(f"""
   
        <ul class="list-group">
          <li class="list-group-item disabled" aria-disabled="true"><h4>Dataset preview</h4></li>
          <li class="list-group-item"><h4>Number of rows in the dataset: <span class="label label-primary">{ netdata.shape[0]:,}</span></h4></li>
          <li class="list-group-item"> <h4>Number of columns in the dataset: <span class="label label-primary">{netdata.shape[1]}</span></h4></li>
          <li class="list-group-item"><h4>Number of unique types in the dataset: <span class="label label-success">{ netdata['type'].nunique():,}</span></h4></li>
        </ul>
  
    """))
temp = netdata['rating'].value_counts()
df = pd.DataFrame({'rating': temp.index,
                   'values': temp.values
                  })
df.iplot(kind='pie',labels='rating',values='values', title='Distribution of ratings in data')
"""
> <font color='#702963' size=3>TV-14:</font><br>
Programs rated TV-14 contains material that parents or adult guardians may find unsuitable for children under the age of 14.

> <font color='#702963' size=3>TV-G:</font><br> 
Netflix has stamped them with an age certification of 'G', indicating they're appropriate for general audiences.

> <font color='#702963' size=3>TV-Y:</font><br> 
A TV-Y rating means that programming is appropriate for children of all ages. TV-Y7 indicates that programming is designed for chil- dren ages 7 and older. An additional rating, TV-Y7-FV, is used to indicate that a program contains “fantasy violence” that may be more intense or combative than other TV-Y7 programs.

> <font color='#702963' size=3>TV-MA:</font><br> 
"TV-MA" is a rating assigned by the TV Parental Guidelines to a television program that was designed for mature audiences only. Using this rating, the TVPG warns viewers that the show's content contains foul language, graphic violence, graphic sexual activity or any combination of these elements.

> <font color='#702963' size=3>TV-PG:</font><br> 
TV-PG means that a show can be viewed by younger audiences but shouldn't be seen without their parents in the room

> <font color='#702963' size=3>R:</font><br> 
R (restricted): No one under 17 admitted without an accompanying parent or guardian. This rating is given for frequent strong language and violence, nudity for sexual purposes, and drug abuse

> <font color='#702963' size=3>NR- Not rated, UR- Unrated</font><br> 

> <font color='#702963' size=3>NC-17:</font><br> 
An NC-17 rating means the content isn't suitable for children under 17 and younger. These are movies meant to be watched after your children have long since been tucked in and are sleeping in their beds. Netflix is streaming several NC-17 movies for the adults in your family to enjoy.

"""
"""
> **It largerly caters to the matured audiences only. Streaming platforms has lot of scopes to cover contents under 15 age groups which will have huge turn around for them**
"""
#Credits: https://www.kaggle.com/shivamb/a-visual-and-insightful-journey-donorschoose/data

t = netdata['month_added'].value_counts()

lObjectsALLcnts = list(t.values)

lObjectsALLlbls = list(t.index)
mapp1 = {1:'Jan',2:'Feb',3:'Mar',4:'Apr',5:'May',6:'Jun',7:'Jul',8:'Aug',9:'Sep',10:'Oct',11:'Nov',12:'Dec'}
lObjectsALLlbls = [mapp1[x] for x in lObjectsALLlbls]

iN = len(lObjectsALLcnts)
arrCnts = np.array(lObjectsALLcnts)

theta=np.arange(0, 2*np.pi, 2*np.pi/iN)
width = (2*np.pi)/iN *0.5
bottom = 50

fig = plt.figure(figsize=(8,8))
ax = fig.add_axes([0.2, 0.1, 1, 0.9], polar=True)
fig.suptitle('Month released', fontsize=16)
bars = ax.bar(theta, arrCnts, width=width, bottom=bottom, color='#eb6951')
plt.axis('off')

rotations = np.rad2deg(theta)
for x, bar, rotation, label in zip(theta, bars, rotations, lObjectsALLlbls):
    lab = ax.text(x,bottom+bar.get_height() , label, ha='left', va='center', rotation=rotation, rotation_mode="anchor",)   
plt.show()
"""
> **Lot of contents are getting released in Oct and Nov compared to other months**
"""
df1=netdata[netdata['type']=='TV Show']
df2=netdata[netdata['type']=='Movie']

df1=df1.groupby('date_added')['title'].nunique().sort_values()
df2=df2.groupby('date_added')['title'].nunique().sort_values()

trace1 = go.Scatter(
    x = df1.index,
    y = df1.values,
    mode = 'markers',
    name = 'Tv shows'
)

trace2 = go.Scatter(
    x = df2.index,
    y = df2.values,
    mode = 'markers',
    name = 'Movies'
)

layout = go.Layout(template= "plotly_dark", title = 'TV Shows', xaxis = dict(title = 'Years'))
fig = go.Figure(data = [trace1,trace2], layout = layout)
fig.show()
"""
> **More movies are getting released since mid 2017 than TV shows. Is this the end of tv shows?**
"""
pd.crosstab(netdata.type,netdata.year_added,margins=True).style.background_gradient(cmap='summer_r')
"""
> **This again tells the same thing about movies and tv shows over the years**
"""
pd.crosstab(netdata.type,netdata.season_count,margins=True).style.background_gradient(cmap='RdYlGn')

"""
> **Almost all tv shows are having 1/2/3 seasons as audience binge watches the entire series in a day. Mini series will be good catch for the audiences. Remember chernobyl?**
"""
"""
<font color='#702963' size=3>Movie duration</font><br> 
"""
f,ax=plt.subplots(1,1,figsize=(10,5))
netdata[netdata['type']=='Movie'].duration.plot.hist(ax=ax,bins=20,edgecolor='black',color='red')
ax.set_title('Movie')
"""
> **Roughly all the movie durations are around 100mins**
"""
"""
<font color='#702963' size=3>Correlation between variables</font><br> 
"""
cols=['country','type','year_added','season_count','release_year','rating','duration','month_added']

sns.heatmap(netdata[cols].corr(),annot=True,cmap='RdYlGn',linewidths=0.2)
fig=plt.gcf()
fig.set_size_inches(10,8)
plt.show()
"""
> **Not much of correlation between features**
"""
"""
<font color='#6f3fdd' size=5>Recommendation system</font><br> 
"""
"""
I will give a brief overview of recommendation systems. This is completely inspired from this excellent [kernel](https://www.kaggle.com/ibtesama/getting-started-with-a-movie-recommendation-system)
"""
"""
> There are basically three types of recommender systems:-
> 
> **Demographic Filtering**- They offer generalized recommendations to every user, based on movie popularity and/or genre. The System recommends the same movies to users with similar demographic features. Since each user is different , this approach is considered to be too simple. The basic idea behind this system is that movies that are more popular and critically acclaimed will have a higher probability of being liked by the average audience.
> 
> **Content Based Filtering**- They suggest similar items based on a particular item. This system uses item metadata, such as genre, director, description, actors, etc. for movies, to make these recommendations. The general idea behind these recommender systems is that if a person liked a particular item, he or she will also like an item that is similar to it.
> 
> **Collaborative Filtering**- This system matches persons with similar interests and provides recommendations based on this matching. Collaborative filters do not require item metadata like its content-based counterparts.
"""
"""
<font color='#633f5c' size=4>Content based filtering</font><br> 
"""
"""
<img src='https://miro.medium.com/max/1642/1*BME1JjIlBEAI9BV5pOO5Mg.png' width=500>
<div align="center"><font size="3">Source: Google</font></div>


"""
#Filling nan values with empty string in director,country,cast
nanlist=['cast','director','country']
metalist=['cast','listed_in','director']

nancols=netdata[nanlist].fillna(' ')

netdata=netdata.drop(nanlist,axis=1)
filterdata=pd.concat([netdata,nancols],axis=1)

#Few processing
filterdata['cast']=filterdata['cast'].apply(lambda x: x.split(','))
filterdata['director']=filterdata['director'].apply(lambda x: x.split(','))
filterdata['country']=filterdata['country'].apply(lambda x: x.split(','))
#Define a TF-IDF Vectorizer Object. Remove all english stop words such as 'the', 'a'
tfidf = TfidfVectorizer(stop_words='english')

#Construct the required TF-IDF matrix by fitting and transforming the data
tfidf_matrix = tfidf.fit_transform(filterdata['description'])

#Output the shape of tfidf_matrix
tfidf_matrix.shape
"""
<p>calculating cosine similarity based on tf-idf for content similarity
"""
# Compute the cosine similarity matrix
cosine_sim = linear_kernel(tfidf_matrix, tfidf_matrix)
#Construct a reverse map of indices and movie titles
indices = pd.Series(filterdata.index, index=filterdata['title']).drop_duplicates()
# Function that takes in movie title as input and outputs most similar movies
def get_recommendations(title, cosine_sim=cosine_sim):
    
    # Get the index of the movie that matches the title
    idx = indices[title]

    # Get the pairwsie similarity scores of all movies with that movie
    sim_scores = list(enumerate(cosine_sim[idx]))

    # Sort the movies based on the similarity scores
    sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)

    # Get the scores of the 10 most similar movies
    sim_scores = sim_scores[1:11]

    # Get the movie indices
    movie_indices = [i[0] for i in sim_scores]

    # Return the top 10 most similar movies
    return filterdata['title'].iloc[movie_indices]

get_recommendations('The Matrix')
"""
We are getting base results but there are other matrix movies which are not considered here and also the one which was ranked is also at the bottom. Let's add meta features and improve the results
"""
"""
<font color='#633f5c' size=3>Adding meta features</font><br> 
"""
def create_meta(x):
    return ' '.join(x['cast'] + x['director'] +x['country'])

filterdata['meta'] = filterdata.apply(create_meta, axis=1)
"""
<p> Apply count vectorizer for these features as the frequency of actor/ director should not be weighted down across the length of the documents
"""
count = CountVectorizer(stop_words='english')
count_matrix = count.fit_transform(filterdata['meta'])
cosine_sim2 = cosine_similarity(count_matrix, count_matrix)
get_recommendations('The Matrix',cosine_sim+cosine_sim2)
"""
Now we could get the matrix movies as top recommendations
"""
"""
<font color='#633f5c' size=4>More updates soon!!</font><br> 
"""