<jupyter_start><jupyter_text>Collaborative  Filtering：Item-based Recommendation<jupyter_code>import numpy as np
import pandas as pd
import warnings
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.neighbors import NearestNeighbors
warnings.filterwarnings('ignore')
# Load data
df = pd.read_csv("RawData/df.csv")

# Only keep the orders that only contains 1 order
order_product = df.groupby('order_id').product_id.count().sort_values(ascending=False)
df = df[df.order_id.isin((order_product[order_product == 1]).index)]

# Select columns for analysis
item_profile = df[['customer_unique_id', 'product_id','review_score']]
item_profile.head()
# Calculate average rating of different product
Ratings_mean = item_profile.groupby('product_id')['review_score'].mean().reset_index().rename(columns = {'review_score': 'mean_rating'})
item_profile = pd.merge(item_profile, Ratings_mean, how='inner', on=['product_id'])
item_profile.head()
print(len(item_profile.customer_unique_id.drop_duplicates().tolist()))
print(len(item_profile.product_id.drop_duplicates().tolist()))
# Create a pivot table
new_df=item_profile.head(10000)
pivot = pd.pivot_table(new_df, index='product_id', columns='customer_unique_id', values='review_score')
pivot.head()
pivot.shape
# Center the mean around 0 (centered cosine/pearson)
# pivot_norm = pivot.apply(lambda x: x - np.nanmean(x), axis=1)
# pivot_norm.head()<jupyter_output><empty_output><jupyter_text>Item Based CF<jupyter_code># Fill NaN with 0
pivot.fillna(0, inplace=True)
pivot.head()<jupyter_output><empty_output><jupyter_text>Calculate Similar Items<jupyter_code># Convert into dataframe
item_sim_df = pd.DataFrame(cosine_similarity(pivot, pivot), 
                           index=pivot.index, 
                           columns=pivot.index)
item_sim_df
def get_similar_product(product_id):
    if product_id not in pivot.index:
        return None, None
    else:
        sim_product = item_sim_df.sort_values(by=product_id, ascending=False).index[1:]
        sim_score = item_sim_df.sort_values(by=product_id, ascending=False).loc[:, product_id].tolist()[1:]
        return sim_product, sim_score
product, score = get_similar_product("a9516a079e37a9c9c36b9b78b10169e8")
for x,y in zip(product[:10], score[:10]):
    print("{} with similarity of {}".format(x, y))
# Predict the rating of product x by user y
def predict_rating(customer_unique_id, product_id, max_neighbor=10):
    product, scores = get_similar_product(product_id)
    product_arr = np.array([x for x in product])
    sim_arr = np.array([x for x in scores])
    
    # Select only the product that has already rated by user x
    filtering = pivot[customer_unique_id].loc[product_arr] != 0
    
    # Calculate the predicted score
    s = np.dot(sim_arr[filtering][:max_neighbor], pivot[customer_unique_id].loc[product_arr[filtering][:max_neighbor]]) \
            / np.sum(sim_arr[filtering][:max_neighbor])
    
    return s
predict_rating("00115fc7123b5310cf6d3a3aa932699e", "a9516a079e37a9c9c36b9b78b10169e8")<jupyter_output><empty_output><jupyter_text>Get recommendation<jupyter_code># Recommend top n_product for customer x
def get_recommendation(customer_unique_id, n_product=1):
    predicted_rating = np.array([])
    
    for _product in pivot.index:
        predicted_rating = np.append(predicted_rating, predict_rating(customer_unique_id, _product))
    
    # Don't recommend sth that the customer has already rated
    temp = pd.DataFrame({'predicted':predicted_rating, 'name':pivot.index})
    filtering = (pivot[customer_unique_id] == 0.0)
    temp = temp.loc[filtering.values].sort_values(by='predicted', ascending=False)

    # Recommend n_product product
    return product.loc[product_index.loc[temp.name[:n_product]]]
# Recommendation for a particular customer
get_recommendation("0010a452c6d13139e50b57f19f52e04e")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11474144584512477, 'fraction_numerical': 0.028813995369179314, 'mean_word_length': 5.7735191637630665, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, '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': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '166562', 'license': 'MIT', 'n_tokens_mistral': 1400, 'n_tokens_neox': 1300, 'n_words': 249, 'path': 'Collaborative Filtering - Item based Recommendation.ipynb', 'repo_name': 'SophieHuGit/OlistEcommerceAnalytics', 'size': '3887'}