Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,22 +1,16 @@
|
|
| 1 |
import streamlit as st
|
| 2 |
import plotly.express as px
|
| 3 |
import pandas as pd
|
| 4 |
-
import numpy as np
|
| 5 |
from datetime import datetime
|
| 6 |
|
| 7 |
# Configuración de la página
|
| 8 |
-
st.set_page_config(page_title="Generador de
|
| 9 |
|
| 10 |
# Función para convertir HEX a RGBA con transparencia
|
| 11 |
def hex_to_rgba(hex_color, alpha=1.0):
|
| 12 |
hex_color = hex_color.lstrip('#')
|
| 13 |
return f'rgba({int(hex_color[0:2], 16)},{int(hex_color[2:4], 16)},{int(hex_color[4:6], 16)},{alpha})'
|
| 14 |
|
| 15 |
-
# Colores predefinidos
|
| 16 |
-
predefined_colors = [
|
| 17 |
-
"#FF5C5C", "#5CCFFF", "#FFA500", "#90EE90", "#9370DB", "#FFD700"
|
| 18 |
-
]
|
| 19 |
-
|
| 20 |
# Lista de fuentes más utilizadas
|
| 21 |
font_options = [
|
| 22 |
"Times New Roman", "Arial", "Helvetica", "Calibri", "Verdana",
|
|
@@ -27,219 +21,70 @@ font_options = [
|
|
| 27 |
st.sidebar.header("Configuración del Gráfico")
|
| 28 |
|
| 29 |
# Título del gráfico
|
| 30 |
-
chart_title = st.sidebar.text_input("Título del Gráfico", "
|
| 31 |
-
|
| 32 |
-
#
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
#
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
if chart_type == "Línea temporal":
|
| 40 |
-
time_unit = st.sidebar.selectbox("Unidad de tiempo", ["Días", "Meses", "Años"])
|
| 41 |
-
|
| 42 |
-
if time_unit == "Días":
|
| 43 |
-
start_date = st.sidebar.date_input("Fecha de inicio", datetime(2023, 1, 1))
|
| 44 |
-
end_date = st.sidebar.date_input("Fecha de fin", datetime(2023, 12, 31))
|
| 45 |
-
x = generate_date_range(start_date, end_date, 'D')
|
| 46 |
-
elif time_unit == "Meses":
|
| 47 |
-
start_date = st.sidebar.date_input("Fecha de inicio", datetime(2023, 1, 1))
|
| 48 |
-
end_date = st.sidebar.date_input("Fecha de fin", datetime(2023, 12, 31))
|
| 49 |
-
x = generate_date_range(start_date, end_date, 'M')
|
| 50 |
-
elif time_unit == "Años":
|
| 51 |
-
start_year = st.sidebar.number_input("Año de inicio", min_value=2000, max_value=2100, value=2020)
|
| 52 |
-
end_year = st.sidebar.number_input("Año de fin", min_value=2000, max_value=2100, value=2023)
|
| 53 |
-
x = [str(year) for year in range(start_year, end_year + 1)]
|
| 54 |
-
else:
|
| 55 |
-
# Ingresar valores para los ejes
|
| 56 |
-
x_values = st.sidebar.text_area("Valores para X (separados por comas)", "2013,2014,2015,2016,2017,2018")
|
| 57 |
-
x = x_values.split(",")
|
| 58 |
-
|
| 59 |
-
# Selector de número de variables Y
|
| 60 |
-
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")
|
| 61 |
-
y_values_list = []
|
| 62 |
-
y_names_list = []
|
| 63 |
for i in range(num_y_vars):
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
# Seleccionar color(es) para el gráfico
|
| 97 |
-
selected_color = st.sidebar.color_picker("Color", "#24CBA0", key="single_color")
|
| 98 |
-
|
| 99 |
-
# Definir colores
|
| 100 |
-
if use_multiple_colors:
|
| 101 |
-
num_colors = len(x)
|
| 102 |
-
colors = [hex_to_rgba(st.sidebar.color_picker(f"Color {i+1}", predefined_colors[i % len(predefined_colors)], key=f"color_{i}"), alpha=opacity)
|
| 103 |
-
for i in range(num_colors)]
|
| 104 |
-
border_colors = [hex_to_rgba(st.sidebar.color_picker(f"Color de Borde {i+1}", predefined_colors[i % len(predefined_colors)], key=f"border_color_{i}"), alpha=border_opacity)
|
| 105 |
-
for i in range(num_colors)]
|
| 106 |
else:
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
for idx, y_set in enumerate(y_values_lists):
|
| 124 |
-
data[y_names_list[idx]] = y_set
|
| 125 |
-
|
| 126 |
-
# Configuración común para todos los gráficos
|
| 127 |
-
common_layout = dict(
|
| 128 |
-
xaxis_title=x_label,
|
| 129 |
-
yaxis_title=y_label,
|
| 130 |
-
plot_bgcolor="white",
|
| 131 |
-
hovermode="x unified",
|
| 132 |
-
width=graph_width,
|
| 133 |
-
height=graph_height,
|
| 134 |
margin=dict(l=60, r=40, t=100, b=40),
|
| 135 |
-
|
| 136 |
-
yaxis=dict(showgrid=True, zeroline=True, gridcolor='rgba(211,211,211,0.5)', zerolinecolor='rgba(128,128,128,0.5)', autorange=True),
|
| 137 |
-
font=dict(family=font_family, size=18, color="black"),
|
| 138 |
-
showlegend=show_legend,
|
| 139 |
-
legend=dict(orientation="v", yanchor="top", y=1, xanchor="left", x=1.02)
|
| 140 |
)
|
| 141 |
|
| 142 |
-
#
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
# Generar el gráfico basado en el tipo seleccionado
|
| 146 |
-
if chart_type == "Línea":
|
| 147 |
-
fig = px.line(data, x="X", y=y_names_list, line_shape="spline")
|
| 148 |
-
fig.update_traces(hovertemplate=hovertemplate)
|
| 149 |
-
if use_multiple_colors:
|
| 150 |
-
for i, name in enumerate(y_names_list):
|
| 151 |
-
fig.update_traces(selector=dict(name=name), line_color=colors[i % len(colors)])
|
| 152 |
-
else:
|
| 153 |
-
fig.update_traces(line_color=color)
|
| 154 |
-
elif chart_type == "Área":
|
| 155 |
-
fig = px.area(data, x="X", y=y_names_list, line_shape="spline")
|
| 156 |
-
fig.update_traces(hovertemplate=hovertemplate)
|
| 157 |
-
if use_multiple_colors:
|
| 158 |
-
for i, name in enumerate(y_names_list):
|
| 159 |
-
fig.update_traces(selector=dict(name=name), line_color=colors[i % len(colors)], fillcolor=colors[i % len(colors)])
|
| 160 |
-
else:
|
| 161 |
-
fig.update_traces(line_color=color, fillcolor=color)
|
| 162 |
-
elif chart_type == "Dispersión":
|
| 163 |
-
fig = px.scatter(data, x="X", y=y_names_list)
|
| 164 |
-
fig.update_traces(hovertemplate=hovertemplate)
|
| 165 |
-
if use_multiple_colors:
|
| 166 |
-
for i, name in enumerate(y_names_list):
|
| 167 |
-
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)
|
| 168 |
-
else:
|
| 169 |
-
fig.update_traces(marker_color=color, marker_line_color=border_color, marker_line_width=border_width)
|
| 170 |
-
elif chart_type == "Barras":
|
| 171 |
-
if horizontal_bars:
|
| 172 |
-
fig = px.bar(data, y="X", x=y_names_list, orientation='h', barmode='stack' if stacked_bars else 'group')
|
| 173 |
-
else:
|
| 174 |
-
fig = px.bar(data, x="X", y=y_names_list, barmode='stack' if stacked_bars else 'group')
|
| 175 |
-
fig.update_traces(hovertemplate=hovertemplate)
|
| 176 |
-
if use_multiple_colors:
|
| 177 |
-
if len(y_names_list) == 1: # Solo una variable Y
|
| 178 |
-
fig.update_traces(marker_color=colors[:len(x)], marker_line_color=border_colors[:len(x)], marker_line_width=border_width)
|
| 179 |
-
else:
|
| 180 |
-
for i, trace in enumerate(fig.data):
|
| 181 |
-
trace.marker.color = colors[i % len(colors)]
|
| 182 |
-
trace.marker.line.color = border_colors[i % len(border_colors)]
|
| 183 |
-
trace.marker.line.width = border_width
|
| 184 |
-
else:
|
| 185 |
-
fig.update_traces(marker_color=color, marker_line_color=border_color, marker_line_width=border_width)
|
| 186 |
-
fig.update_layout(bargap=0.2)
|
| 187 |
-
elif chart_type == "Donut":
|
| 188 |
-
figs = []
|
| 189 |
-
for i, y_name in enumerate(y_names_list):
|
| 190 |
-
fig = px.pie(data, values=y_name, names="X", hole=hole_size, color_discrete_sequence=colors[:len(x)])
|
| 191 |
-
fig.update_traces(hovertemplate='<b>%{label}</b>: %{value} (%{percent})', textinfo='percent+label')
|
| 192 |
-
fig.update_layout(
|
| 193 |
-
title=dict(
|
| 194 |
-
text=f"{chart_title}<br><sub>{y_name}</sub>" if len(y_names_list) > 1 else chart_title,
|
| 195 |
-
x=0.5,
|
| 196 |
-
y=0.95,
|
| 197 |
-
xanchor='center',
|
| 198 |
-
yanchor='top',
|
| 199 |
-
font=dict(
|
| 200 |
-
family=font_family,
|
| 201 |
-
size=18,
|
| 202 |
-
color="#374151",
|
| 203 |
-
weight="normal"
|
| 204 |
-
)
|
| 205 |
-
),
|
| 206 |
-
**common_layout
|
| 207 |
-
)
|
| 208 |
-
figs.append(fig)
|
| 209 |
-
for fig in figs:
|
| 210 |
-
st.plotly_chart(fig)
|
| 211 |
-
|
| 212 |
-
# Añadir anotación para el título
|
| 213 |
-
if chart_type != "Donut":
|
| 214 |
-
fig.update_layout(
|
| 215 |
-
title=dict(
|
| 216 |
-
text=f"{chart_title}",
|
| 217 |
-
x=0.5,
|
| 218 |
-
y=0.95,
|
| 219 |
-
xanchor='center',
|
| 220 |
-
yanchor='top',
|
| 221 |
-
font=dict(
|
| 222 |
-
family=font_family,
|
| 223 |
-
size=18,
|
| 224 |
-
color="#374151",
|
| 225 |
-
weight="normal"
|
| 226 |
-
)
|
| 227 |
-
)
|
| 228 |
-
)
|
| 229 |
-
|
| 230 |
-
# Aplicar configuración común
|
| 231 |
-
fig.update_layout(**common_layout)
|
| 232 |
-
|
| 233 |
-
# Aplicar múltiples colores si se seleccionó la opción
|
| 234 |
-
if use_multiple_colors and chart_type != "Donut":
|
| 235 |
-
for i, trace in enumerate(fig.data):
|
| 236 |
-
trace.update(marker_color=colors[i % len(colors)], marker_line_color=border_colors[i % len(border_colors)], marker_line_width=border_width)
|
| 237 |
-
|
| 238 |
-
# Mostrar el gráfico
|
| 239 |
-
st.plotly_chart(fig)
|
| 240 |
-
|
| 241 |
-
# Forzar el autoescale
|
| 242 |
-
fig.update_layout(xaxis_autorange=True, yaxis_autorange=True)
|
| 243 |
|
| 244 |
# Información adicional
|
| 245 |
st.write("Aquí puede añadir información adicional sobre los gráficos generados.")
|
|
|
|
| 1 |
import streamlit as st
|
| 2 |
import plotly.express as px
|
| 3 |
import pandas as pd
|
|
|
|
| 4 |
from datetime import datetime
|
| 5 |
|
| 6 |
# Configuración de la página
|
| 7 |
+
st.set_page_config(page_title="Generador de Franjas de Tiempo Apiladas", layout="wide")
|
| 8 |
|
| 9 |
# Función para convertir HEX a RGBA con transparencia
|
| 10 |
def hex_to_rgba(hex_color, alpha=1.0):
|
| 11 |
hex_color = hex_color.lstrip('#')
|
| 12 |
return f'rgba({int(hex_color[0:2], 16)},{int(hex_color[2:4], 16)},{int(hex_color[4:6], 16)},{alpha})'
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
# Lista de fuentes más utilizadas
|
| 15 |
font_options = [
|
| 16 |
"Times New Roman", "Arial", "Helvetica", "Calibri", "Verdana",
|
|
|
|
| 21 |
st.sidebar.header("Configuración del Gráfico")
|
| 22 |
|
| 23 |
# Título del gráfico
|
| 24 |
+
chart_title = st.sidebar.text_input("Título del Gráfico", "Gráfico de Franjas de Tiempo Apiladas")
|
| 25 |
+
|
| 26 |
+
# Seleccionar formato de tiempo
|
| 27 |
+
time_format = st.sidebar.selectbox("Formato de Tiempo", ["Día", "Mes", "Año"])
|
| 28 |
+
|
| 29 |
+
# Ingresar valores para franjas de tiempo
|
| 30 |
+
num_y_vars = st.sidebar.number_input("Número de Variables Y", min_value=1, max_value=10, value=1, step=1)
|
| 31 |
+
|
| 32 |
+
y_values = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
for i in range(num_y_vars):
|
| 34 |
+
y_start = st.sidebar.text_input(f"Fecha de Inicio para Y-{i+1} (YYYY-MM-DD)", key=f"y_start_{i}")
|
| 35 |
+
y_end = st.sidebar.text_input(f"Fecha de Fin para Y-{i+1} (YYYY-MM-DD)", key=f"y_end_{i}")
|
| 36 |
+
y_name = st.sidebar.text_input(f"Nombre de la Variable Y-{i+1}", key=f"y_name_{i}")
|
| 37 |
+
if y_start and y_end and y_name:
|
| 38 |
+
y_values[y_name] = (y_start, y_end)
|
| 39 |
+
|
| 40 |
+
# Crear el DataFrame con franjas de tiempo
|
| 41 |
+
data_list = []
|
| 42 |
+
for y_name, (start_date, end_date) in y_values.items():
|
| 43 |
+
data_list.append({
|
| 44 |
+
'Variable': y_name,
|
| 45 |
+
'Start': datetime.strptime(start_date, '%Y-%m-%d'),
|
| 46 |
+
'End': datetime.strptime(end_date, '%Y-%m-%d')
|
| 47 |
+
})
|
| 48 |
+
|
| 49 |
+
data = pd.DataFrame(data_list)
|
| 50 |
+
|
| 51 |
+
# Convertir el DataFrame para el gráfico
|
| 52 |
+
data['Duration'] = data['End'] - data['Start']
|
| 53 |
+
data['Start'] = pd.to_datetime(data['Start'])
|
| 54 |
+
data['End'] = pd.to_datetime(data['End'])
|
| 55 |
+
|
| 56 |
+
# Crear gráfico
|
| 57 |
+
fig = px.timeline(data, x_start="Start", x_end="End", y="Variable", color="Variable", title=chart_title)
|
| 58 |
+
fig.update_yaxes(categoryorder="total ascending")
|
| 59 |
+
|
| 60 |
+
# Personalizar el formato de tiempo en el eje X
|
| 61 |
+
if time_format == "Día":
|
| 62 |
+
tickformat = "%d-%m-%Y"
|
| 63 |
+
elif time_format == "Mes":
|
| 64 |
+
tickformat = "%Y-%m"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
else:
|
| 66 |
+
tickformat = "%Y"
|
| 67 |
+
|
| 68 |
+
fig.update_layout(
|
| 69 |
+
xaxis_title="Tiempo",
|
| 70 |
+
yaxis_title="Variables",
|
| 71 |
+
xaxis=dict(
|
| 72 |
+
tickformat=tickformat,
|
| 73 |
+
titlefont=dict(size=14),
|
| 74 |
+
tickfont=dict(size=12),
|
| 75 |
+
),
|
| 76 |
+
yaxis=dict(
|
| 77 |
+
titlefont=dict(size=14),
|
| 78 |
+
tickfont=dict(size=12),
|
| 79 |
+
),
|
| 80 |
+
width=800,
|
| 81 |
+
height=600,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
margin=dict(l=60, r=40, t=100, b=40),
|
| 83 |
+
font=dict(family="Times New Roman", size=18, color="black")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
)
|
| 85 |
|
| 86 |
+
# Mostrar el gráfico
|
| 87 |
+
st.plotly_chart(fig)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
|
| 89 |
# Información adicional
|
| 90 |
st.write("Aquí puede añadir información adicional sobre los gráficos generados.")
|