Spaces:
Runtime error
Runtime error
File size: 6,449 Bytes
f912653 b4c7df7 807a8f8 f912653 c86a927 807a8f8 b4c7df7 4b93540 c86a927 b4c7df7 eee895c b4c7df7 4b93540 c0503dc b4c7df7 4b93540 b4c7df7 4ff1ca9 b4c7df7 c0503dc b4c7df7 4b93540 807a8f8 4b93540 807a8f8 65d4df9 807a8f8 bb0c663 65d4df9 bb0c663 807a8f8 c0503dc 807a8f8 b4c7df7 c0503dc b4c7df7 4b93540 c0503dc b4c7df7 c0503dc 807a8f8 4b93540 807a8f8 c86a927 807a8f8 8b2ad1d c0503dc 4b93540 807a8f8 4b93540 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
import streamlit as st
import pandas as pd
import re
import requests
# DATA:
movies = pd.read_csv('https://raw.githubusercontent.com/tobiasaurer/movie-recommender-streamlit/main/data/movies.csv')
ratings = pd.read_csv('https://raw.githubusercontent.com/tobiasaurer/movie-recommender-streamlit/main/data/ratings.csv')
links = pd.read_csv('https://raw.githubusercontent.com/tobiasaurer/movie-recommender-streamlit/main/data/links.csv')
# clean titles column by moving "The" and "A" to the beginning of the string
# this makes it more searchable for users
movies.loc[lambda df: df["title"].str.contains(", The", regex=True), 'title'] = 'The ' + movies['title']
movies.loc[lambda df: df["title"].str.contains(", The", regex=True), 'title'] = movies['title'].str.replace(", The", '', regex=True)
movies.loc[lambda df: df["title"].str.contains(", A", regex=True), 'title'] = 'A ' + movies['title']
movies.loc[lambda df: df["title"].str.contains(", A", regex=True), 'title'] = movies['title'].str.replace(", A", '', regex=True)
# extract year from title and store it in new column
movies= movies.assign(year = lambda df_ : df_['title'].replace(r'(.*)\((\d{4})\)', r'\2', regex= True))
movies.year = pd.to_numeric(movies.year, errors= 'coerce').fillna(0).astype('int')
# INSTRUCTIONS:
st.title("Popularity-Based Recommender")
# FUNCTIONS:
def get_popular_recommendations(n, genres, time_range):
recommendations = (
ratings
.groupby('movieId')
.agg(avg_rating = ('rating', 'mean'), num_ratings = ('rating', 'count'))
.merge(movies, on='movieId')
.assign(combined_rating = lambda x: x['avg_rating'] * x['num_ratings']**0.5)
[lambda df: df["genres"].str.contains(genres, regex=True)]
.loc[lambda df : ((df['year'] >= time_range[0]) & ( df['year'] <= time_range[1]))]
.sort_values('combined_rating', ascending=False)
.head(n)
[['title', 'avg_rating', 'genres']]
.rename(columns= {'title': 'Movie Title', 'avg_rating': 'Average Rating', 'genres': 'Genres'})
)
return recommendations
def get_popular_recommendations_streaming(n, genres, time_range, country, url, headers):
recommendations = (
ratings
.groupby('movieId')
.agg(avg_rating = ('rating', 'mean'), num_ratings = ('rating', 'count'))
.merge(movies, on='movieId')
.assign(combined_rating = lambda x: x['avg_rating'] * x['num_ratings']**0.5)
[lambda df: df["genres"].str.contains(genres, regex=True)]
.loc[lambda df : ((df['year'] >= time_range[0]) & ( df['year'] <= time_range[1]))]
.sort_values('combined_rating', ascending=False)
.head(n)
[['title', 'avg_rating', 'genres', 'movieId']]
)
# merge recommendations with links df to get imdbIds for the API calls
recommendations_ids = (
recommendations
.merge(links, how = 'left', on = 'movieId')
# [['title', 'genres', 'imdbId']]
)
recommendations_ids['imdbId'] = 'tt0' + recommendations_ids['imdbId'].astype('str')
imdb_ids = list(recommendations_ids['imdbId'])
# create new column for streaming links
recommendations_ids['Streaming Availability'] = ""
# loop through imdb_ids to make one api call for each to get available streaming links
for id in imdb_ids:
# make api call
querystring = {"country":country,"imdb_id":id,"output_language":"en"}
response = requests.request("GET", url, headers=headers, params=querystring)
streaming_info = response.json()
for streaming_service in streaming_info['streamingInfo']:
recommendations_ids.loc[recommendations_ids['imdbId'] == id, 'Streaming Availability'] += f"{streaming_service}: {streaming_info['streamingInfo'][streaming_service][country]['link']} \n"
recommendations_ids.rename(columns= {'title': 'Movie Title', 'genres': 'Genres'}, inplace = True)
return recommendations_ids[['Movie Title', 'Genres', 'Streaming Availability']]
def transform_genre_to_regex(genres):
regex = ""
for genre in genres:
regex += f"(?=.*{genre})"
return regex
# USER INPUT:
st.write("""
Move the slider to the desired number of recommendations you wish to receive.
""")
number_of_recommendations = st.slider("Number of recommendations", 1, 10, 5)
st.write("""
Move the sliders to choose a timeperiod for your recommendations.
""")
time_range = st.slider('Time-period:', min_value=1900, max_value=2018, value=(1900, 2018), step=1)
st.write("""
__Optional__: You can narrow down the recommendations by picking one or several genre(s).
However, the more genres you choose, the fewer movies will be recommended.
""")
genre_list = set([inner for outer in movies.genres.str.split('|') for inner in outer])
genres = st.multiselect('Optional: Select one or more genres', genre_list, default=None, key=None, help=None, on_change=None, args=None, kwargs=None, disabled=False)
genres_regex = transform_genre_to_regex(genres)
st.write("""
__Optional__: You can receive links for popular streaming services for each recommendation (if available) by selecting your countrycode.
Select none if you don't want to get streaming links.
""")
streaming_country = st.selectbox('Optional: Country for streaming information', ('none', 'de', 'us'))
# API INFORMATION:
# Streaming availability
url = "https://streaming-availability.p.rapidapi.com/get/basic"
headers = {
"X-RapidAPI-Key": st.secrets["api_key"],
"X-RapidAPI-Host": "streaming-availability.p.rapidapi.com"
}
# EXECUTION:
if st.button("Get Recommendations"):
if streaming_country == 'none':
st.write(get_popular_recommendations(number_of_recommendations, genres_regex, time_range))
else:
try:
recommendations = get_popular_recommendations_streaming(number_of_recommendations, genres_regex, time_range, streaming_country, url, headers)
st.write("Double-click on a Streaming-Availability cell to see all options.", recommendations)
except:
recommendations = get_popular_recommendations(number_of_recommendations, genres_regex, time_range)
st.write('Error: Streaming information could not be gathered. Providing output without streaming availability instead.', recommendations) |