Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import plotly.express as px | |
| import pandas as pd | |
| from datetime import datetime, timedelta | |
| # Configuración de la página | |
| st.set_page_config(page_title="Generador de Franjas de Tiempo", layout="wide") | |
| # Función para convertir HEX a RGBA con transparencia | |
| def hex_to_rgba(hex_color, alpha=1.0): | |
| hex_color = hex_color.lstrip('#') | |
| return f'rgba({int(hex_color[0:2], 16)},{int(hex_color[2:4], 16)},{int(hex_color[4:6], 16)},{alpha})' | |
| # Colores predefinidos | |
| predefined_colors = [ | |
| "#FF5C5C", "#5CCFFF", "#FFA500", "#90EE90", "#9370DB", "#FFD700" | |
| ] | |
| # Lista de fuentes más utilizadas | |
| font_options = [ | |
| "Times New Roman", "Arial", "Helvetica", "Calibri", "Verdana", | |
| "Tahoma", "Georgia", "Garamond", "Courier New", "Brush Script MT" | |
| ] | |
| # Sidebar para la configuración del gráfico | |
| st.sidebar.header("Configuración del Gráfico") | |
| # Título del gráfico | |
| chart_title = st.sidebar.text_input("Título del Gráfico", "Gráfico de Franjas de Tiempo") | |
| # Seleccionar formato de tiempo | |
| time_format = st.sidebar.selectbox("Formato de Tiempo", ["Año", "Mes y Año"]) | |
| # Ingresar valores para franjas de tiempo | |
| num_y_vars = st.sidebar.number_input("Número de Variables Y", min_value=1, max_value=30, value=3, step=1) | |
| y_values = {} | |
| for i in range(num_y_vars): | |
| year = 2020 + i % 10 # Esto asegura que el año sea siempre válido | |
| y_start = st.sidebar.text_input(f"Fecha de Inicio para Y-{i+1} (YYYY-MM-DD)", key=f"y_start_{i}", value=f"{year}-01-01") | |
| y_end = st.sidebar.text_input(f"Fecha de Fin para Y-{i+1} (YYYY-MM-DD)", key=f"y_end_{i}", value=f"{year + 1}-12-31") | |
| y_name = st.sidebar.text_input(f"Nombre de la Variable Y-{i+1}", key=f"y_name_{i}", value=f"Y-{i+1}") | |
| y_values[y_name] = (y_start, y_end) | |
| # Personalizar las etiquetas de los ejes | |
| x_axis_label = st.sidebar.text_input("Etiqueta para el Eje X", "Tiempo") | |
| y_axis_label = st.sidebar.text_input("Etiqueta para el Eje Y", "Variables") | |
| # Opciones adicionales | |
| with st.sidebar.expander("Opciones Adicionales"): | |
| superposed = st.checkbox("Superpuestas", value=False) | |
| bar_width = st.slider("Ancho de la Barra de Variable", min_value=0.1, max_value=1.0, value=0.5, step=0.1) | |
| show_grid = st.checkbox("Mostrar Líneas de Rejilla", value=True) | |
| opacity = st.slider("Opacidad (%)", min_value=0, max_value=100, value=100, step=1) / 100 | |
| border_width = st.slider("Grosor del Borde", min_value=0.0, max_value=3.0, value=1.0, step=0.1) | |
| border_opacity = st.slider("Opacidad del Borde (%)", min_value=0, max_value=100, value=100, step=1) / 100 | |
| # Opción para múltiples colores | |
| use_multiple_colors = st.sidebar.checkbox("Usar múltiples colores", value=True, key="use_multiple_colors") | |
| # Seleccionar color(es) para el gráfico | |
| selected_color = st.sidebar.color_picker("Color", "#24CBA0", key="single_color") | |
| # Definir colores | |
| if use_multiple_colors: | |
| colors = [st.sidebar.color_picker(f"Color {i+1}", predefined_colors[i % len(predefined_colors)], key=f"color_{i}") | |
| for i in range(num_y_vars)] | |
| else: | |
| color = selected_color | |
| colors = [color] * num_y_vars # Definir colors para casos donde no se usa múltiple colores | |
| # Crear el DataFrame con franjas de tiempo | |
| data_list = [] | |
| for idx, (y_name, (start_date, end_date)) in enumerate(y_values.items()): | |
| if start_date and end_date and y_name: | |
| color_with_opacity = hex_to_rgba(colors[idx], opacity) | |
| border_color_with_opacity = hex_to_rgba(colors[idx], border_opacity) | |
| data_list.append({ | |
| 'Variable': y_name, | |
| 'Start': datetime.strptime(start_date, '%Y-%m-%d'), | |
| 'End': datetime.strptime(end_date, '%Y-%m-%d'), | |
| 'Category': '' if superposed else y_name, # Cambiar categoría dependiendo de la opción seleccionada | |
| 'Color': color_with_opacity, # Asignar color a cada variable con opacidad | |
| 'Border Width': border_width, | |
| 'Border Color': border_color_with_opacity, # Asignar color del borde con opacidad | |
| 'Custom Hover': f'{y_name} ({start_date} - {end_date})' # Texto personalizado para el hover | |
| }) | |
| data = pd.DataFrame(data_list) | |
| # Ajustar fechas para simular apilamiento si está activado | |
| if superposed: | |
| offset = timedelta(days=1) # Ajusta el offset según el tamaño de la columna seleccionado | |
| for i in range(1, len(data)): | |
| data.loc[i, 'Start'] = data.loc[i-1, 'End'] | |
| data.loc[i, 'End'] = data.loc[i, 'Start'] + (data.loc[i, 'End'] - data.loc[i, 'Start']) | |
| data['Category'] = ' ' # Usar una cadena vacía para ocultar el texto "Superpuestas" | |
| # Crear gráfico de franjas de tiempo | |
| fig = px.timeline(data, x_start="Start", x_end="End", y="Category", color="Variable", title=chart_title, | |
| hover_data={'Variable': False, 'Start': False, 'End': False, 'Category': False, 'Custom Hover': True}) | |
| # Actualizar los colores y estilos de las franjas | |
| for idx, row in data.iterrows(): | |
| fig.data[idx].update(marker_color=row['Color']) | |
| fig.data[idx].update(marker_line=dict(width=row['Border Width'], color=row['Border Color'])) | |
| fig.data[idx].update(hovertemplate=row['Custom Hover']) # Usar el texto personalizado para el hover | |
| # Ajustar el ancho de las barras si están superpuestas | |
| if superposed: | |
| fig.update_traces(marker=dict(line_width=bar_width * 5)) # Ajusta el ancho de la barra en modo superpuesto | |
| # Personalizar el formato de tiempo en el eje X | |
| if time_format == "Año": | |
| tickformat = "%Y" | |
| dtick = "M12" # Intervalo de 1 año | |
| else: # "Mes y Año" | |
| tickformat = "%b %Y" | |
| dtick = "M1" # Intervalo de 1 mes | |
| # Configuración de líneas de rejilla | |
| grid_style = dict(showgrid=show_grid) | |
| fig.update_layout( | |
| xaxis_title=x_axis_label, | |
| yaxis_title=y_axis_label, | |
| xaxis=dict( | |
| tickformat=tickformat, | |
| dtick=dtick, | |
| titlefont=dict(size=14), | |
| tickfont=dict(size=12), | |
| **grid_style | |
| ), | |
| yaxis=dict( | |
| titlefont=dict(size=14), | |
| tickfont=dict(size=12), | |
| **grid_style | |
| ), | |
| width=800, | |
| height=600, | |
| margin=dict(l=60, r=40, t=100, b=40), | |
| bargap=1-bar_width, # Controlar el ancho de la barra con el bargap | |
| font=dict(family="Times New Roman", size=18, color="#374151"), # Configuración de la fuente y color | |
| title=dict( | |
| text=chart_title, | |
| x=0.5, | |
| y=0.95, | |
| xanchor='center', | |
| yanchor='top', | |
| font=dict( | |
| family="Times New Roman", | |
| size=18, | |
| color="#374151", | |
| weight="normal" | |
| ) | |
| ), | |
| legend_title_text='' # Eliminar el texto del título de la leyenda | |
| ) | |
| # Mostrar el gráfico | |
| st.plotly_chart(fig) | |
| # Información adicional | |
| st.write("") | |