<jupyter_start><jupyter_text>The results above show us the top 10 books in our data. We saw that the max score in our data was 5.0 but we don’t see any books in the above result with a score of 5.0. Indeed, we have filtered these books according to the number of notes. We’ve made sure that all of the books we have in the above results have a decent rating. There may be books in the data that may have only 1 or 2 notes may be rated 5.0. We want to avoid such books, which is why we used this type of filtering.Let’s go ahead and take a look at some of the top authors in our data. We’ll rank them according to the number of books they’ve written as long as those books are present in the data<jupyter_code>most_books  = df.groupby('authors')['title'].count().sort_values(ascending=False).head(10)
plt.figure(figsize=(10, 10))
ax =most_books.plot.barh()
ax.set_title("Top 10 authors with most books")
ax.set_xlabel("Total number of books")<jupyter_output><empty_output><jupyter_text>From the above chart, <NAME> and <NAME> have the most books in the data. Both authors have 40 books in our dataset followed by <NAME> and <NAME>.Next, we’ll take a look at which books have been reviewed the most. We have the average rating column in our data and also the number of times a particular book has been rated. We will try to use this column to find the most commented books present in our data:<jupyter_code>most_rated  = df.sort_values('ratings_count',  ascending = False).head(10)
top10_most_rated = most_rated[['title','ratings_count']]
top10_most_rated
plt.figure(figsize=(15,10))
sns.barplot(data =top10_most_rated, x = 'ratings_count',y= 'title', palette = 'inferno')<jupyter_output><empty_output><jupyter_text>We can see that Twilight has been rated more times than any other book! Also, these ratings are all in the millions! So that means Twilight has been reviewed over 4 million times, followed by The Hobbit or There and Back Again and The Catcher in the Rye which has been reviewed over 2 million times.  Let’s try to find a relation between our average score and the number of scores. We are doing this to see how we can use these columns in our recommendation. We will also check the distribution of average scores with the number of pages in a book, the language used in the book and the number of text reviews:<jupyter_code>plt.subplots(figsize=[15,10])
sns.distplot(df['average_rating']);

ax= sns.relplot(data=df, x="average_rating", y="ratings_count",height=11,color = 'red')
plt.title("Relation between Rating counts and Average Ratings",fontsize = 15)
ax.set_axis_labels("Average Rating", "Ratings Count")
df
plt.figure(figsize=(15,10))
ax = sns.relplot(x="average_rating", y= "  num_pages", data = df, color = 'red',sizes=(100, 200), height=7, marker='o')
#there is two space before the word "num_pages", this is why it is "  num_pages", there will be error if you remove the two space 
ax.set_axis_labels("Average Rating", "Number of Pages")<jupyter_output><empty_output><jupyter_text>After comparing the average rating with the different columns, we can continue to use the language and number of ratings for our recommendation system. Still, the other columns didn’t make much sense and using them might not help us to a great extent so we could omit them.I will make a copy of our original data just to be safe so that we are safe in case we mess anything up:<jupyter_code>df2 = df.copy()
df2.head()<jupyter_output><empty_output><jupyter_text>We are now going to create a new column called ‘rating_between’. We will divide our average rating column into different categories such as rating between 0 and 1, 1 and 2, etc. This will work as one of the features that we will build into our model so that it can make better predictions:<jupyter_code>def ratingbetween(df2):
    if (df2['average_rating']>=0) & (df2['average_rating']<=1):
        val = "between 0 and 1"
    elif (df2['average_rating']> 1) & (df2['average_rating']<=2):
        val = "between 1 and 2"
    elif (df2['average_rating']> 2) & (df2['average_rating']<=3):
        val = "between 2 and 3"
    elif (df2['average_rating']> 3) & (df2['average_rating']<=4):
        val = "between 3 and 4"
    else:
        val =  "between 4 and 5"
    return val
df2['rating_between'] =  df2.apply(ratingbetween, axis=1)
df2.head(3)<jupyter_output><empty_output><jupyter_text>We are now going to create two new DataFrames containing the different values of the rating_between column that we have just created. We will assign a value of 1 if one grade falls under a particular group, say 4 and 5, and the others will be assigned a value of 0.We will apply the same approach to split the language code column to retrieve these languages individually and give them the value of 1 and 0 also where 1 will be assigned if the book is written in a particular language eg English and 0 if it is not written in English:<jupyter_code>rating_df = pd.get_dummies(df2['rating_between'])
rating_df.head()
language_df = pd.get_dummies(df2['language_code'])
language_df.tail()<jupyter_output><empty_output><jupyter_text>We are now going to concatenate these two data frames into one and name it as features. This DataFrame will be the functionality that we provide to the Book Recommendation System with Machine Learning. It will contain the values of rating_df and language_df and will also have the values of average grade and number of grades:<jupyter_code>features = pd.concat([rating_df, 
                      language_df, 
                      df2['average_rating'], 
                      df2['ratings_count']], axis=1)
features<jupyter_output><empty_output><jupyter_text>Book Recommendation System: Final Step Now that our features are ready, we will now use the Min-Max scaler to reduce these values. This will help reduce the bias for some of the books that have too many features. The algorithm will find the median for all and equalize it:  Scaling the data<jupyter_code>from sklearn.preprocessing import MinMaxScaler
min_max_scaler = MinMaxScaler()
features = min_max_scaler.fit_transform(features)
features<jupyter_output><empty_output><jupyter_text>These feature is in a normalize form  ML model in the scalled dataset<jupyter_code>from sklearn import neighbors
model = neighbors.NearestNeighbors(n_neighbors=6, algorithm='ball_tree') #KNN algorithm 
model.fit(features)
dist, idlist = model.kneighbors(features)
dist<jupyter_output><empty_output><jupyter_text>We have built a machine learning model for recommending books and now we will need to create a function using Python. When this function is called, we will have to pass the name of the book to it. The model will try to find books based on the features. We’ll store those book names that the system recommends in a list and return them at the end:<jupyter_code>def BookRecommender(book_name):
    book_list_name = []
    book_id = df2[df2['title'] == book_name].index
    book_id = book_id[0]
    for newid in idlist[book_id]:
        book_list_name.append(df2.loc[newid].title)
    return book_list_name
    
BookNames = BookRecommender('<NAME> and the Prisoner of Azkaban (<NAME>  #3)')
BookNames<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07798549107142858, 'fraction_numerical': 0.015345982142857142, 'mean_word_length': 4.885878489326765, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '141947', 'license': 'MIT', 'n_tokens_mistral': 2177, 'n_tokens_neox': 2065, 'n_words': 931, 'path': 'Book Recommendation System.ipynb', 'repo_name': 'rejwanbinsulaiman/Book_recommendation_System', 'size': '7214'}