import pandas as pd import difflib from spacy.tokens import Doc import numpy as np from numpy import dot from numpy.linalg import norm from pyvis.network import Network import streamlit.components.v1 as components color_code_node = { 0: '#4B9EFF', 1: '#4BD4FF', 2: '#3CDFCB', 3: '#37DF8E', 4: '#A0C159', 5: '#CA804B', 6: '#CA524B', 7: '#CA4B97', 8: '#C04BCA', 9: '#5D4BCA', 10: '#213ABA', 11: '#0E6697', } class HealthseaSearch: def __init__(self, _health_aspects, _products, _conditions, _benefits): self.health_aspects = _health_aspects self.products = _products self.conditions = _conditions self.benefits = _benefits def __call__(self, query): return query # Load product meta def get_products(self, _aspect, n): product_list = [] product_ids = {} _n = n _aspect = _aspect.replace(" ", "_") if _aspect in self.health_aspects: aspect = self.health_aspects[_aspect] else: _aspect = difflib.get_close_matches("_aspect", self.health_aspects.keys())[ 0 ] aspect = self.health_aspects[_aspect] product_scoring = aspect["products"] if n != 0: if n > len(product_scoring): n = len(product_scoring) product_scoring = aspect["products"][:n] for product in product_scoring: if product[1] not in product_ids: product_list.append((product[0], self.products[product[1]], _aspect)) product_ids[product[1]] = 1 for alias in aspect["alias"]: n = _n _product_scoring = self.health_aspects[alias]["products"] if n != 0: if n > len(_product_scoring): n = len(_product_scoring) _product_scoring = self.health_aspects[alias]["products"][:n] for product in _product_scoring: if product[1] not in product_ids: product_list.append((product[0], self.products[product[1]], alias)) product_ids[product[1]] = 1 n = _n if len(product_list) > n and n != 0: product_list = product_list[:n] product_list = sorted(product_list, key=lambda tup: tup[0], reverse=True) return product_list # Load product meta and return as DataFrame def get_products_df(self, _aspect, n): product_list = self.get_products(_aspect, n) product_data = { "product": [], "score": [], "health_aspect": [], "rating": [], "reviews": [], } for product in product_list: product_data["score"].append(product[0]) product_data["product"].append(product[1]["name"]) product_data["health_aspect"].append(product[2]) product_data["rating"].append(product[1]["rating"]) product_data["reviews"].append(product[1]["review_count"]) datatypes = { "product": str, "score": int, "health_aspect": str, "rating": str, "reviews": int, } df = pd.DataFrame(data=product_data) df = df.astype(datatypes) return df # Get health aspect def get_aspect(self, _aspect): _aspect = _aspect.replace(" ", "_") if _aspect in self.health_aspects: return self.health_aspects[_aspect] else: _aspect = difflib.get_close_matches("_aspect", self.health_aspects.keys())[ 0 ] return self.health_aspects[_aspect] # Get health aspect meta def get_aspect_meta(self, _aspect): _aspect = _aspect.replace(" ", "_") if _aspect in self.conditions: return self.conditions[_aspect] elif _aspect in self.benefits: return self.benefits[_aspect] else: _aspect = difflib.get_close_matches("_aspect", self.conditions.keys())[0] return self.conditions[_aspect] def pyvis(self, vectors): net = Network(height='500px', width='700px', bgcolor="#0E1117", font_color="#ffffff") net.barnes_hut(gravity=-2500) net.set_edge_smooth("dynamic") net.toggle_stabilization(False) net.add_node(vectors[0][0], label=vectors[0][0], color="#4EA0DB", value=100, shape="circle") # node id = 1 and label = Node 1 for vector in vectors[1:]: net.add_node(vector[0], label=vector[0], color="#FE51B9", value=70, shape="circle") # node id = 1 and label = Node 1 for i, vector in enumerate(vectors): current_vector = vectors[i] if i < len(vectors): if i == 0: for _vector in vectors[i+1:]: sim = self.calculate_cosine_sim(current_vector[1],_vector[1]) net.add_edge(current_vector[0],_vector[0], weight=sim, value=sim, title=sim) else: for _vector in vectors[i+1:]: sim = self.calculate_cosine_sim(current_vector[1],_vector[1]) net.add_edge(current_vector[0],_vector[0], weight=sim, value=sim/2, title=sim) #for _vector in vectors[1:]: # sim = self.calculate_cosine_sim(vectors[0][1],_vector[1]) # net.add_edge(vectors[0][0],_vector[0], weight=sim, value=sim*0.1, title=sim) net.save_graph("viz.html") HtmlFile = open("viz.html", 'r', encoding='utf-8') source_code = HtmlFile.read() components.html(source_code, height = 500, width=700) # Experimental def get_recursive_alias(self, _aspect, n, node_list, edge_list, _max): aspect = self.get_aspect(_aspect) aspect_name = aspect["name"].replace(" ","_") if aspect_name not in node_list: node_list[aspect_name] = {"level":n} aspect_alias = aspect["alias"] if len(aspect_alias) > 0 and n <= _max: for alias in aspect_alias: if alias not in node_list: edge_list.append((aspect_name,alias,n)) self.get_recursive_alias(alias, n+1, node_list, edge_list,_max) return node_list, edge_list else: return node_list, edge_list def add_to_network(self, network, node_list, edge_list): for node in node_list: value = 100-(15*node_list[node]["level"]) network.add_node(node, label=node, color=color_code_node[node_list[node]["level"]], value=value, shape="dot", title = str(node_list[node]["level"])) for edge in edge_list: value = 1-(0.15*edge[2]) network.add_edge(edge[0], edge[1], value=value) def pyvis2(self, node_list, edge_list): net = Network(height='500px', width='700px', bgcolor="#0E1117", font_color="#ffffff") net.barnes_hut(gravity=-2500-(len(node_list)*2)) net.set_edge_smooth("dynamic") self.add_to_network(net, node_list, edge_list) net.save_graph("viz.html") HtmlFile = open("viz.html", 'r', encoding='utf-8') source_code = HtmlFile.read() components.html(source_code, height = 500, width=700) def calculate_cosine_sim(self,a,b): cos_sim = dot(a, b)/(norm(a)*norm(b)) return cos_sim # Load substance meta def get_substances(self, _aspect, n): substance_list = [] substance_ids = {} exclude = ["sodium", "sugar", "sugar_alcohol"] _n = n _aspect = _aspect.replace(" ", "_") if _aspect in self.health_aspects: aspect = self.health_aspects[_aspect] else: _aspect = difflib.get_close_matches("_aspect", self.health_aspects.keys())[ 0 ] aspect = self.health_aspects[_aspect] substance_scoring = aspect["substance"] if n != 0: if n > len(substance_scoring): n = len(substance_scoring) substance_scoring = aspect["substance"][:n] for substance in substance_scoring: if substance[1] in exclude: continue if substance[1] not in substance_ids: substance_list.append((substance[0], substance[1], _aspect)) substance_ids[substance[1]] = 1 for alias in aspect["alias"]: n = _n _substance_scoring = self.health_aspects[alias]["substance"] if n != 0: if n > len(_substance_scoring): n = len(_substance_scoring) _substance_scoring = self.health_aspects[alias]["substance"][:n] for substance in _substance_scoring: if substance[1] in exclude: continue if substance[1] not in substance_ids: substance_list.append((substance[0], substance[1], alias)) substance_ids[substance[1]] = 1 n = _n if len(substance_list) > n and n != 0: substance_list = substance_list[:n] substance_list = sorted(substance_list, key=lambda tup: tup[0], reverse=True) return substance_list # Load substance meta and return as DataFrame def get_substances_df(self, _aspect, n): substance_list = self.get_substances(_aspect, n) substance_data = {"substance": [], "score": [], "health_aspect": []} for substance in substance_list: substance_data["score"].append(substance[0]) substance_data["substance"].append(substance[1]) substance_data["health_aspect"].append(substance[2]) datatypes = {"substance": str, "score": int, "health_aspect": str} df = pd.DataFrame(data=substance_data) df = df.astype(datatypes) return df # Get all health aspect indices def get_all_conditions(self): condition_list = [] for condition_key in self.conditions: if condition_key in self.health_aspects: alias = len(self.health_aspects[condition_key]["alias"]) else: alias = 0 condition_list.append((self.conditions[condition_key]["frequency"],condition_key,alias)) condition_list = sorted(condition_list, key=lambda tup: tup[0], reverse=True) return condition_list def get_all_conditions_df(self): condition_list = self.get_all_conditions()[:100] condition_data = { "Condition": [], "Frequency": [], "Alias": [] } for condition in condition_list: condition_data["Frequency"].append(condition[0]) condition_data["Condition"].append(condition[1]) condition_data["Alias"].append(condition[2]) datatypes = { "Frequency": int, "Condition": str, "Alias": int } df = pd.DataFrame(data=condition_data) df = df.astype(datatypes) return df def get_all_benefits(self): benefit_list = [] for benefit_key in self.benefits: if benefit_key in self.health_aspects: alias = len(self.health_aspects[benefit_key]["alias"]) else: alias = 0 benefit_list.append((self.benefits[benefit_key]["frequency"],benefit_key,alias)) benefit_list = sorted(benefit_list, key=lambda tup: tup[0], reverse=True) return benefit_list def get_all_benefits_df(self): benefit_list = self.get_all_benefits()[:100] benefit_data = { "Benefit": [], "Frequency": [], "Alias": [] } for benefit in benefit_list: benefit_data["Frequency"].append(benefit[0]) benefit_data["Benefit"].append(benefit[1]) benefit_data["Alias"].append(benefit[2]) datatypes = { "Frequency": int, "Benefit": str, "Alias": int } df = pd.DataFrame(data=benefit_data) df = df.astype(datatypes) return df