Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -138,6 +138,123 @@ def main():
|
|
| 138 |
else:
|
| 139 |
st.warning("No se pudieron cargar los datos. Por favor, verifica la instalación.")
|
| 140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
if __name__ == "__main__":
|
| 142 |
try:
|
| 143 |
main()
|
|
|
|
| 138 |
else:
|
| 139 |
st.warning("No se pudieron cargar los datos. Por favor, verifica la instalación.")
|
| 140 |
|
| 141 |
+
if __name__ == "__main__":
|
| 142 |
+
try:
|
| 143 |
+
main()
|
| 144 |
+
finally:
|
| 145 |
+
gc.collect()
|
| 146 |
+
|
| 147 |
+
import streamlit as st
|
| 148 |
+
from transformers import pipeline
|
| 149 |
+
import pandas as pd
|
| 150 |
+
import plotly.express as px
|
| 151 |
+
import nltk
|
| 152 |
+
from nltk.tokenize import word_tokenize
|
| 153 |
+
from nltk.corpus import stopwords
|
| 154 |
+
from nltk.stem import WordNetLemmatizer
|
| 155 |
+
import re
|
| 156 |
+
import gc
|
| 157 |
+
|
| 158 |
+
st.set_page_config(page_title="Análisis de Reseñas de Amazon", page_icon="📊", layout="wide")
|
| 159 |
+
|
| 160 |
+
@st.cache_resource
|
| 161 |
+
def load_sentiment_analyzer():
|
| 162 |
+
return pipeline("sentiment-analysis", model="nlptown/bert-base-multilingual-uncased-sentiment")
|
| 163 |
+
|
| 164 |
+
@st.cache_resource
|
| 165 |
+
def download_nltk_resources():
|
| 166 |
+
nltk.download('punkt')
|
| 167 |
+
nltk.download('stopwords')
|
| 168 |
+
nltk.download('wordnet')
|
| 169 |
+
|
| 170 |
+
@st.cache_data
|
| 171 |
+
def load_data():
|
| 172 |
+
try:
|
| 173 |
+
return pd.read_csv('sample_reviews.csv')
|
| 174 |
+
except Exception as e:
|
| 175 |
+
st.error(f"Error cargando datos: {str(e)}")
|
| 176 |
+
return None
|
| 177 |
+
|
| 178 |
+
def analyze_sentiment(text):
|
| 179 |
+
analyzer = load_sentiment_analyzer()
|
| 180 |
+
result = analyzer(text)[0]
|
| 181 |
+
rating = int(result['label'].split()[0])
|
| 182 |
+
if rating >= 4:
|
| 183 |
+
sentiment = "POSITIVO"
|
| 184 |
+
color = "green"
|
| 185 |
+
elif rating == 3:
|
| 186 |
+
sentiment = "NEUTRAL"
|
| 187 |
+
color = "blue"
|
| 188 |
+
else:
|
| 189 |
+
sentiment = "NEGATIVO"
|
| 190 |
+
color = "red"
|
| 191 |
+
return sentiment, result['score'], color
|
| 192 |
+
|
| 193 |
+
def main():
|
| 194 |
+
st.title("📊 Análisis de Reseñas de Amazon")
|
| 195 |
+
|
| 196 |
+
# Sección de Análisis de Texto en Tiempo Real
|
| 197 |
+
st.header("🔍 Análisis de Sentimiento en Tiempo Real")
|
| 198 |
+
user_text = st.text_area("Escribe o pega un texto para analizar:", height=150)
|
| 199 |
+
|
| 200 |
+
if user_text:
|
| 201 |
+
with st.spinner('Analizando sentimiento...'):
|
| 202 |
+
sentiment, confidence, color = analyze_sentiment(user_text)
|
| 203 |
+
|
| 204 |
+
col1, col2 = st.columns(2)
|
| 205 |
+
col1.metric("Sentimiento", sentiment)
|
| 206 |
+
col2.metric("Confianza", f"{confidence:.2%}")
|
| 207 |
+
|
| 208 |
+
st.markdown(f"<h3 style='color: {color};'>Resultado: {sentiment}</h3>", unsafe_allow_html=True)
|
| 209 |
+
|
| 210 |
+
# Separador
|
| 211 |
+
st.markdown("---")
|
| 212 |
+
|
| 213 |
+
# Dashboard Original
|
| 214 |
+
download_nltk_resources()
|
| 215 |
+
df = load_data()
|
| 216 |
+
|
| 217 |
+
if df is not None:
|
| 218 |
+
categories = ['Todas'] + sorted(df['product_category'].unique().tolist())
|
| 219 |
+
selected_category = st.sidebar.selectbox("Categoría de Producto", categories)
|
| 220 |
+
|
| 221 |
+
df_filtered = df[df['product_category'] == selected_category] if selected_category != 'Todas' else df
|
| 222 |
+
|
| 223 |
+
col1, col2 = st.columns(2)
|
| 224 |
+
|
| 225 |
+
with col1:
|
| 226 |
+
sentiment_counts = df_filtered['sentiment'].value_counts()
|
| 227 |
+
fig_sentiment = px.pie(
|
| 228 |
+
values=sentiment_counts.values,
|
| 229 |
+
names=sentiment_counts.index,
|
| 230 |
+
title="Distribución de Sentimientos"
|
| 231 |
+
)
|
| 232 |
+
st.plotly_chart(fig_sentiment, use_container_width=True)
|
| 233 |
+
|
| 234 |
+
with col2:
|
| 235 |
+
rating_counts = df_filtered['star_rating'].value_counts().sort_index()
|
| 236 |
+
fig_ratings = px.bar(
|
| 237 |
+
x=rating_counts.index,
|
| 238 |
+
y=rating_counts.values,
|
| 239 |
+
title="Distribución de Ratings",
|
| 240 |
+
labels={'x': 'Rating', 'y': 'Cantidad'}
|
| 241 |
+
)
|
| 242 |
+
st.plotly_chart(fig_ratings, use_container_width=True)
|
| 243 |
+
|
| 244 |
+
col1, col2, col3 = st.columns(3)
|
| 245 |
+
col1.metric("Total de Reseñas", f"{len(df_filtered):,}")
|
| 246 |
+
col2.metric("Rating Promedio", f"{df_filtered['star_rating'].mean():.2f}⭐")
|
| 247 |
+
col3.metric("% Positivas", f"{(df_filtered['sentiment'] == 'positive').mean():.1%}")
|
| 248 |
+
|
| 249 |
+
if selected_category == 'Todas':
|
| 250 |
+
st.header("📊 Análisis por Categoría")
|
| 251 |
+
category_stats = df.groupby('product_category').agg({
|
| 252 |
+
'star_rating': 'mean',
|
| 253 |
+
'sentiment': lambda x: (x == 'positive').mean()
|
| 254 |
+
}).round(3)
|
| 255 |
+
category_stats.columns = ['Rating Promedio', '% Positivas']
|
| 256 |
+
st.dataframe(category_stats)
|
| 257 |
+
|
| 258 |
if __name__ == "__main__":
|
| 259 |
try:
|
| 260 |
main()
|