VicGerardoPR commited on
Commit
48a9b19
·
verified ·
1 Parent(s): 4661fa3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -61
app.py CHANGED
@@ -5,6 +5,8 @@ import seaborn as sns
5
  import io
6
  import base64
7
  from PIL import Image
 
 
8
 
9
  # Configuración de la página
10
  st.set_page_config(
@@ -17,7 +19,7 @@ st.set_page_config(
17
  st.title("📊 Visualizador de Datos")
18
  st.markdown("### Carga tu archivo CSV o Excel y crea visualizaciones personalizadas")
19
 
20
- # Función para cargar el archivo
21
  def load_data():
22
  uploaded_file = st.file_uploader("Carga tu archivo CSV o Excel", type=["csv", "xlsx", "xls"])
23
 
@@ -29,45 +31,102 @@ def load_data():
29
  else:
30
  data = pd.read_excel(uploaded_file)
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  return data
33
  except Exception as e:
34
  st.error(f"Error al cargar el archivo: {e}")
35
  return None
36
  return None
37
 
38
- # Función para generar gráficos
39
- def create_plot(data, x_col, y_col, plot_type):
40
- fig, ax = plt.subplots(figsize=(10, 6))
41
 
42
- if plot_type == "Barras":
43
- sns.barplot(x=x_col, y=y_col, data=data, ax=ax)
44
- elif plot_type == "Barras (Count)":
45
- # Crear conteo de valores
46
- count_data = data[x_col].value_counts().reset_index()
47
- count_data.columns = [x_col, 'count']
48
- sns.barplot(x=x_col, y='count', data=count_data, ax=ax)
49
- plt.ylabel('Frecuencia')
50
- elif plot_type == "Líneas":
51
- sns.lineplot(x=x_col, y=y_col, data=data, ax=ax)
52
- elif plot_type == "Dispersión":
53
- sns.scatterplot(x=x_col, y=y_col, data=data, ax=ax)
54
- elif plot_type == "Histograma":
55
- sns.histplot(data[x_col], ax=ax)
56
- plt.xlabel(x_col)
57
- elif plot_type == "Boxplot":
58
- sns.boxplot(x=x_col, y=y_col, data=data, ax=ax)
59
- elif plot_type == "Violín":
60
- sns.violinplot(x=x_col, y=y_col, data=data, ax=ax)
61
- elif plot_type == "Pastel":
62
- data[x_col].value_counts().plot.pie(autopct='%1.1f%%', ax=ax)
63
- plt.ylabel('')
64
- elif plot_type == "Mapa de calor":
65
- if len(data) > 100:
66
- sample_data = data.sample(100)
67
- else:
68
- sample_data = data
69
- correlation = sample_data.select_dtypes(include=['float64', 'int64']).corr()
70
- sns.heatmap(correlation, annot=True, cmap='coolwarm', ax=ax)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
  plt.tight_layout()
73
  return fig
@@ -98,55 +157,59 @@ def main():
98
  with col2:
99
  st.info(f"Número de columnas: {data.shape[1]}")
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  # Selección de columnas y tipo de gráfico
102
  st.subheader("Crear visualización")
103
 
104
- col1, col2, col3 = st.columns(3)
105
 
106
  with col1:
 
107
  plot_type = st.selectbox(
108
  "Tipo de gráfico",
109
- ["Barras", "Barras (Count)", "Líneas", "Dispersión", "Histograma", "Boxplot", "Violín", "Pastel", "Mapa de calor"]
110
  )
111
 
112
- # Opciones de columnas basadas en el tipo de gráfico
113
- numeric_cols = data.select_dtypes(include=['float64', 'int64']).columns.tolist()
114
- categorical_cols = data.select_dtypes(include=['object']).columns.tolist()
115
- all_cols = data.columns.tolist()
116
-
117
  with col2:
118
- if plot_type == "Histograma":
119
- x_col = st.selectbox("Selecciona la columna para el histograma", numeric_cols)
120
- y_col = None
121
- elif plot_type == "Mapa de calor":
122
- x_col = "Correlación"
123
- y_col = "Correlación"
124
- elif plot_type == "Pastel":
125
- x_col = st.selectbox("Selecciona la columna para el gráfico de pastel", categorical_cols if categorical_cols else all_cols)
126
- y_col = None
127
- elif plot_type == "Barras (Count)":
128
- x_col = st.selectbox("Selecciona la columna para contar frecuencias", all_cols)
129
- y_col = "count" # Valor especial para indicar que se usará conteo
130
  else:
131
- x_options = categorical_cols + numeric_cols if categorical_cols else all_cols
132
- x_col = st.selectbox("Selecciona la columna para el eje X", x_options)
133
-
134
- with col3:
135
- if plot_type not in ["Histograma", "Pastel", "Mapa de calor", "Barras (Count)"]:
136
- y_col = st.selectbox("Selecciona la columna para el eje Y", numeric_cols if numeric_cols else all_cols)
137
 
138
  # Crear gráfico
139
  if st.button("Generar visualización"):
140
  try:
141
  st.subheader("Visualización")
142
- fig = create_plot(data, x_col, y_col, plot_type)
143
  st.pyplot(fig)
144
 
145
  # Botón para descargar la imagen
146
  st.markdown(
147
  get_image_download_link(
148
  fig,
149
- f"{plot_type}_{x_col}_{y_col if y_col else ''}",
150
  "📥 Descargar imagen"
151
  ),
152
  unsafe_allow_html=True
@@ -154,7 +217,7 @@ def main():
154
 
155
  except Exception as e:
156
  st.error(f"Error al generar el gráfico: {e}")
157
- st.info("Sugerencia: Verifica que las columnas seleccionadas sean compatibles con el tipo de gráfico.")
158
 
159
  # Ejecutar la aplicación
160
  if __name__ == "__main__":
 
5
  import io
6
  import base64
7
  from PIL import Image
8
+ import numpy as np
9
+ from datetime import datetime
10
 
11
  # Configuración de la página
12
  st.set_page_config(
 
19
  st.title("📊 Visualizador de Datos")
20
  st.markdown("### Carga tu archivo CSV o Excel y crea visualizaciones personalizadas")
21
 
22
+ # Función para cargar el archivo y procesar fechas
23
  def load_data():
24
  uploaded_file = st.file_uploader("Carga tu archivo CSV o Excel", type=["csv", "xlsx", "xls"])
25
 
 
31
  else:
32
  data = pd.read_excel(uploaded_file)
33
 
34
+ # Procesar la columna de fecha si existe
35
+ if 'HML_TXDATE' in data.columns:
36
+ try:
37
+ # Convertir a datetime
38
+ data['HML_TXDATE'] = pd.to_datetime(data['HML_TXDATE'])
39
+
40
+ # Extraer el día de la semana
41
+ data['DIA_SEMANA'] = data['HML_TXDATE'].dt.day_name()
42
+
43
+ # Crear una columna con el formato español (opcional)
44
+ dias_esp = {
45
+ 'Monday': 'Lunes',
46
+ 'Tuesday': 'Martes',
47
+ 'Wednesday': 'Miércoles',
48
+ 'Thursday': 'Jueves',
49
+ 'Friday': 'Viernes',
50
+ 'Saturday': 'Sábado',
51
+ 'Sunday': 'Domingo'
52
+ }
53
+ data['DIA_SEMANA_ESP'] = data['DIA_SEMANA'].map(dias_esp)
54
+
55
+ # Extraer otras componentes de tiempo útiles
56
+ data['HORA'] = data['HML_TXDATE'].dt.hour
57
+ data['MES'] = data['HML_TXDATE'].dt.month
58
+ data['AÑO'] = data['HML_TXDATE'].dt.year
59
+
60
+ st.success("✅ Columna de fecha 'HML_TXDATE' procesada correctamente")
61
+ except Exception as e:
62
+ st.warning(f"No se pudo procesar la columna de fecha: {e}")
63
+
64
  return data
65
  except Exception as e:
66
  st.error(f"Error al cargar el archivo: {e}")
67
  return None
68
  return None
69
 
70
+ # Función para generar gráficos basados en conteos
71
+ def create_count_plot(data, x_col, plot_type):
72
+ fig, ax = plt.subplots(figsize=(12, 6))
73
 
74
+ # Preparar datos de conteo
75
+ if x_col in data.columns:
76
+ # Eliminar valores nulos para el conteo
77
+ valid_data = data[x_col].dropna()
78
+
79
+ if plot_type == "Barras":
80
+ # Contar valores y ordenar por frecuencia
81
+ count_data = valid_data.value_counts().reset_index()
82
+ count_data.columns = [x_col, 'count']
83
+
84
+ # Ordenar por conteo de mayor a menor
85
+ count_data = count_data.sort_values('count', ascending=False)
86
+
87
+ # Limitar a los 20 valores más frecuentes para mejor visualización
88
+ if len(count_data) > 20:
89
+ count_data = count_data.head(20)
90
+ plt.title(f"Top 20 valores más frecuentes - {x_col}")
91
+ else:
92
+ plt.title(f"Frecuencia de valores - {x_col}")
93
+
94
+ # Crear gráfico de barras
95
+ sns.barplot(x=x_col, y='count', data=count_data, ax=ax)
96
+ plt.xticks(rotation=45, ha='right')
97
+ plt.ylabel('Frecuencia')
98
+ plt.tight_layout()
99
+
100
+ elif plot_type == "Pastel":
101
+ # Contar valores
102
+ counts = valid_data.value_counts()
103
+
104
+ # Si hay muchos valores únicos, mostrar solo los top 10
105
+ if len(counts) > 10:
106
+ # Guardar el resto como "Otros"
107
+ otros = pd.Series({'Otros': counts[10:].sum()})
108
+ counts = pd.concat([counts[:10], otros])
109
+ plt.title(f"Top 10 valores más frecuentes - {x_col}")
110
+ else:
111
+ plt.title(f"Distribución de valores - {x_col}")
112
+
113
+ # Crear gráfico de pastel
114
+ counts.plot.pie(autopct='%1.1f%%', ax=ax)
115
+ plt.ylabel('')
116
+
117
+ elif plot_type == "Histograma":
118
+ # Solo aplicable a datos numéricos
119
+ if pd.api.types.is_numeric_dtype(valid_data):
120
+ sns.histplot(valid_data, kde=True, ax=ax)
121
+ plt.xlabel(x_col)
122
+ plt.ylabel('Frecuencia')
123
+ plt.title(f"Distribución de {x_col}")
124
+ else:
125
+ plt.text(0.5, 0.5, "El histograma solo es aplicable a datos numéricos",
126
+ ha='center', va='center', transform=ax.transAxes)
127
+ else:
128
+ plt.text(0.5, 0.5, f"Columna '{x_col}' no encontrada en el dataset",
129
+ ha='center', va='center', transform=ax.transAxes)
130
 
131
  plt.tight_layout()
132
  return fig
 
157
  with col2:
158
  st.info(f"Número de columnas: {data.shape[1]}")
159
 
160
+ # Mostrar lista de columnas disponibles
161
+ st.subheader("Columnas disponibles")
162
+ all_cols = data.columns.tolist()
163
+
164
+ # Identificar tipo de datos para cada columna
165
+ col_types = {}
166
+ for col in all_cols:
167
+ if pd.api.types.is_numeric_dtype(data[col]):
168
+ col_types[col] = "Numérico"
169
+ elif pd.api.types.is_datetime64_dtype(data[col]):
170
+ col_types[col] = "Fecha/Hora"
171
+ else:
172
+ col_types[col] = "Texto/Categórico"
173
+
174
+ # Mostrar tipos de columnas
175
+ col_type_df = pd.DataFrame(list(col_types.items()), columns=['Columna', 'Tipo'])
176
+ st.dataframe(col_type_df)
177
+
178
  # Selección de columnas y tipo de gráfico
179
  st.subheader("Crear visualización")
180
 
181
+ col1, col2 = st.columns(2)
182
 
183
  with col1:
184
+ # Visualizaciones basadas en conteo
185
  plot_type = st.selectbox(
186
  "Tipo de gráfico",
187
+ ["Barras", "Pastel", "Histograma"]
188
  )
189
 
 
 
 
 
 
190
  with col2:
191
+ # Mostrar opciones especiales para día de la semana si existe
192
+ if 'DIA_SEMANA_ESP' in data.columns:
193
+ use_day_of_week = st.checkbox("¿Analizar por día de la semana?")
194
+ if use_day_of_week:
195
+ x_col = "DIA_SEMANA_ESP"
196
+ else:
197
+ x_col = st.selectbox("Selecciona la columna para analizar", all_cols)
 
 
 
 
 
198
  else:
199
+ x_col = st.selectbox("Selecciona la columna para analizar", all_cols)
 
 
 
 
 
200
 
201
  # Crear gráfico
202
  if st.button("Generar visualización"):
203
  try:
204
  st.subheader("Visualización")
205
+ fig = create_count_plot(data, x_col, plot_type)
206
  st.pyplot(fig)
207
 
208
  # Botón para descargar la imagen
209
  st.markdown(
210
  get_image_download_link(
211
  fig,
212
+ f"{plot_type}_{x_col}",
213
  "📥 Descargar imagen"
214
  ),
215
  unsafe_allow_html=True
 
217
 
218
  except Exception as e:
219
  st.error(f"Error al generar el gráfico: {e}")
220
+ st.info("Sugerencia: Verifica que la columna seleccionada sea compatible con el tipo de gráfico.")
221
 
222
  # Ejecutar la aplicación
223
  if __name__ == "__main__":