tx3bas commited on
Commit
ea88ce5
·
verified ·
1 Parent(s): 93e61b0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -215
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 Gráficos Personalizado", layout="wide")
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", "Generador de Gráfico")
31
-
32
- # Tipo de gráfico
33
- chart_type = st.sidebar.selectbox("Tipo de Gráfico", ["Línea", "Área", "Dispersión", "Barras", "Donut", "Línea temporal"])
34
-
35
- # Función para generar rangos de fechas
36
- def generate_date_range(start_date, end_date, freq):
37
- return pd.date_range(start=start_date, end=end_date, freq=freq).strftime('%Y-%m-%d').tolist()
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
- if f"y_values_{i}" not in st.session_state:
65
- st.session_state[f"y_values_{i}"] = ','.join([str(np.random.randint(1, 25)) for _ in x])
66
- 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}")
67
- y_name = st.sidebar.text_input(f"Nombre de la Variable Y-{i+1}", f"Variable Y-{i+1}", key=f"y_name_{i}")
68
- y_values_list.append(y_values)
69
- y_names_list.append(y_name)
70
-
71
- # Etiquetas personalizadas para los ejes
72
- x_label = st.sidebar.text_input("Etiqueta para el eje X", "X")
73
- y_label = st.sidebar.text_input("Etiqueta para el eje Y", "Y")
74
-
75
- # Desplegable de opciones adicionales
76
- with st.sidebar.expander("Opciones Adicionales"):
77
- graph_width = st.slider("Ancho del Gráfico", min_value=400, max_value=1000, value=800, step=50)
78
- graph_height = st.slider("Alto del Gráfico", min_value=300, max_value=800, value=600, step=50)
79
- font_family = st.selectbox("Fuente", font_options, index=font_options.index("Times New Roman"))
80
- show_legend = st.checkbox("Mostrar Leyenda", value=True)
81
- opacity = st.slider("Opacidad (%)", min_value=0, max_value=100, value=30, step=1) / 100
82
- border_width = st.slider("Grosor del Borde", min_value=0.0, max_value=3.0, value=1.5, step=0.1)
83
- border_opacity = st.slider("Opacidad del Borde (%)", min_value=0, max_value=100, value=60, step=1) / 100
84
- if chart_type == "Barras" and num_y_vars > 1:
85
- stacked_bars = st.checkbox("Superpuestas", key="stacked_bars")
86
- else:
87
- stacked_bars = False
88
- if chart_type == "Barras":
89
- horizontal_bars = st.checkbox("Invertidas", key="horizontal_bars")
90
- if chart_type == "Donut":
91
- hole_size = st.slider("Tamaño del agujero (%)", min_value=0, max_value=100, value=30, step=1) / 100
92
-
93
- # Opción para múltiples colores (siempre activada para Donut)
94
- 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")
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
- color = hex_to_rgba(selected_color, alpha=opacity)
108
- border_color = hex_to_rgba(selected_color, alpha=border_opacity)
109
- colors = [color] * len(x) # Definir colors para casos donde no se usa múltiple colores
110
-
111
- # Procesar valores
112
- y_values_lists = [[float(i) for i in y_values.split(",") if i.strip()] for y_values in y_values_list]
113
-
114
- # Asegurar que todas las listas de Y tengan el mismo tamaño que X
115
- for y_values in y_values_lists:
116
- while len(y_values) < len(x):
117
- y_values.append(0)
118
- while len(y_values) > len(x):
119
- y_values.pop()
120
-
121
- # Crear un DataFrame
122
- data = pd.DataFrame({"X": x})
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
- xaxis=dict(showgrid=True, zeroline=True, gridcolor='rgba(211,211,211,0.5)', zerolinecolor='rgba(128,128,128,0.5)', autorange=True),
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
- # Personalizar el hovertemplate
143
- hovertemplate = '<b>%{y}</b>'
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.")