| import streamlit as st |
| import re |
| import altair as alt |
| from folder_management import create_folder, remove_files_folder |
| st.set_page_config('Product Recommendation Application', layout='wide', page_icon='airtory_logo.PNG') |
|
|
| |
| def intro(): |
| import streamlit as st |
|
|
| st.markdown("## Welcome to the Product Recommendation Application! 👋") |
| st.sidebar.success("Select a page from above.") |
|
|
| st.markdown( |
| """ |
| **👈 Select a page from the navigation bar to the left** |
| |
| ### Functionality of Pages |
| #### Generate Recommendations Page |
| - This page allows you to generate recommendations for a particular keyword/publisherid combo. |
| - The recommendations for each keyword/publisherid combo, are stored in a separate SQLite Database Table. |
| - Ideally, for each keyword/publisherid combo, the recommendations should only be generated once per day. To mock this, you are only allowed to generate recommendations for a specific keyword/publisherid combo once. |
| #### Product Recommendations Page |
| - This page displays the Product Recommendations for each keyword/publisherid combo for which the recommendations were generated in the previous page. |
| - You can currently select the available keywords from the dropdown provided in the side bar. |
| - For the time being, the Publisher ID is restricted to a single known value. This can be easily updated later. |
| - Note: Since the click tracker I was using had issues, as a workaround I had to use a Button instead. So now, to register a click against a product, you need to click on the 'Select' button provided below each product. |
| - For each session, once a product is clicked on, it is no longer displayed. |
| - You can choose the number of recommendations to be displayed, between 1 & 5. |
| - The maximum number of recommendations that are available for display for each keyword/publisherid combo is restricted to 50. |
| - The minumum number depends on the products available from bizrate. |
| - If/when all available recommendations for a keyword/publisherid combo has been clicked on, you can either choose a different keyword, reload the application to create a new session. |
| #### Analytics Page |
| - Displays a Line Chart and a Bar Chart, to show the distribution of clicks across Session ID, Keyword, Publisher ID, SKU or Date. |
| - Displays a table of the most clicked SKU's |
| """ |
| ) |
|
|
| def generate_recommendations(): |
| import os |
| import string |
| import random |
| import streamlit as st |
| import warnings |
| warnings.filterwarnings('ignore') |
|
|
| |
| |
| from folder_management import create_folder, remove_files_folder |
| from sqlite_database import create_insert_table, query_table, insert_clickdata_table, check_for_table |
| from recommend import query_bizrate, recommend |
|
|
| |
| def random_string(N=7): |
| res = ''.join(random.choices(string.ascii_lowercase + string.digits, k=N)) |
| return str(res) |
|
|
| def query_and_recommend(keyword, publisherid): |
| query_bizrate(keyword, publisherid) |
| recommend(keyword, publisherid) |
|
|
| |
| |
| |
|
|
| st.title('Generate Recommendations') |
| st.markdown('''<pre style="text-align:center"> |
| <strong><span style="color:#6a8759"> |
| Generate Recommendations for any Keyword - Publisher ID Combo. <br><br> </span></strong></pre>''', |
| unsafe_allow_html=True) |
|
|
| col1, col2 = st.columns(2) |
|
|
| selected_keyword = '' |
| publisher_id = '' |
|
|
| with col1: |
| selected_keyword = st.text_input('Enter a single word as keyword:', 'aquaman') |
| selected_keyword = selected_keyword.lower() |
| selected_keyword = ''.join(re.split(r"[ \|\\\/,.-]", selected_keyword)) |
| |
| st.write(selected_keyword) |
|
|
| with col2: |
| publisher_id = st.text_input("Enter a Publisher ID: ", '725895') |
| |
|
|
| keyword_pubid_list = [] |
| for file in os.listdir('bizrate'): |
| keyword_pubid_list.append(file.replace(".xml", "")) |
|
|
| if selected_keyword + "_" + publisher_id in keyword_pubid_list: |
| st.error('Keyword - Publisher ID Combo Exists!') |
| else: |
| st.info("Keyword - Publisher ID Combo doesn't exist. Must be queried") |
| st.button('Generate Recommendations', key=random_string(), on_click=query_and_recommend, |
| args=([selected_keyword, publisher_id])) |
|
|
| def display_recommendations(): |
| import pandas as pd |
| import numpy as np |
| import requests |
| from bs4 import BeautifulSoup |
| import urllib.parse |
| import os |
| import string |
| import random |
|
|
| import time |
|
|
| import streamlit as st |
| import uuid |
|
|
| import warnings |
| import sys |
|
|
| warnings.filterwarnings('ignore') |
|
|
| |
| |
| from folder_management import create_folder, remove_files_folder |
| from sqlite_database import create_insert_table, query_table, insert_clickdata_table, check_for_table |
|
|
| |
| def random_string(N=7): |
| res = ''.join(random.choices(string.ascii_lowercase + string.digits, k=N)) |
| return str(res) |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| st.title('Product Recommender System') |
| st.markdown('''<pre style="text-align:center"> |
| <strong><span style="color:#6a8759"> |
| It will take as inputs: Keyword and Publisher ID. |
| Displays (upto) Top 5 Recommendations & Collects Click Information. <br><br> </span></strong></pre>''', |
| unsafe_allow_html=True) |
|
|
| |
| if 'store' not in st.session_state: |
| st.session_state.store = False |
|
|
| try: |
| df_session = pd.read_excel('df_session.xlsx') |
| df_row = pd.DataFrame({'ID': uuid.uuid4()}, index=[0]) |
| df_session = pd.concat([df_session, df_row], ignore_index=True) |
| df_session.to_excel('df_session.xlsx', index=False) |
| df_sku = pd.DataFrame({'SessionID': pd.Series(dtype='object'), 'Keyword': pd.Series(dtype='object'), |
| 'Skus': pd.Series(dtype='object'), |
| 'Count': pd.Series(dtype='int')}) |
| df_sku.to_excel('df_sku.xlsx', index=False) |
|
|
| except FileNotFoundError: |
| df_session = pd.DataFrame({'ID': uuid.uuid4()}, index=[0]) |
| df_session.to_excel('df_session.xlsx', index=False) |
|
|
| df_session = pd.read_excel('df_session.xlsx') |
| session_id = list(df_session['ID'])[-1] |
| |
|
|
| |
|
|
| |
| |
| list_keywords = [] |
| list_publisherid = [] |
| for file in os.listdir('bizrate'): |
| keyword_publisherid = file.replace(".xml", "") |
| list_keywords.append(keyword_publisherid.split("_")[0]) |
| list_publisherid.append(keyword_publisherid.split("_")[1]) |
| |
| list_publisherid = ['725895'] |
| selected_keyword = st.sidebar.selectbox("Select a Keyword:", set(sorted(list_keywords))) |
| publisher_id = st.sidebar.selectbox("Select a Publisher ID:", set(list_publisherid)) |
|
|
| |
| |
|
|
| |
|
|
| try: |
| rec_df = query_table('RecSysData', selected_keyword + "_" + publisher_id) |
| except pd.errors.DatabaseError: |
| |
| rec_df = pd.DataFrame({}, columns=['title', 'Brand', 'url', 'Image', 'Skus', 'price', 'originalPrice', |
| 'markdownPercent', 'totalPrice', 'condition', 'stock', 'relevancy']) |
|
|
| |
|
|
| |
|
|
| try: |
| click_data_df = query_table('session_data', 'session_data') |
|
|
| if click_data_df.empty: |
| df_top_rec = rec_df.head(5) |
| else: |
| displayed_skus = list(click_data_df[click_data_df['session_id'] == session_id][ |
| 'Skus']) |
| |
| rec_df = rec_df[~rec_df['Skus'].isin(displayed_skus)] |
| except pd.errors.DatabaseError as e: |
| print(e) |
|
|
| |
| |
| try: |
| top_df = rec_df.sample(5).reset_index() |
| except Exception as e: |
| |
| top_df = rec_df.head(5).reset_index() |
|
|
| recs_to_display = 0 |
| if len(top_df) > 5: |
| recs_to_display = st.sidebar.slider('Recommendations to Display', 1, 5) |
| elif len(top_df) > 1: |
| recs_to_display = st.sidebar.slider('Recommendations to Display', 1, len(top_df), len(top_df)) |
| else: |
| recs_to_display = 1 |
|
|
| |
| image_width_dictionary = { |
| 5: 200, |
| 4: 240, |
| 3: 280, |
| 2: 320, |
| 1: 400} |
|
|
| if recs_to_display > 0: |
| idx = 0 |
| cols = st.columns(recs_to_display) |
| for col in cols: |
| with col: |
| try: |
| title = top_df['title'][idx] |
| img_link = top_df['url'][idx] |
| sku = top_df['Skus'][idx] |
| list_price = top_df['originalPrice'][idx] |
| selling_price = top_df['price'][idx] |
| discount = top_df['markdownPercent'][idx] |
| st.image(top_df['Image'][idx], width=image_width_dictionary[recs_to_display]) |
| |
| |
| |
| content = '''<p><strong> <a href={}>{}</a> </strong> <br> |
| <strong>SKU:</strong> {} <br> |
| <strong>S.P:</strong> $ {}<br> |
| <strong>Discount:</strong> % {} <br> |
| <strong>L.P:</strong> $ {} <br> |
| </p>'''.format(img_link, title, sku, selling_price, discount, list_price) |
| st.markdown(content, unsafe_allow_html=True) |
| st.button('Select', key=random_string(), on_click=insert_clickdata_table, |
| args=([session_id, selected_keyword, publisher_id, sku, 1])) |
| except KeyError: |
| st.info('No more recommendations to display for this Keyword-PublisherID Combo!') |
| st.info('You can search for another keyword or reload the page!') |
| idx += 1 |
| else: |
| st.text( |
| 'No more recommendations to display for this Keyword-PublisherID Combo! You can search for another keyword or reload the page!') |
|
|
|
|
| def display_analytics(): |
| import pandas as pd |
| import numpy as np |
| import requests |
| from bs4 import BeautifulSoup |
| import urllib.parse |
| import os |
| import string |
| import random |
|
|
| import time |
|
|
| import streamlit as st |
| import uuid |
|
|
| import warnings |
|
|
| warnings.filterwarnings('ignore') |
|
|
| |
| |
| from folder_management import create_folder, remove_files_folder |
| from sqlite_database import create_insert_table, query_table, insert_clickdata_table, check_for_table |
|
|
| |
| |
| st.title('Analytics') |
|
|
| df = query_table('session_data', 'session_data') |
| |
| df['date'] = df['clicked_at'].map(lambda x: pd.Timestamp(x).date()) |
| x_col_list = list(df.columns) |
| x_col_list.remove('count') |
| x_col_list.remove('clicked_at') |
| print(x_col_list) |
| column = st.selectbox('Select a Dimension:', x_col_list) |
|
|
| |
| if column: |
| grouped_df = df.groupby([column]).sum().reset_index() |
| if column != 'date': |
| grouped_df = grouped_df.sort_values(by='count', ascending=False) |
| grouped_df.rename(columns={'count': 'clicks'}, inplace=True) |
| |
| col1, col2 = st.columns(2) |
| with col1: |
| |
| alt_line_chart = alt.Chart(grouped_df).mark_line(color='#3ac81e').encode(x=column, y='clicks') |
| st.altair_chart(alt_line_chart, use_container_width=True) |
| |
| with col2: |
| |
| alt_bar_chart = alt.Chart(grouped_df).mark_bar(color='#3ac81e').encode(x=column, y='clicks') |
| st.altair_chart(alt_bar_chart, use_container_width=True) |
|
|
| st.title("Top Products") |
| agg_df = df[['keyword', 'publisherid', 'Skus', 'count']] |
| agg_df.rename(columns={'keyword': 'Keywords', 'publisherid': 'PublisherID', 'count': 'Clicks'}, inplace=True) |
| agg_df = agg_df.groupby(['Skus', 'Keywords', 'PublisherID']).sum().reset_index() |
| agg_df = agg_df.sort_values(by='Clicks', ascending=False).reset_index(drop=True) |
| st.dataframe(agg_df.head(20), width=1000) |
|
|
|
|
| create_folder('bizrate') |
| create_folder('sqlite_databases') |
|
|
| page_names_to_funcs = { |
| "—": intro, |
| "Generate Recommendations": generate_recommendations, |
| "Product Recommendations": display_recommendations, |
| "Analytics": display_analytics |
| } |
|
|
| page_name = st.sidebar.selectbox("Choose a Page", page_names_to_funcs.keys()) |
| page_names_to_funcs[page_name]() |