xerubin
commited on
Commit
•
1f9bcbb
1
Parent(s):
f5b4a41
commit inicial
Browse files- app.py +67 -0
- as_bert_df.py +126 -0
- assets/favicon.ico +0 -0
- assets/flags.jpg +0 -0
- assets/header.jpg +0 -0
- page1.py +150 -0
- page2_.py +149 -0
app.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
"""
|
3 |
+
Created on Sat Dec 23 13:22:00 2023
|
4 |
+
@author: Essio Rubin C.
|
5 |
+
"""
|
6 |
+
from PIL import Image
|
7 |
+
import streamlit as st
|
8 |
+
from st_pages import Page, show_pages, add_page_title
|
9 |
+
|
10 |
+
# icon
|
11 |
+
im = Image.open("assets/favicon.ico")
|
12 |
+
st.set_page_config(
|
13 |
+
page_title="Analisis de sentimiento de reseñas de Hoteles",
|
14 |
+
page_icon=im,
|
15 |
+
layout="wide",
|
16 |
+
)
|
17 |
+
|
18 |
+
# img header
|
19 |
+
img = Image.open("assets/header.jpg")
|
20 |
+
st.image(img, width=1000)
|
21 |
+
|
22 |
+
# show links to pages
|
23 |
+
show_pages(
|
24 |
+
[
|
25 |
+
Page("app.py", "Presentación", "🏠"),
|
26 |
+
Page("page1.py", "Análisis de reseñas uno a uno", ":blue_book:"),
|
27 |
+
Page("page2_.py", "Análisis de reseñas en lotes", ":books:"),
|
28 |
+
]
|
29 |
+
)
|
30 |
+
|
31 |
+
# show text
|
32 |
+
css_text_1 = '''
|
33 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
|
34 |
+
|
35 |
+
<p style="font-family: Verdana; font-size: 15px; font-weight: 400; color: #494848;">
|
36 |
+
<span style="font-family: Georgia, serif; font-size: 20px; font-weight: 400; color: blue; font-style: italic; ">IA Hotel Reviews</span> es una aplicación que utiliza Inteligencia Artificial para realizar un análisis inteligente de las reseñas que dejan tus clientes. Ayuda a identificar el sentimiento positivo o negativo que hay detrás de estos comentarios. Obtendrás un análisis certero de la opiniones que vierten tus clientes y con ello puedes tomar mejores decisiones sobre tu personal, las instalaciones y otros aspectos de tu hotel con el fin de ganar más clientes e incrementar tus ganancias.
|
37 |
+
</p>
|
38 |
+
<p style="font-family: Verdana; font-size: 3px;"> </p>
|
39 |
+
<p style="font-family: Verdana; font-size: 15px; font-weight: 300; ; color: #494848;">
|
40 |
+
Este programa es multidioma ya que Las reseñas pueden estar escritas en idioma español, holandés, italiano, alemán, francés o inglés.
|
41 |
+
</p>
|
42 |
+
|
43 |
+
'''
|
44 |
+
st.write(css_text_1, unsafe_allow_html=True)
|
45 |
+
|
46 |
+
# show image
|
47 |
+
img = Image.open("assets/flags.jpg")
|
48 |
+
st.image(img, width=350)
|
49 |
+
|
50 |
+
css_text_2 = '''
|
51 |
+
<p style="font-family: Verdana; font-size: 3px;"> </p>
|
52 |
+
<p style="font-family: Verdana; font-size: 15px; font-weight: 400; color: #494848;">
|
53 |
+
Te ofrecemos dos opciones de análisis:
|
54 |
+
</p>
|
55 |
+
|
56 |
+
<i class="fa-solid fa-gear"></i>
|
57 |
+
|
58 |
+
<a style="font-family: Verdana; font-size: 17px; font-weight: 200; text-decoration: none; ; color: #6c88f4;" href="http://localhost:8501/An%C3%A1lisis%20de%20rese%C3%B1as%20uno%20a%20uno">Análisis de reseñas uno a uno</a>
|
59 |
+
|
60 |
+
<i class="fa-solid fa-gear"></i>
|
61 |
+
|
62 |
+
<a style="font-family: Verdana; font-size: 17px; font-weight: 200; text-decoration: none; ; color: #6c88f4;" href="http://localhost:8501/An%C3%A1lisis%20de%20rese%C3%B1as%20en%20lotes">Análisis de reseñas en lotes</a>
|
63 |
+
'''
|
64 |
+
|
65 |
+
st.write(css_text_2, unsafe_allow_html=True)
|
66 |
+
|
67 |
+
|
as_bert_df.py
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
"""
|
3 |
+
Created on Sun Dec 3 09:26:33 2023
|
4 |
+
|
5 |
+
@author: ideaUser
|
6 |
+
Modelo (huggingface)
|
7 |
+
https://huggingface.co/nlptown/bert-base-multilingual-uncased-sentiment
|
8 |
+
|
9 |
+
"""
|
10 |
+
|
11 |
+
#%%
|
12 |
+
|
13 |
+
import torch
|
14 |
+
from transformers import BertTokenizer, BertForSequenceClassification
|
15 |
+
from transformers import pipeline
|
16 |
+
import pandas as pd
|
17 |
+
|
18 |
+
#%%
|
19 |
+
|
20 |
+
|
21 |
+
# Download pretrained BERT from Hugging Face for sentiment analisis
|
22 |
+
model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
|
23 |
+
tokenizer = BertTokenizer.from_pretrained(model_name)
|
24 |
+
model = BertForSequenceClassification.from_pretrained(model_name)
|
25 |
+
|
26 |
+
# function predict sentiment using BERT pretrained
|
27 |
+
def get_review_sentiment(text):
|
28 |
+
classifier = pipeline("sentiment-analysis", model=model, tokenizer=tokenizer)
|
29 |
+
results = classifier(text)
|
30 |
+
return int(results[0]["label"][0])
|
31 |
+
|
32 |
+
|
33 |
+
#%%
|
34 |
+
# function for batch predict stars
|
35 |
+
def batch_predict_sentiment_stars(data):
|
36 |
+
sentiment = []
|
37 |
+
for index, row in data.iterrows():
|
38 |
+
sentiment.append(get_review_sentiment(row["review"]))
|
39 |
+
data_result = pd.DataFrame(
|
40 |
+
{
|
41 |
+
"review": list(data["review"]),
|
42 |
+
"predict": sentiment
|
43 |
+
})
|
44 |
+
return data_result
|
45 |
+
|
46 |
+
|
47 |
+
#%%
|
48 |
+
# function for batch predict sentiment label [NEGATIVE, NEUTRAL, POSITIVE]
|
49 |
+
def batch_predict_sentiment_3_label(data):
|
50 |
+
sentiment = []
|
51 |
+
for index, row in data.iterrows():
|
52 |
+
stars = get_review_sentiment(row["review"])
|
53 |
+
label = ""
|
54 |
+
if stars < 3:
|
55 |
+
label = "negative"
|
56 |
+
elif stars == 3:
|
57 |
+
label = "neutral"
|
58 |
+
elif stars > 3 & stars <= 5:
|
59 |
+
label = "positive"
|
60 |
+
sentiment.append(label)
|
61 |
+
data_result = pd.DataFrame(
|
62 |
+
{
|
63 |
+
"review": list(data["review"]),
|
64 |
+
"label": list(data["label"]),
|
65 |
+
"predict": sentiment
|
66 |
+
})
|
67 |
+
return data_result
|
68 |
+
|
69 |
+
#%%
|
70 |
+
# function for batch predict sentiment label [NEGATIVE, POSITIVE]
|
71 |
+
def batch_predict_sentiment_2_label(data):
|
72 |
+
total_rows = data.shape[0]
|
73 |
+
sentiment = []
|
74 |
+
i = 1
|
75 |
+
for index, row in data.iterrows():
|
76 |
+
stars = get_review_sentiment(row["review"])
|
77 |
+
label = ""
|
78 |
+
if stars < 3:
|
79 |
+
label = "negative"
|
80 |
+
elif stars >= 3 & stars <= 5:
|
81 |
+
label = "positive"
|
82 |
+
sentiment.append(label)
|
83 |
+
if i % 100 == 0:
|
84 |
+
print(i, " / " , total_rows )
|
85 |
+
i += 1
|
86 |
+
|
87 |
+
# return a dataframe
|
88 |
+
data_result = pd.DataFrame(
|
89 |
+
{
|
90 |
+
"review": list(data["review"]),
|
91 |
+
"label": list(data["label"]),
|
92 |
+
"predict": sentiment
|
93 |
+
})
|
94 |
+
return data_result
|
95 |
+
|
96 |
+
|
97 |
+
#%%
|
98 |
+
if __name__ == "__main__":
|
99 |
+
|
100 |
+
hotel_reviews = ["El fin de semana mi pareja y yo hicimos una reserva en este hotel, con el fin de descansar y desconectar, fue sólo una noche y menos mal. Nos llevaron a un ala bastante apartada del hotel porque nos dijeron que era mejor para descansar ya que la parte de fuera era muy “jaleosa”. Nos pareció bien porque era justo lo que buscábamos, y cuál fue nuestra sorpresa? Desde las 6 de la mañana con ruidos, primero lo que suponemos que eran unos tacones en la habitación de arriba (de eso no tiene culpa el hotel, obviamente) y después sobre las 7 o poco más, las limpiadoras moviendo muebles y arrastrando sofás o lo que fuera. Habíamos cogido sólo alojamiento para descansar, pensando en no tener que madrugar como habitualmente, pero fue IMPOSIBLE por los ruidos constantes. Por destacar algo…",
|
101 |
+
"El hotel en general está bien, las habtiaciones son espaciosas y el personal es muy amable (sobretodo el encargado del roof-top y la piscina) y la zona de la piscina es curiosa. Pero tiene dos grandes fallos: El primero es que el wifi no llegaba bien a la habitación ya que se cortaba continuamente. El segundo fallo es que no se les ocurre otra cosa que poner un edredón nórdico en vez de una sábana fina en pleno agosto en Sevilla.",
|
102 |
+
"El hotel es moderno, amplio y limpio, pero no hemos podido disfrutar de la experiencia porque con tanto ruido no hemos podido descansar. Además la piscina estaba llena de gente y no la hemos podido usar. Los empleados muy amables y la ubicación perfecta."
|
103 |
+
]
|
104 |
+
|
105 |
+
data_df = pd.DataFrame(
|
106 |
+
{
|
107 |
+
"review": hotel_reviews,
|
108 |
+
"label":['positive','negative','positive']
|
109 |
+
}
|
110 |
+
)
|
111 |
+
# save dataframe
|
112 |
+
data_df.to_csv('data/sa_data.csv', index=False)
|
113 |
+
|
114 |
+
#%%
|
115 |
+
# pruebas
|
116 |
+
# read csv
|
117 |
+
data_df = pd.read_csv('data/sa_data.csv')
|
118 |
+
#result = batch_predict_sentiment_stars(data_df)
|
119 |
+
#result = batch_predict_sentiment_3_label(data_df)
|
120 |
+
result = batch_predict_sentiment_2_label(data_df)
|
121 |
+
print("Columns:\n", result.dtypes)
|
122 |
+
print("\n(rows, cols): ", result.shape)
|
123 |
+
print("\nData:\n",result)
|
124 |
+
|
125 |
+
#%%
|
126 |
+
|
assets/favicon.ico
ADDED
assets/flags.jpg
ADDED
assets/header.jpg
ADDED
page1.py
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
"""
|
3 |
+
Created on Sat Dec 23 13:22:00 2023
|
4 |
+
@author: Essio Rubin C.
|
5 |
+
"""
|
6 |
+
from PIL import Image
|
7 |
+
import streamlit as st
|
8 |
+
from st_pages import Page, show_pages, add_page_title
|
9 |
+
import time
|
10 |
+
import pandas as pd
|
11 |
+
import matplotlib.pyplot as plt
|
12 |
+
import numpy as np
|
13 |
+
from as_bert_df import batch_predict_sentiment_stars
|
14 |
+
|
15 |
+
c1 = st.container()
|
16 |
+
c2 = st.container()
|
17 |
+
|
18 |
+
data_df = pd.DataFrame(
|
19 |
+
{
|
20 |
+
"review": ["",], "predict":[0,]
|
21 |
+
}
|
22 |
+
)
|
23 |
+
|
24 |
+
# function to show base page
|
25 |
+
def show_base_page():
|
26 |
+
with c1:
|
27 |
+
# the title and icon to the current page
|
28 |
+
add_page_title()
|
29 |
+
|
30 |
+
# show text
|
31 |
+
text_css = """
|
32 |
+
<p style="font-family: Verdana; font-size: 15px; font-weight: 400; ; color: #494848;">
|
33 |
+
Una reseña debe ser un texto que tenga una o varias oraciones que incluyan opiniones referidas a servicios que brinda
|
34 |
+
un Hotel.
|
35 |
+
La reseña puede estar escrita en idioma español, holandés, italiano, alemán, francés o inglés.
|
36 |
+
</p>
|
37 |
+
|
38 |
+
"""
|
39 |
+
st.write(text_css, unsafe_allow_html=True)
|
40 |
+
|
41 |
+
# show image
|
42 |
+
img = Image.open("assets/flags.jpg")
|
43 |
+
st.image(img, width=200)
|
44 |
+
|
45 |
+
|
46 |
+
# function to show data editor
|
47 |
+
def show_data_editor(data):
|
48 |
+
with c1:
|
49 |
+
# dataframe editor
|
50 |
+
global st_data
|
51 |
+
global placeholder
|
52 |
+
placeholder = st.empty()
|
53 |
+
|
54 |
+
#st_data = st.data_editor(
|
55 |
+
st_data = placeholder.data_editor(
|
56 |
+
data,
|
57 |
+
column_config={
|
58 |
+
"review": st.column_config.TextColumn(
|
59 |
+
"review",
|
60 |
+
help="Ingrese la reseña.",
|
61 |
+
width="large",
|
62 |
+
required=True,
|
63 |
+
max_chars=500,
|
64 |
+
validate="[a-zA-Záéíóúñ.,]+$"
|
65 |
+
),
|
66 |
+
"predict": st.column_config.NumberColumn(
|
67 |
+
"predict",
|
68 |
+
help="Sentimiento expresado en cantidad de estrellas.",
|
69 |
+
width="small",
|
70 |
+
required=False,
|
71 |
+
default=0,
|
72 |
+
min_value=0,
|
73 |
+
max_value=5,
|
74 |
+
format="%d ⭐",
|
75 |
+
)
|
76 |
+
|
77 |
+
},
|
78 |
+
hide_index=True,
|
79 |
+
num_rows="dynamic",
|
80 |
+
height = 260,
|
81 |
+
width = 900,
|
82 |
+
)
|
83 |
+
|
84 |
+
def show_button():
|
85 |
+
global placeholder2
|
86 |
+
placeholder2 = st.empty()
|
87 |
+
with c1:
|
88 |
+
# show buttons
|
89 |
+
global button_1
|
90 |
+
button_1 = placeholder2.button(" :gear: Predecir", type="primary", key='but_1')
|
91 |
+
|
92 |
+
|
93 |
+
# define action funtion for button
|
94 |
+
def predecir():
|
95 |
+
#st.session_state.disabled = True
|
96 |
+
data_df = st_data
|
97 |
+
if data_df.shape[0] > 0:
|
98 |
+
st.write(data_df.shape[0])
|
99 |
+
# progress bar
|
100 |
+
progress_text = "Procesando. Espere."
|
101 |
+
my_bar = st.progress(0, text=progress_text)
|
102 |
+
for percent_complete in range(100):
|
103 |
+
time.sleep(0.01)
|
104 |
+
my_bar.progress(percent_complete + 1, text=progress_text)
|
105 |
+
time.sleep(1)
|
106 |
+
my_bar.empty()
|
107 |
+
result = batch_predict_sentiment_stars(data_df)
|
108 |
+
placeholder.empty()
|
109 |
+
placeholder2.empty()
|
110 |
+
show_data_editor(result)
|
111 |
+
show_chart(result)
|
112 |
+
else:
|
113 |
+
st.error("Debe ingresar una reseña.")
|
114 |
+
|
115 |
+
|
116 |
+
def show_chart(data):
|
117 |
+
with c2:
|
118 |
+
fig, ax = plt.subplots()
|
119 |
+
fig.set_figwidth(5)
|
120 |
+
fig.set_figheight(3)
|
121 |
+
# title
|
122 |
+
ax.set_title("Histograma de Frecuencias", fontsize = 8)
|
123 |
+
|
124 |
+
# axis
|
125 |
+
ax.set_xlim([0, 5])
|
126 |
+
|
127 |
+
# x label
|
128 |
+
ax.set_xlabel('Sentimiento (Número de estrellas)', fontsize = 6)
|
129 |
+
|
130 |
+
ax.set_ylabel('Frecuencia', fontsize = 6)
|
131 |
+
|
132 |
+
# Crear un histograma
|
133 |
+
ax.hist(data['predict'], bins=20, color ="green")
|
134 |
+
|
135 |
+
# Mostrar el gráfico en Streamlit
|
136 |
+
st.pyplot(fig)
|
137 |
+
|
138 |
+
#------------------------------------------
|
139 |
+
# main flow
|
140 |
+
#------------------------------------------
|
141 |
+
show_base_page()
|
142 |
+
show_data_editor(data_df)
|
143 |
+
show_button()
|
144 |
+
if button_1:
|
145 |
+
predecir()
|
146 |
+
|
147 |
+
|
148 |
+
|
149 |
+
|
150 |
+
|
page2_.py
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
"""
|
3 |
+
Created on Sat Dec 23 13:22:00 2023
|
4 |
+
@author: Essio Rubin C.
|
5 |
+
"""
|
6 |
+
from PIL import Image
|
7 |
+
import streamlit as st
|
8 |
+
from st_pages import add_page_title
|
9 |
+
import time
|
10 |
+
import pandas as pd
|
11 |
+
import matplotlib.pyplot as plt
|
12 |
+
from as_bert_df import batch_predict_sentiment_stars
|
13 |
+
|
14 |
+
c1 = st.container()
|
15 |
+
c2 = st.container()
|
16 |
+
|
17 |
+
# function to show base page
|
18 |
+
def show_base_page():
|
19 |
+
with c1:
|
20 |
+
# show title and icon to the current page
|
21 |
+
add_page_title()
|
22 |
+
|
23 |
+
# show text
|
24 |
+
text_css = """
|
25 |
+
<p style="font-family: Verdana; font-size: 15px; font-weight: 400; ; color: #494848;">
|
26 |
+
El archivo de reseñas debe ser un archivo de texto que contenga una reseña por cada línea.
|
27 |
+
La reseña puede estar escrita en idioma español, holandés, italiano, alemán, francés o inglés.
|
28 |
+
</p>
|
29 |
+
<p> </p>
|
30 |
+
"""
|
31 |
+
st.write(text_css, unsafe_allow_html=True)
|
32 |
+
|
33 |
+
# show image
|
34 |
+
img = Image.open("assets/flags.jpg")
|
35 |
+
st.image(img, width=200)
|
36 |
+
|
37 |
+
# placeholder for hide widget
|
38 |
+
global placeholder, placeholder2
|
39 |
+
placeholder = st.empty()
|
40 |
+
placeholder2 = st.empty()
|
41 |
+
|
42 |
+
# file upload
|
43 |
+
global uploaded_file
|
44 |
+
uploaded_file = placeholder.file_uploader("Cargar archivo de reseñas ...", type=['txt', 'csv'], key='uploader')
|
45 |
+
|
46 |
+
global button_1
|
47 |
+
button_1 = placeholder2.button(" :gear: Predecir", type="primary", key='but_1')
|
48 |
+
|
49 |
+
|
50 |
+
|
51 |
+
# define action funtion for button
|
52 |
+
def predecir():
|
53 |
+
if uploaded_file is not None:
|
54 |
+
global data_df
|
55 |
+
# progress bar
|
56 |
+
progress_text = "Procesando. Espere."
|
57 |
+
my_bar = st.progress(0, text=progress_text)
|
58 |
+
|
59 |
+
for percent_complete in range(100):
|
60 |
+
time.sleep(0.01)
|
61 |
+
my_bar.progress(percent_complete + 1, text=progress_text)
|
62 |
+
time.sleep(1)
|
63 |
+
my_bar.empty()
|
64 |
+
|
65 |
+
data_df = pd.read_csv(uploaded_file, sep=";")
|
66 |
+
if data_df.shape[0] > 0:
|
67 |
+
# formatear columnas
|
68 |
+
if data_df.shape[1] < 2:
|
69 |
+
data_df['review'] = 0
|
70 |
+
data_df.columns = ["review","predict"]
|
71 |
+
|
72 |
+
result = batch_predict_sentiment_stars(data_df)
|
73 |
+
|
74 |
+
# mostrar resulyados
|
75 |
+
show_data_editor(result)
|
76 |
+
show_chart(result)
|
77 |
+
placeholder.empty()
|
78 |
+
placeholder2.empty()
|
79 |
+
else:
|
80 |
+
st.error("Archivo se encuentra vacío.")
|
81 |
+
else:
|
82 |
+
st.error("Debe subir un archivo de texto")
|
83 |
+
|
84 |
+
def show_data_editor(data_df):
|
85 |
+
with c2:
|
86 |
+
st.data_editor(
|
87 |
+
data_df,
|
88 |
+
column_config={
|
89 |
+
"review": st.column_config.TextColumn(
|
90 |
+
"review",
|
91 |
+
help="Ingrese la reseña.",
|
92 |
+
width="large",
|
93 |
+
required=True,
|
94 |
+
max_chars=500,
|
95 |
+
validate="[a-zA-Z]+$"
|
96 |
+
),
|
97 |
+
"predict": st.column_config.NumberColumn(
|
98 |
+
"predict",
|
99 |
+
help="Sentimiento expresado en cantidad de estrellas.",
|
100 |
+
width="small",
|
101 |
+
required=False,
|
102 |
+
default=0,
|
103 |
+
min_value=0,
|
104 |
+
max_value=5,
|
105 |
+
format="%d ⭐",
|
106 |
+
)
|
107 |
+
},
|
108 |
+
hide_index=True,
|
109 |
+
num_rows="dynamic",
|
110 |
+
height = 260,
|
111 |
+
width = 900,
|
112 |
+
)
|
113 |
+
|
114 |
+
|
115 |
+
|
116 |
+
def show_chart(data):
|
117 |
+
fig, ax = plt.subplots()
|
118 |
+
fig.set_figwidth(5)
|
119 |
+
fig.set_figheight(3)
|
120 |
+
# title
|
121 |
+
ax.set_title("Histograma de Frecuencias", fontsize = 8)
|
122 |
+
|
123 |
+
# axis
|
124 |
+
ax.set_xlim([0, 5])
|
125 |
+
|
126 |
+
# x label
|
127 |
+
ax.set_xlabel('Sentimiento (Número de estrellas)', fontsize = 6)
|
128 |
+
|
129 |
+
ax.set_ylabel('Frecuencia', fontsize = 6)
|
130 |
+
|
131 |
+
# Crear un histograma
|
132 |
+
ax.hist(data['predict'], bins=20, color ="green")
|
133 |
+
|
134 |
+
# Mostrar el gráfico en Streamlit
|
135 |
+
st.pyplot(fig)
|
136 |
+
|
137 |
+
#------------------------------------------
|
138 |
+
# main flow
|
139 |
+
#------------------------------------------
|
140 |
+
show_base_page()
|
141 |
+
|
142 |
+
if button_1:
|
143 |
+
predecir()
|
144 |
+
|
145 |
+
|
146 |
+
|
147 |
+
|
148 |
+
|
149 |
+
|