WALTERMAC commited on
Commit
e125fdd
verified
1 Parent(s): 2c77392

Upload 2 files

Browse files

se agregan archivos de prueba

Files changed (2) hide show
  1. app.py +241 -0
  2. requirements.txt +0 -0
app.py ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import re
3
+ from datetime import datetime
4
+ import streamlit as st
5
+ from transformers import pipeline
6
+ import nltk
7
+ from nltk.corpus import stopwords
8
+ from nltk.util import ngrams
9
+ from collections import Counter
10
+ import plotly.express as px
11
+
12
+ # Descargar stopwords de nltk
13
+ nltk.download('stopwords')
14
+ nltk.download('punkt')
15
+
16
+ # Cargar el pipeline de an谩lisis de sentimientos
17
+ sentiment_analysis = pipeline('sentiment-analysis', model='dccuchile/bert-base-spanish-wwm-uncased')
18
+
19
+ # Funci贸n para procesar el archivo .txt de WhatsApp
20
+ def cargar_chat_txt(file):
21
+ content = file.getvalue().decode('utf-8')
22
+ lines = content.splitlines()
23
+
24
+ fechas = []
25
+ autores = []
26
+ mensajes = []
27
+
28
+ pattern = r"(\d{1,2}/\d{1,2}/\d{4}), (\d{1,2}:\d{2}\s?[ap]\.?\s?[m]\.?) - (.*?):(.*)"
29
+
30
+ for line in lines:
31
+ if "cifrados de extremo a extremo" in line:
32
+ continue
33
+
34
+ match = re.match(pattern, line.strip())
35
+
36
+ if match:
37
+ fecha = match.group(1)
38
+ hora = match.group(2)
39
+ autor = match.group(3).strip()
40
+ mensaje = match.group(4).strip()
41
+
42
+ hora = hora.replace("\u202f", "").strip()
43
+ hora = hora.replace(".", "")
44
+
45
+ fecha_hora_str = f"{fecha} {hora}"
46
+
47
+ try:
48
+ fecha_hora = datetime.strptime(fecha_hora_str, "%d/%m/%Y %I:%M%p")
49
+ except ValueError as e:
50
+ print(f"Error al parsear la fecha y hora: {fecha_hora_str} - {e}")
51
+ continue
52
+
53
+ fechas.append(fecha_hora)
54
+ autores.append(autor)
55
+ mensajes.append(mensaje)
56
+
57
+ df = pd.DataFrame({
58
+ 'FechaHora': fechas,
59
+ 'Autor': autores,
60
+ 'Mensaje': mensajes
61
+ })
62
+
63
+ if 'FechaHora' in df.columns and 'Autor' in df.columns and 'Mensaje' in df.columns:
64
+ df['FechaHora'] = pd.to_datetime(df['FechaHora'])
65
+ return df
66
+ else:
67
+ return None
68
+
69
+ # Funci贸n para quitar las stopwords de los mensajes
70
+ def quitar_stopwords(mensaje):
71
+ stop_words = set(stopwords.words('spanish'))
72
+ mensaje_tokens = nltk.word_tokenize(mensaje.lower())
73
+ mensaje_filtrado = [word for word in mensaje_tokens if word not in stop_words]
74
+ return ' '.join(mensaje_filtrado)
75
+
76
+ # Funci贸n para extraer bigramas y trigramas
77
+ def extraer_bigrams_trigrams(mensaje):
78
+ tokens = nltk.word_tokenize(mensaje.lower())
79
+ bigrams = list(ngrams(tokens, 2))
80
+ trigrams = list(ngrams(tokens, 3))
81
+ return bigrams, trigrams
82
+
83
+ # Funci贸n para clasificar la urgencia basada en el autor
84
+ def urgencia_por_autor(autor):
85
+ autores_prioritarios = ["Jefe", "Hijo", "Mam谩", "Pap谩", "Esposa"]
86
+
87
+ if any(char in autor for char in ["鉂わ笍", "馃挅", "馃挊", "馃挐", "馃挄"]):
88
+ return 2 # Asignar urgencia alta si el autor tiene coraz贸n en su nombre
89
+
90
+ return 2 if autor in autores_prioritarios else 0
91
+
92
+ # Funci贸n para clasificar la urgencia basada en la hora
93
+ def urgencia_por_hora(hora):
94
+ hora = datetime.strptime(hora, "%H:%M")
95
+ if hora >= datetime.strptime("20:00", "%H:%M") or hora <= datetime.strptime("05:00", "%H:%M"):
96
+ return 1
97
+ return 0
98
+
99
+ # Funci贸n para clasificar la urgencia basada en el sentimiento
100
+ def urgencia_por_sentimiento(sentimiento):
101
+ if sentimiento == 'LABEL_4': # Muy negativo
102
+ return 3 # Alta urgencia
103
+ elif sentimiento == 'LABEL_3': # Negativo
104
+ return 2 # Urgencia moderada
105
+ elif sentimiento == 'LABEL_2': # Neutro
106
+ return 1 # Baja urgencia
107
+ elif sentimiento == 'LABEL_1': # Positivo
108
+ return 1 # Baja urgencia
109
+ elif sentimiento == 'LABEL_0': # Muy positivo
110
+ return 0 # Sin urgencia
111
+ return 0 # Si no coincide con ning煤n sentimiento, asignar baja urgencia
112
+
113
+ # Funci贸n para verificar si el mensaje contiene palabras clave de urgencia
114
+ def urgencia_por_palabras_clave(mensaje):
115
+ palabras_clave = ["urgente", "es urgente", "es para hoy", "necesito ayuda", "por favor", "con urgencia"]
116
+ mensaje = mensaje.lower()
117
+
118
+ for palabra in palabras_clave:
119
+ if palabra in mensaje:
120
+ return 1 # Incrementa urgencia
121
+ return 0 # No hay urgencia en las palabras clave
122
+
123
+ # Funci贸n para verificar si el mensaje contiene palabras negativas
124
+ def urgencia_por_palabras_negativas(mensaje):
125
+ palabras_negativas = ["malo", "no me gusta", "odio", "peor", "terrible", "desastroso", "fatal"]
126
+ mensaje = mensaje.lower()
127
+
128
+ for palabra in palabras_negativas:
129
+ if palabra in mensaje:
130
+ return 2 # Incrementa urgencia por negatividad
131
+ return 0 # No hay urgencia en las palabras negativas
132
+
133
+ # Funci贸n para mapear las etiquetas del an谩lisis de sentimientos a etiquetas legibles
134
+ def mapear_sentimiento(sentimiento):
135
+ sentimiento_mapeado = {
136
+ 'LABEL_0': 'Muy Positivo',
137
+ 'LABEL_1': 'Positivo',
138
+ 'LABEL_2': 'Neutro',
139
+ 'LABEL_3': 'Negativo',
140
+ 'LABEL_4': 'Muy Negativo'
141
+ }
142
+ return sentimiento_mapeado.get(sentimiento, 'Desconocido') # Si no encuentra la etiqueta, regresa "Desconocido"
143
+
144
+
145
+ # Funci贸n para calcular el nivel de urgencia
146
+ def calcular_urgencia(row):
147
+ mensaje_filtrado = quitar_stopwords(row['Mensaje'])
148
+
149
+ # Extraer bigramas y trigramas
150
+ bigrams, trigrams = extraer_bigrams_trigrams(mensaje_filtrado)
151
+
152
+ # An谩lisis de sentimiento
153
+ result = sentiment_analysis(mensaje_filtrado)
154
+ sentimiento = result[0]['label']
155
+ probabilidad = result[0]['score']
156
+
157
+ # Mapear el sentimiento a texto legible
158
+ sentimiento_legible = mapear_sentimiento(sentimiento)
159
+
160
+ # Si la probabilidad es baja, clasificar como "Neutro"
161
+ if probabilidad < 0.6:
162
+ sentimiento_legible = 'Neutro'
163
+
164
+ # Clasificaci贸n de urgencia
165
+ urgencia = urgencia_por_autor(row['Autor']) + urgencia_por_hora(row['FechaHora'].strftime('%H:%M')) + urgencia_por_sentimiento(sentimiento)
166
+
167
+ urgencia += urgencia_por_palabras_clave(row['Mensaje'])
168
+ urgencia += urgencia_por_palabras_negativas(row['Mensaje'])
169
+
170
+ # Ahora, tambi茅n vamos a agregar la urgencia por los bigramas y trigramas
171
+ for bigram in bigrams + trigrams:
172
+ bigram_str = ' '.join(bigram)
173
+ sentiment_bigram = sentiment_analysis(bigram_str)[0]['label']
174
+ urgencia += urgencia_por_sentimiento(sentiment_bigram)
175
+
176
+ return min(5, urgencia), sentimiento_legible # Regresamos la urgencia y el sentimiento legible
177
+
178
+
179
+ # Funci贸n para extraer y contar bigramas y trigramas de un DataFrame
180
+ def obtener_bigrams_trigrams(df):
181
+ bigramas = []
182
+ trigramas = []
183
+
184
+ for mensaje in df['Mensaje']:
185
+ bigrams, trigrams = extraer_bigrams_trigrams(mensaje)
186
+ bigramas.extend([' '.join(bigram) for bigram in bigrams])
187
+ trigramas.extend([' '.join(trigram) for trigram in trigrams])
188
+
189
+ return bigramas, trigramas
190
+
191
+ # Funci贸n para visualizar bigramas y trigramas en un gr谩fico
192
+ def mostrar_grafica_bigrams_trigrams(bigramas, trigramas):
193
+ # Contamos las ocurrencias de bigramas y trigramas
194
+ bigram_count = Counter(bigramas).most_common(10)
195
+ trigram_count = Counter(trigramas).most_common(10)
196
+
197
+ # Bigramas
198
+ bigram_df = pd.DataFrame(bigram_count, columns=['Bigram', 'Frecuencia'])
199
+ fig_bigram = px.bar(bigram_df, x='Bigram', y='Frecuencia', title="Top 10 Bigramas m谩s comunes")
200
+
201
+ # Trigramas
202
+ trigram_df = pd.DataFrame(trigram_count, columns=['Trigram', 'Frecuencia'])
203
+ fig_trigram = px.bar(trigram_df, x='Trigram', y='Frecuencia', title="Top 10 Trigramas m谩s comunes")
204
+
205
+ return fig_bigram, fig_trigram
206
+
207
+ # Streamlit application code
208
+ st.title("An谩lisis de Chat de WhatsApp")
209
+
210
+ uploaded_file = st.file_uploader("Sube un archivo TXT de chat de WhatsApp", type=["txt"])
211
+
212
+ if uploaded_file is not None:
213
+ df_chat = cargar_chat_txt(uploaded_file)
214
+
215
+ if df_chat is not None and not df_chat.empty:
216
+ st.write("Primeros mensajes del chat:")
217
+ st.dataframe(df_chat.head())
218
+
219
+ # Calcular la urgencia y sentimiento
220
+ df_chat[['Urgencia', 'Sentimiento']] = df_chat.apply(calcular_urgencia, axis=1, result_type='expand')
221
+
222
+ st.write("Mensajes con su nivel de urgencia y sentimiento:")
223
+ st.dataframe(df_chat[['FechaHora', 'Autor', 'Mensaje', 'Urgencia', 'Sentimiento']])
224
+
225
+ # Extraer bigramas y trigramas
226
+ bigramas, trigramas = obtener_bigrams_trigrams(df_chat)
227
+
228
+ # Mostrar gr谩ficas
229
+ fig_bigram, fig_trigram = mostrar_grafica_bigrams_trigrams(bigramas, trigramas)
230
+
231
+ st.plotly_chart(fig_bigram)
232
+ st.plotly_chart(fig_trigram)
233
+
234
+ # Visualizaci贸n del nivel de urgencia
235
+ if st.button('Mostrar Gr谩fico de Urgencia'):
236
+ urgencia_count = df_chat['Urgencia'].value_counts().reset_index()
237
+ urgencia_count.columns = ['Urgencia', 'Cantidad']
238
+ fig = px.bar(urgencia_count, x='Urgencia', y='Cantidad', title="Distribuci贸n de Niveles de Urgencia")
239
+ st.plotly_chart(fig)
240
+ else:
241
+ st.write("No se encontraron mensajes en el archivo.")
requirements.txt ADDED
Binary file (3.47 kB). View file