Update app.py
Browse files
app.py
CHANGED
|
@@ -36,15 +36,15 @@ x_values = st.sidebar.text_area("Valores para X (separados por comas)", "2013,20
|
|
| 36 |
x = x_values.split(",")
|
| 37 |
|
| 38 |
# Selector de número de variables Y
|
| 39 |
-
num_y_vars = st.sidebar.number_input("Número de variables Y", min_value=1, max_value=100, value=1, step=1)
|
| 40 |
y_values_list = []
|
| 41 |
y_names_list = []
|
| 42 |
for i in range(num_y_vars):
|
| 43 |
if f"y_values_{i}" not in st.session_state:
|
| 44 |
st.session_state[f"y_values_{i}"] = ','.join([str(np.random.randint(1, 25)) for _ in x])
|
| 45 |
-
y_values = st.sidebar.text_area(f"Valores para Y-{i+1} (separados por comas)", st.session_state[f"y_values_{i}"])
|
| 46 |
st.session_state[f"y_values_{i}"] = y_values # Guardar los valores en session_state
|
| 47 |
-
y_name = st.sidebar.text_input(f"Nombre de la Variable Y-{i+1}", f"Variable Y-{i+1}")
|
| 48 |
y_values_list.append(y_values)
|
| 49 |
y_names_list.append(y_name)
|
| 50 |
|
|
@@ -62,16 +62,16 @@ with st.sidebar.expander("Opciones Adicionales"):
|
|
| 62 |
border_width = st.slider("Grosor del Borde", min_value=0.0, max_value=3.0, value=1.5, step=0.1)
|
| 63 |
border_opacity = st.slider("Opacidad del Borde (%)", min_value=0, max_value=100, value=60, step=1) / 100
|
| 64 |
if chart_type == "Barras" and num_y_vars > 1:
|
| 65 |
-
stacked_bars = st.checkbox("Superpuestas")
|
| 66 |
else:
|
| 67 |
stacked_bars = False
|
| 68 |
if chart_type == "Barras":
|
| 69 |
-
horizontal_bars = st.checkbox("Invertidas")
|
| 70 |
if chart_type == "Donut":
|
| 71 |
hole_size = st.slider("Tamaño del agujero (%)", min_value=0, max_value=100, value=30, step=1) / 100
|
| 72 |
|
| 73 |
# Opción para múltiples colores (siempre activada para Donut)
|
| 74 |
-
use_multiple_colors = st.sidebar.checkbox("Usar múltiples colores", value=True if chart_type == "Donut" or num_y_vars > 1 else False)
|
| 75 |
|
| 76 |
# Seleccionar color(es) para el gráfico
|
| 77 |
selected_color = st.sidebar.color_picker("Color", "#24CBA0", key="single_color")
|
|
@@ -218,187 +218,3 @@ else:
|
|
| 218 |
# Información adicional
|
| 219 |
st.write("""
|
| 220 |
""")
|
| 221 |
-
|
| 222 |
-
# Selector de número de variables Y
|
| 223 |
-
num_y_vars = st.sidebar.number_input("Número de variables Y", min_value=1, max_value=100, value=1, step=1)
|
| 224 |
-
y_values_list = []
|
| 225 |
-
y_names_list = []
|
| 226 |
-
for i in range(num_y_vars):
|
| 227 |
-
if f"y_values_{i}" not in st.session_state:
|
| 228 |
-
st.session_state[f"y_values_{i}"] = ','.join([str(np.random.randint(1, 25)) for _ in x])
|
| 229 |
-
y_values = st.sidebar.text_area(f"Valores para Y-{i+1} (separados por comas)", st.session_state[f"y_values_{i}"])
|
| 230 |
-
st.session_state[f"y_values_{i}"] = y_values # Guardar los valores en session_state
|
| 231 |
-
y_name = st.sidebar.text_input(f"Nombre de la Variable Y-{i+1}", f"Variable Y-{i+1}")
|
| 232 |
-
y_values_list.append(y_values)
|
| 233 |
-
y_names_list.append(y_name)
|
| 234 |
-
|
| 235 |
-
# Etiquetas personalizadas para los ejes
|
| 236 |
-
x_label = st.sidebar.text_input("Etiqueta para el eje X", "X")
|
| 237 |
-
y_label = st.sidebar.text_input("Etiqueta para el eje Y", "Y")
|
| 238 |
-
|
| 239 |
-
# Desplegable de opciones adicionales
|
| 240 |
-
with st.sidebar.expander("Opciones Adicionales"):
|
| 241 |
-
graph_width = st.slider("Ancho del Gráfico", min_value=400, max_value=1000, value=800, step=50)
|
| 242 |
-
graph_height = st.slider("Alto del Gráfico", min_value=300, max_value=800, value=600, step=50)
|
| 243 |
-
font_family = st.selectbox("Fuente", font_options, index=font_options.index("Times New Roman"))
|
| 244 |
-
show_legend = st.checkbox("Mostrar Leyenda", value=True)
|
| 245 |
-
opacity = st.slider("Opacidad (%)", min_value=0, max_value=100, value=30, step=1) / 100
|
| 246 |
-
border_width = st.slider("Grosor del Borde", min_value=0.0, max_value=3.0, value=1.5, step=0.1)
|
| 247 |
-
border_opacity = st.slider("Opacidad del Borde (%)", min_value=0, max_value=100, value=60, step=1) / 100
|
| 248 |
-
if chart_type == "Barras" and num_y_vars > 1:
|
| 249 |
-
stacked_bars = st.checkbox("Superpuestas")
|
| 250 |
-
else:
|
| 251 |
-
stacked_bars = False
|
| 252 |
-
if chart_type == "Barras":
|
| 253 |
-
horizontal_bars = st.checkbox("Invertidas")
|
| 254 |
-
if chart_type == "Donut":
|
| 255 |
-
hole_size = st.slider("Tamaño del agujero (%)", min_value=0, max_value=100, value=30, step=1) / 100
|
| 256 |
-
|
| 257 |
-
# Opción para múltiples colores (siempre activada para Donut)
|
| 258 |
-
use_multiple_colors = st.sidebar.checkbox("Usar múltiples colores", value=True if chart_type == "Donut" or num_y_vars > 1 else False)
|
| 259 |
-
|
| 260 |
-
# Seleccionar color(es) para el gráfico
|
| 261 |
-
selected_color = st.sidebar.color_picker("Color", "#24CBA0", key="single_color")
|
| 262 |
-
|
| 263 |
-
# Definir colores
|
| 264 |
-
if use_multiple_colors or chart_type == "Donut":
|
| 265 |
-
num_colors = max(len(y_values_list), len(x))
|
| 266 |
-
colors = [hex_to_rgba(selected_color if i == 0 else st.sidebar.color_picker(f"Color {i+1}", predefined_colors[i % len(predefined_colors)], key=f"color_{i}"), alpha=opacity)
|
| 267 |
-
for i in range(num_colors)]
|
| 268 |
-
border_colors = [hex_to_rgba(selected_color if i == 0 else predefined_colors[i % len(predefined_colors)], alpha=border_opacity)
|
| 269 |
-
for i in range(num_colors)]
|
| 270 |
-
else:
|
| 271 |
-
color = hex_to_rgba(selected_color, alpha=opacity)
|
| 272 |
-
border_color = hex_to_rgba(selected_color, alpha=border_opacity)
|
| 273 |
-
colors = [color] * len(x) # Definir colors para casos donde no se usa múltiple colores
|
| 274 |
-
|
| 275 |
-
# Procesar valores
|
| 276 |
-
y_values_lists = [[float(i) for i in y_values.split(",") if i.strip()] for y_values in y_values_list]
|
| 277 |
-
|
| 278 |
-
# Verificar si las listas tienen el mismo tamaño
|
| 279 |
-
if any(len(x) != len(y) for y in y_values_lists):
|
| 280 |
-
st.error("Todos los valores de X y Y deben tener la misma cantidad de elementos.")
|
| 281 |
-
else:
|
| 282 |
-
# Crear un DataFrame
|
| 283 |
-
data = pd.DataFrame({"X": x})
|
| 284 |
-
for idx, y_set in enumerate(y_values_lists):
|
| 285 |
-
data[y_names_list[idx]] = y_set
|
| 286 |
-
|
| 287 |
-
# Configuración común para todos los gráficos
|
| 288 |
-
common_layout = dict(
|
| 289 |
-
xaxis_title=x_label,
|
| 290 |
-
yaxis_title=y_label,
|
| 291 |
-
plot_bgcolor="white",
|
| 292 |
-
hovermode="x unified",
|
| 293 |
-
width=graph_width,
|
| 294 |
-
height=graph_height,
|
| 295 |
-
margin=dict(l=60, r=40, t=100, b=40),
|
| 296 |
-
xaxis=dict(showgrid=True, zeroline=True, gridcolor='rgba(211,211,211,0.5)', zerolinecolor='rgba(128,128,128,0.5)', autorange=True),
|
| 297 |
-
yaxis=dict(showgrid=True, zeroline=True, gridcolor='rgba(211,211,211,0.5)', zerolinecolor='rgba(128,128,128,0.5)', autorange=True),
|
| 298 |
-
font=dict(family=font_family, size=18, color="black"),
|
| 299 |
-
showlegend=show_legend,
|
| 300 |
-
legend=dict(orientation="v", yanchor="top", y=1, xanchor="left", x=1.02)
|
| 301 |
-
)
|
| 302 |
-
|
| 303 |
-
# Personalizar el hovertemplate
|
| 304 |
-
hovertemplate = '<b>%{y}</b>'
|
| 305 |
-
|
| 306 |
-
# Generar el gráfico basado en el tipo seleccionado
|
| 307 |
-
if chart_type == "Línea":
|
| 308 |
-
fig = px.line(data, x="X", y=y_names_list, line_shape="spline")
|
| 309 |
-
fig.update_traces(hovertemplate=hovertemplate)
|
| 310 |
-
if use_multiple_colors:
|
| 311 |
-
for i, name in enumerate(y_names_list):
|
| 312 |
-
fig.update_traces(selector=dict(name=name), line_color=colors[i % len(colors)])
|
| 313 |
-
else:
|
| 314 |
-
fig.update_traces(line_color=color)
|
| 315 |
-
elif chart_type == "Área":
|
| 316 |
-
fig = px.area(data, x="X", y=y_names_list, line_shape="spline")
|
| 317 |
-
fig.update_traces(hovertemplate=hovertemplate)
|
| 318 |
-
if use_multiple_colors:
|
| 319 |
-
for i, name in enumerate(y_names_list):
|
| 320 |
-
fig.update_traces(selector=dict(name=name), line_color=colors[i % len(colors)], fillcolor=colors[i % len(colors)])
|
| 321 |
-
else:
|
| 322 |
-
fig.update_traces(line_color=color, fillcolor=color)
|
| 323 |
-
elif chart_type == "Dispersión":
|
| 324 |
-
fig = px.scatter(data, x="X", y=y_names_list)
|
| 325 |
-
fig.update_traces(hovertemplate=hovertemplate)
|
| 326 |
-
if use_multiple_colors:
|
| 327 |
-
for i, name in enumerate(y_names_list):
|
| 328 |
-
fig.update_traces(selector=dict(name=name), marker_color=colors[i % len(colors)], marker_line_color=border_colors[i % len(border_colors)], marker_line_width=border_width)
|
| 329 |
-
else:
|
| 330 |
-
fig.update_traces(marker_color=color, marker_line_color=border_color, marker_line_width=border_width)
|
| 331 |
-
elif chart_type == "Barras":
|
| 332 |
-
if horizontal_bars:
|
| 333 |
-
fig = px.bar(data, x=y_names_list, y="X", orientation='h', barmode='stack' if stacked_bars else 'group')
|
| 334 |
-
else:
|
| 335 |
-
fig = px.bar(data, x="X", y=y_names_list, barmode='stack' if stacked_bars else 'group')
|
| 336 |
-
fig.update_traces(hovertemplate=hovertemplate)
|
| 337 |
-
if use_multiple_colors:
|
| 338 |
-
if horizontal_bars:
|
| 339 |
-
fig.update_traces(marker_color=colors[:len(data)], marker_line_color=border_colors[:len(data)], marker_line_width=border_width)
|
| 340 |
-
else:
|
| 341 |
-
fig.update_traces(marker_color=colors[:len(x)], marker_line_color=border_colors[:len(x)], marker_line_width=border_width)
|
| 342 |
-
else:
|
| 343 |
-
fig.update_traces(marker_color=color, marker_line_color=border_color, marker_line_width=border_width)
|
| 344 |
-
fig.update_layout(bargap=0.2)
|
| 345 |
-
elif chart_type == "Donut":
|
| 346 |
-
figs = []
|
| 347 |
-
for i, y_name in enumerate(y_names_list):
|
| 348 |
-
fig = px.pie(data, values=y_name, names="X", hole=hole_size, color_discrete_sequence=colors[:len(x)])
|
| 349 |
-
fig.update_traces(hovertemplate='<b>%{label}</b>: %{value} (%{percent})', textinfo='percent+label')
|
| 350 |
-
fig.update_layout(
|
| 351 |
-
title=dict(
|
| 352 |
-
text=f"{chart_title}<br><sub>{y_name}</sub>" if len(y_names_list) > 1 else chart_title,
|
| 353 |
-
x=0.5,
|
| 354 |
-
y=0.95,
|
| 355 |
-
xanchor='center',
|
| 356 |
-
yanchor='top',
|
| 357 |
-
font=dict(
|
| 358 |
-
family=font_family,
|
| 359 |
-
size=18,
|
| 360 |
-
color="#374151",
|
| 361 |
-
weight="normal"
|
| 362 |
-
)
|
| 363 |
-
),
|
| 364 |
-
**common_layout
|
| 365 |
-
)
|
| 366 |
-
figs.append(fig)
|
| 367 |
-
for fig in figs:
|
| 368 |
-
st.plotly_chart(fig)
|
| 369 |
-
|
| 370 |
-
# Añadir anotación para el título
|
| 371 |
-
if chart_type != "Donut":
|
| 372 |
-
fig.update_layout(
|
| 373 |
-
title=dict(
|
| 374 |
-
text=f"{chart_title}",
|
| 375 |
-
x=0.5,
|
| 376 |
-
y=0.95,
|
| 377 |
-
xanchor='center',
|
| 378 |
-
yanchor='top',
|
| 379 |
-
font=dict(
|
| 380 |
-
family=font_family,
|
| 381 |
-
size=18,
|
| 382 |
-
color="#374151",
|
| 383 |
-
weight="normal"
|
| 384 |
-
)
|
| 385 |
-
)
|
| 386 |
-
)
|
| 387 |
-
|
| 388 |
-
# Aplicar configuración común
|
| 389 |
-
fig.update_layout(**common_layout)
|
| 390 |
-
|
| 391 |
-
# Aplicar múltiples colores si se seleccionó la opción
|
| 392 |
-
if use_multiple_colors and chart_type != "Donut":
|
| 393 |
-
for i, trace in enumerate(fig.data):
|
| 394 |
-
trace.update(marker_color=colors[i % len(colors)], marker_line_color=border_colors[i % len(border_colors)], marker_line_width=border_width)
|
| 395 |
-
|
| 396 |
-
# Mostrar el gráfico
|
| 397 |
-
st.plotly_chart(fig)
|
| 398 |
-
|
| 399 |
-
# Forzar el autoescale
|
| 400 |
-
fig.update_layout(xaxis_autorange=True, yaxis_autorange=True)
|
| 401 |
-
|
| 402 |
-
# Información adicional
|
| 403 |
-
st.write("""
|
| 404 |
-
""")
|
|
|
|
| 36 |
x = x_values.split(",")
|
| 37 |
|
| 38 |
# Selector de número de variables Y
|
| 39 |
+
num_y_vars = st.sidebar.number_input("Número de variables Y", min_value=1, max_value=100, value=1, step=1, key="num_y_vars")
|
| 40 |
y_values_list = []
|
| 41 |
y_names_list = []
|
| 42 |
for i in range(num_y_vars):
|
| 43 |
if f"y_values_{i}" not in st.session_state:
|
| 44 |
st.session_state[f"y_values_{i}"] = ','.join([str(np.random.randint(1, 25)) for _ in x])
|
| 45 |
+
y_values = st.sidebar.text_area(f"Valores para Y-{i+1} (separados por comas)", st.session_state[f"y_values_{i}"], key=f"y_values_{i}")
|
| 46 |
st.session_state[f"y_values_{i}"] = y_values # Guardar los valores en session_state
|
| 47 |
+
y_name = st.sidebar.text_input(f"Nombre de la Variable Y-{i+1}", f"Variable Y-{i+1}", key=f"y_name_{i}")
|
| 48 |
y_values_list.append(y_values)
|
| 49 |
y_names_list.append(y_name)
|
| 50 |
|
|
|
|
| 62 |
border_width = st.slider("Grosor del Borde", min_value=0.0, max_value=3.0, value=1.5, step=0.1)
|
| 63 |
border_opacity = st.slider("Opacidad del Borde (%)", min_value=0, max_value=100, value=60, step=1) / 100
|
| 64 |
if chart_type == "Barras" and num_y_vars > 1:
|
| 65 |
+
stacked_bars = st.checkbox("Superpuestas", key="stacked_bars")
|
| 66 |
else:
|
| 67 |
stacked_bars = False
|
| 68 |
if chart_type == "Barras":
|
| 69 |
+
horizontal_bars = st.checkbox("Invertidas", key="horizontal_bars")
|
| 70 |
if chart_type == "Donut":
|
| 71 |
hole_size = st.slider("Tamaño del agujero (%)", min_value=0, max_value=100, value=30, step=1) / 100
|
| 72 |
|
| 73 |
# Opción para múltiples colores (siempre activada para Donut)
|
| 74 |
+
use_multiple_colors = st.sidebar.checkbox("Usar múltiples colores", value=True if chart_type == "Donut" or num_y_vars > 1 else False, key="use_multiple_colors")
|
| 75 |
|
| 76 |
# Seleccionar color(es) para el gráfico
|
| 77 |
selected_color = st.sidebar.color_picker("Color", "#24CBA0", key="single_color")
|
|
|
|
| 218 |
# Información adicional
|
| 219 |
st.write("""
|
| 220 |
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|