diff --git a/.gitignore b/.gitignore
index 459c006..8b38332 100644
--- a/.gitignore
+++ b/.gitignore
@@ -145,3 +145,4 @@ dmypy.json
.github/desktop.ini
*.ini
+configs/configuraciones_generales.yaml
diff --git a/run_all_urbantrips.py b/run_all_urbantrips.py
new file mode 100644
index 0000000..1b31bf8
--- /dev/null
+++ b/run_all_urbantrips.py
@@ -0,0 +1,21 @@
+from urbantrips import initialize_environment
+from urbantrips import process_transactions
+from urbantrips import run_postprocessing
+from urbantrips import create_viz
+from urbantrips import run_dashboard
+
+import warnings
+
+# Filter and suppress specific warnings
+warnings.filterwarnings("ignore")
+
+def main():
+
+ initialize_environment.main()
+ process_transactions.main()
+ run_postprocessing.main()
+ create_viz.main()
+ run_dashboard.main()
+
+if __name__ == "__main__":
+ main()
diff --git a/urbantrips/dashboard/dash_utils.py b/urbantrips/dashboard/dash_utils.py
index 7c9b7c5..69e1b14 100644
--- a/urbantrips/dashboard/dash_utils.py
+++ b/urbantrips/dashboard/dash_utils.py
@@ -12,7 +12,8 @@
from shapely import wkt
from matplotlib import colors as mcolors
from folium import Figure
-from shapely.geometry import LineString, Point, Polygon
+from shapely.geometry import LineString, Point, Polygon, shape, mapping
+import h3
def leer_configs_generales():
@@ -127,12 +128,16 @@ def calculate_weighted_means(df,
def normalize_vars(tabla):
if 'dia' in tabla.columns:
- tabla.loc[tabla.dia == 'weekday', 'dia'] = 'Día hábil'
+ tabla.loc[tabla.dia == 'weekday', 'dia'] = 'Hábil'
tabla.loc[tabla.dia == 'weekend', 'dia'] = 'Fin de semana'
if 'day_type' in tabla.columns:
- tabla.loc[tabla.day_type == 'weekday', 'day_type'] = 'Día hábil'
+ tabla.loc[tabla.day_type == 'weekday', 'day_type'] = 'Hábil'
tabla.loc[tabla.day_type == 'weekend', 'day_type'] = 'Fin de semana'
+ if 'tipo_dia' in tabla.columns:
+ tabla.loc[tabla.tipo_dia == 'Dia habil', 'tipo_dia'] = 'Hábil'
+ # tabla.loc[tabla.tipo_dia == 'weekend', 'tipo_dia'] = 'Fin de semana'
+
if 'nombre_linea' in tabla.columns:
tabla['nombre_linea'] = tabla['nombre_linea'].str.replace(' -', '')
if 'Modo' in tabla.columns:
@@ -624,4 +629,10 @@ def traigo_zonas_values(tipo = 'etapas'):
(zonas_values.inicio_norm.notna())&
(zonas_values.inicio_norm!=' (cuenca)')].sort_values(['zona', 'inicio_norm']).rename(columns={'inicio_norm':'Nombre'})
- return zonas_values
\ No newline at end of file
+ return zonas_values
+
+# Convert geometry to H3 indices
+def get_h3_indices_in_geometry(geometry, resolution):
+ geojson = mapping(geometry)
+ h3_indices = list(h3.polyfill(geojson, resolution, geo_json_conformant=True))
+ return h3_indices
\ No newline at end of file
diff --git a/urbantrips/dashboard/dashboard.py b/urbantrips/dashboard/dashboard.py
index 3a3a1ea..bf9baf3 100644
--- a/urbantrips/dashboard/dashboard.py
+++ b/urbantrips/dashboard/dashboard.py
@@ -17,7 +17,7 @@
from folium import Figure
from shapely.geometry import LineString
-from dash_utils import levanto_tabla_sql, get_logo
+from dash_utils import levanto_tabla_sql, get_logo, traigo_indicadores
st.set_page_config(layout="wide")
@@ -79,26 +79,24 @@
# Inject CSS with Markdown
col3.markdown(hide_table_row_index, unsafe_allow_html=True)
-
-
col3.table(df)
df = indicadores.loc[indicadores.orden == 3, ['Indicador', 'Valor']].copy()
titulo = indicadores.loc[indicadores.orden == 3].Titulo.unique()[0]
- col2.text(titulo)
- # CSS to inject contained in a string
- hide_table_row_index = """
-
- """
+ # col2.text(titulo)
+ # # CSS to inject contained in a string
+ # hide_table_row_index = """
+ #
+ # """
- # Inject CSS with Markdown
- col2.markdown(hide_table_row_index, unsafe_allow_html=True)
+ # # Inject CSS with Markdown
+ # col2.markdown(hide_table_row_index, unsafe_allow_html=True)
- col2.table(df)
+ # col2.table(df)
else:
# Usar HTML para personalizar el estilo del texto
@@ -127,3 +125,21 @@
"""
col2.markdown(texto_html, unsafe_allow_html=True)
+with st.expander('Indicadores', True):
+ col1, col2, col3 = st.columns([2, 2, 2])
+
+ general, modal, distancias = traigo_indicadores('all')
+
+ st.session_state.general_ = general.loc[general.mes==desc_dia_i, ['Tipo', 'Indicador', 'Valor']].set_index('Tipo')
+ st.session_state.modal_ = modal.loc[modal.mes==desc_dia_i, ['Tipo', 'Indicador', 'Valor']].set_index('Tipo')
+ st.session_state.distancias_ = distancias.loc[distancias.mes==desc_dia_i, ['Tipo', 'Indicador', 'Valor']].set_index('Tipo')
+
+
+ st.session_state.general_ = st.session_state.general_[~st.session_state.general_.Indicador.isin(['Cantidad de Usuarios', 'Cantidad de Viajes'])]
+ if len(st.session_state.general_) > 0:
+ col1.write(f'Periodo: {desc_dia_i}')
+ col1.table(st.session_state.general_)
+ # col2.write('')
+ # col2.table(st.session_state.modal_)
+ col3.write('')
+ col3.table(st.session_state.distancias_)
\ No newline at end of file
diff --git a/urbantrips/dashboard/pages/1_Datos Generales.py b/urbantrips/dashboard/pages/1_Datos Generales.py
index 202804d..6353cfc 100644
--- a/urbantrips/dashboard/pages/1_Datos Generales.py
+++ b/urbantrips/dashboard/pages/1_Datos Generales.py
@@ -1,3 +1,4 @@
+import numpy as np
import streamlit as st
import pandas as pd
import folium
@@ -9,7 +10,206 @@
from dash_utils import (levanto_tabla_sql, get_logo,
create_linestring_od, extract_hex_colors_from_cmap)
-
+import matplotlib.pyplot as plt
+from itertools import combinations
+import squarify
+from matplotlib_venn import venn3
+
+# Function to create activity combinations as tuples
+def get_activity_tuple(cols_dummies, selected_cols_dummies):
+ return tuple(1 if activity in selected_cols_dummies else 0 for activity in cols_dummies)
+
+# Function to calculate subset sizes
+def get_activity_combination_number(df, cols_dummies, activity_combination):
+ activity_str_filter = [
+ f"{a} > 0" if a in activity_combination else f"{a} == 0" for a in cols_dummies
+ ]
+ activity_str_filter = " & ".join(activity_str_filter)
+ return len(df.query(activity_str_filter))
+
+# Generate example data
+def generate_example_data(num_rows=100):
+ np.random.seed(42) # For reproducibility
+ data = {
+ 'train': np.random.randint(0, 2, size=num_rows), # Binary: 0 (not used), 1 (used)
+ 'subway': np.random.randint(0, 2, size=num_rows),
+ 'bus': np.random.randint(0, 2, size=num_rows)
+ }
+ return pd.DataFrame(data)
+
+# Generate subset sizes dictionary
+def calculate_subset_sizes(df, cols_dummies):
+ list_of_tuples = [
+ item
+ for sublist in [list(combinations(cols_dummies, i)) for i in range(1, len(cols_dummies) + 1)]
+ for item in sublist
+ ]
+ return {
+ get_activity_tuple(cols_dummies, combo): get_activity_combination_number(df, cols_dummies, combo)
+ for combo in list_of_tuples
+ }
+
+# Extract subset sizes for Venn diagram
+def get_venn_subsets(subset_sizes):
+ return (
+ subset_sizes.get((1, 0, 0), 0), # Only 'train'
+ subset_sizes.get((0, 1, 0), 0), # Only 'subway'
+ subset_sizes.get((1, 1, 0), 0), # 'train' and 'subway'
+ subset_sizes.get((0, 0, 1), 0), # Only 'bus'
+ subset_sizes.get((1, 0, 1), 0), # 'train' and 'bus'
+ subset_sizes.get((0, 1, 1), 0), # 'subway' and 'bus'
+ subset_sizes.get((1, 1, 1), 0) # 'train', 'subway', and 'bus'
+ )
+
+# Plot Venn diagram
+def plot_venn_diagram(etapas_modos):
+
+ cols_dummies = [x for x in etapas_modos.columns.tolist() if x not in ['mes', 'tipo_dia', 'genero', 'factor_expansion_linea']]
+
+ # Calcular porcentajes
+ absolute_values = calculate_weighted_values(etapas_modos, cols_dummies, weight_column='factor_expansion_linea', as_percentage=False)
+ percentage_values = calculate_weighted_values(etapas_modos, cols_dummies, weight_column='factor_expansion_linea', as_percentage=True)
+
+ modal_etapas = pd.DataFrame(list(absolute_values.items()), columns=['Modes', 'Cantidad']).round(0)
+ modal_etapas[cols_dummies] = pd.DataFrame(modal_etapas['Modes'].tolist(), index=modal_etapas.index)
+ modal_etapas['Modo'] = ''
+ for i in cols_dummies:
+ modal_etapas.loc[modal_etapas[i]>=1, 'Modo'] += i+'-'
+ modal_etapas.loc[modal_etapas.Modo.str[-1:]=='-', 'Modo'] = modal_etapas.loc[modal_etapas.Modo.str[-1:]=='-'].Modo.str[:-1]
+ modal_etapas = modal_etapas[['Modo', 'Cantidad']]
+ modal_etapas['Cantidad'] = modal_etapas['Cantidad'].astype(int)
+ modal_etapas['%'] = (modal_etapas['Cantidad'] / modal_etapas['Cantidad'].sum() * 100).round(1)
+ modal_etapas = modal_etapas.sort_values('Cantidad', ascending=False)
+
+ venn_subsets = get_venn_subsets(percentage_values)
+
+ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))
+
+ # Left subplot: Venn3
+ venn3(subsets=venn_subsets, set_labels=[activity.capitalize() for activity in cols_dummies], ax=ax1)
+ ax1.set_title("Partición modal (%)")
+
+ # Identificar multimodal (más de un modo utilizado)
+ etapas_modos['Multimodal'] = (etapas_modos[cols_dummies].gt(0).sum(axis=1) > 1).astype(int)
+
+ # Identificar multietapa (más de una etapa en al menos un modo)
+ etapas_modos['Multietapa'] = (etapas_modos[cols_dummies].gt(1).any(axis=1)).astype(int)
+
+ for i in cols_dummies:
+ etapas_modos.loc[etapas_modos.Multimodal==1, i] = 0
+ etapas_modos.loc[etapas_modos.Multietapa==1, i] = 0
+ # etapas_modos.loc[etapas_modos[i]>=1, i] = 1
+
+ etapas_modos.loc[(etapas_modos.Multietapa>0)&(etapas_modos.Multimodal>0), 'Multietapa'] = 0
+
+ cols_dummies = cols_dummies+['Multimodal', 'Multietapa']
+
+ etapas_modos["Modos"] = etapas_modos[cols_dummies].idxmax(axis=1)
+
+ v = etapas_modos.groupby('Modos', as_index=False).factor_expansion_linea.sum().round()
+ v['p'] = (v.factor_expansion_linea /v.factor_expansion_linea.sum() * 100).round(1)
+ v['m'] = v.Modos +'\n('+v.p.astype(str)+'%)'
+ v.loc[v.p<3, 'm'] = v.loc[v.p<3, 'm'].str.replace('\n', ' ')
+
+ values_data =v.p.values.tolist()
+ values_names = v.m.values.tolist()
+
+ fixed_palette = [
+ '#AED6F1', '#F9E79F', '#ABEBC6', '#F5B7B1', '#D2B4DE',
+ '#FAD7A0', '#85C1E9', '#A3E4D7', '#F7DC6F', '#F0B27A',
+ '#F8C471', '#D7BDE2', '#A2D9CE', '#FDEBD0', '#D5F5E3',
+ '#F9E79F', '#82E0AA', '#BB8FCE', '#EDBB99', '#A9CCE3'
+ ]
+
+ colors = fixed_palette[:len(v)]
+
+ # Right subplot: Squarify treemap
+ squarify.plot(values_data,
+ label=values_names,
+ color=colors,
+ ax=ax2,
+ text_kwargs={'fontsize': 10, 'color': 'black'}) #, 'fontweight': 'bold'
+ ax2.axis("off")
+
+ plt.tight_layout()
+ plt.show()
+
+
+ modal_viajes = etapas_modos.groupby('Modos', as_index=False).factor_expansion_linea.sum().round(0).rename(columns={'factor_expansion_linea':'Cantidad'})
+ modal_viajes['%'] = (modal_viajes['Cantidad'] / modal_viajes['Cantidad'].sum() * 100).round(1)
+ modal_viajes = modal_viajes.sort_values('Cantidad', ascending=False)
+ modal_viajes = modal_viajes.rename(columns={'Modos':'Modo'})
+
+ return fig, modal_etapas, modal_viajes
+
+# Función para calcular los porcentajes o valores absolutos ponderados
+def calculate_weighted_values(df, cols_dummies, weight_column, as_percentage=True):
+ # Calcular el total ponderado
+ total_weight = df[weight_column].sum()
+
+ # Crear el diccionario para cada combinación de actividades
+ subset_sizes = {}
+ for combo in [list(c) for i in range(1, len(cols_dummies) + 1) for c in combinations(cols_dummies, i)]:
+ activity_str_filter = [f"{a} > 0" if a in combo else f"{a} == 0" for a in cols_dummies]
+ query_str = " & ".join(activity_str_filter)
+ subset_weight = df.query(query_str)[weight_column].sum()
+ subset_sizes[tuple(1 if a in combo else 0 for a in cols_dummies)] = subset_weight
+
+ # Convertir a porcentajes si as_percentage es True
+ if as_percentage:
+ subset_sizes = {key: round((value / total_weight) * 100, 1) for key, value in subset_sizes.items()}
+
+ return subset_sizes
+
+def traigo_socio_indicadores(socio_indicadores):
+ totals = None
+ totals_porc = 0
+ avg_distances = 0
+ avg_times = 0
+ avg_velocity = 0
+ modos_genero_abs = 0
+ modos_genero_porc = 0
+ modos_tarifa_abs = 0
+ modos_tarifa_porc = 0
+ avg_viajes = 0
+ avg_etapas = 0
+ avg_tiempo_entre_viajes = 0
+
+ if len(socio_indicadores) > 0:
+
+ df = socio_indicadores[socio_indicadores.tabla=='viajes-genero-tarifa'].copy()
+ totals = pd.crosstab(values=df.factor_expansion_linea, columns=df.Genero, index=df.Tarifa, aggfunc='sum', margins=True, margins_name='Total', normalize=False).fillna(0).round().astype(int).apply(lambda col: col.map(lambda x: f'{x:,.0f}'.replace(',', '.')))
+ totals_porc = (pd.crosstab(values=df.factor_expansion_linea, columns=df.Genero, index=df.Tarifa, aggfunc='sum', margins=True, margins_name='Total', normalize=True) * 100).round(2)
+
+ modos = socio_indicadores[socio_indicadores.tabla=='etapas-genero-modo'].copy()
+ modos_genero_abs = pd.crosstab(values=modos.factor_expansion_linea, index=[modos.Genero], columns=modos.Modo, aggfunc='sum', normalize=False, margins=True, margins_name='Total').fillna(0).astype(int).apply(lambda col: col.map(lambda x: f'{x:,.0f}'.replace(',', '.')))
+ modos_genero_porc = (pd.crosstab(values=modos.factor_expansion_linea, index=modos.Genero, columns=modos.Modo, aggfunc='sum', normalize=True, margins=True, margins_name='Total') * 100).round(2)
+
+ modos = socio_indicadores[socio_indicadores.tabla=='etapas-tarifa-modo'].copy()
+ modos_tarifa_abs = pd.crosstab(values=modos.factor_expansion_linea, index=[modos.Tarifa], columns=modos.Modo, aggfunc='sum', normalize=False, margins=True, margins_name='Total').fillna(0).astype(int).apply(lambda col: col.map(lambda x: f'{x:,.0f}'.replace(',', '.')))
+ modos_tarifa_porc = (pd.crosstab(values=modos.factor_expansion_linea, index=modos.Tarifa, columns=modos.Modo, aggfunc='sum', normalize=True, margins=True, margins_name='Total') * 100).round(2)
+
+ avg_distances = pd.crosstab(values=df.Distancia, columns=df.Genero, index=df.Tarifa, margins=True, margins_name='Total',aggfunc=lambda x: (x * df.loc[x.index, 'factor_expansion_linea']).sum() / df.loc[x.index, 'factor_expansion_linea'].sum(), ).fillna(0).round(2)
+ avg_times = pd.crosstab(values=df['Tiempo de viaje'], columns=df.Genero, index=df.Tarifa, margins=True, margins_name='Total',aggfunc=lambda x: (x * df.loc[x.index, 'factor_expansion_linea']).sum() / df.loc[x.index, 'factor_expansion_linea'].sum(), ).fillna(0).round(2)
+ avg_velocity = pd.crosstab(values=df['Velocidad'], columns=df.Genero, index=df.Tarifa, margins=True, margins_name='Total',aggfunc=lambda x: (x * df.loc[x.index, 'factor_expansion_linea']).sum() / df.loc[x.index, 'factor_expansion_linea'].sum(), ).fillna(0).round(2)
+ avg_etapas = pd.crosstab(values=df['Etapas promedio'], columns=df.Genero, index=df.Tarifa, margins=True, margins_name='Total',aggfunc=lambda x: (x * df.loc[x.index, 'factor_expansion_linea']).sum() / df.loc[x.index, 'factor_expansion_linea'].sum(), ).round(2).fillna('')
+ user = socio_indicadores[socio_indicadores.tabla=='usuario-genero-tarifa'].copy()
+ avg_viajes = pd.crosstab(values=user['Viajes promedio'],
+ index=[user.Tarifa],
+ columns=user.Genero,
+ margins=True,
+ margins_name='Total',
+ aggfunc=lambda x: (x * user.loc[x.index, 'factor_expansion_linea']).sum() / user.loc[x.index, 'factor_expansion_linea'].sum(),).round(2).fillna('')
+
+ avg_tiempo_entre_viajes = pd.crosstab(values=df['Tiempo entre viajes'],
+ columns=df.Genero,
+ index=df.Tarifa,
+ margins=True,
+ margins_name='Total',
+ aggfunc=lambda x: (x * df.loc[x.index, 'factor_expansion_linea']).sum() / df.loc[x.index, 'factor_expansion_linea'].sum(), ).fillna(0).round(2)
+
+ return totals, totals_porc, avg_distances, avg_times, avg_velocity, modos_genero_abs, modos_genero_porc, modos_tarifa_abs, modos_tarifa_porc, avg_viajes, avg_etapas, avg_tiempo_entre_viajes
+
def crear_mapa_folium(df_agg,
cmap,
var_fex,
@@ -62,41 +262,36 @@ def crear_mapa_folium(df_agg,
st.image(logo)
-with st.expander('Partición modal'):
-
- col1, col2, col3 = st.columns([1, 3, 3])
- particion_modal = levanto_tabla_sql('particion_modal')
-
- desc_dia_m = col1.selectbox(
- 'Periodo', options=particion_modal.desc_dia.unique(), key='desc_dia_m')
- tipo_dia_m = col1.selectbox(
- 'Tipo de día', options=particion_modal.tipo_dia.unique(), key='tipo_dia_m')
-
- # Etapas
- particion_modal_etapas = particion_modal[(particion_modal.desc_dia == desc_dia_m) & (
- particion_modal.tipo_dia == tipo_dia_m) & (particion_modal.tipo == 'etapas')]
- if col2.checkbox('Ver datos: etapas'):
- col2.write(particion_modal_etapas)
- fig2 = px.bar(particion_modal_etapas, x='modo', y='modal')
- fig2.update_layout(title_text='Partición modal de Etapas')
- fig2.update_xaxes(title_text='Modo')
- fig2.update_yaxes(title_text='Partición modal (%)')
- fig2.update_traces(marker_color='brown')
- col2.plotly_chart(fig2)
-
- # Viajes
- particion_modal_viajes = particion_modal[(particion_modal.desc_dia == desc_dia_m) & (
- particion_modal.tipo_dia == tipo_dia_m) & (particion_modal.tipo == 'viajes')]
- if col3.checkbox('Ver datos: viajes'):
- col3.write(particion_modal_viajes)
- fig = px.bar(particion_modal_viajes, x='modo', y='modal')
- fig.update_layout(title_text='Partición modal de Viajes')
- fig.update_xaxes(title_text='Modo')
- fig.update_yaxes(title_text='Partición modal (%)')
- fig.update_traces(marker_color='navy')
- col3.plotly_chart(fig)
+with st.expander('Partición modal', True):
+
+ col1, col2, col3, col4 = st.columns([1, 5, 1.5, 1.5])
+ particion_modal = levanto_tabla_sql('datos_particion_modal')
+
+ desc_mes = col1.selectbox(
+ 'Periodo', options=particion_modal.mes.unique(), key='desc_mes')
+ desc_tipo_dia = col1.selectbox(
+ 'Tipo de día', options=particion_modal.tipo_dia.unique(), key='desc_tipo_dia')
+
+ list_genero = particion_modal.genero.unique()
+ list_genero = ['Todos' if item == '-' else item for item in list_genero]
+
+ desc_genero = col1.selectbox(
+ 'Genero', options=list_genero, key='desc_genero')
+ query = f'select * from datos_particion_modal where mes="{desc_mes}" and tipo_dia="{desc_tipo_dia}"'
+ if desc_genero!='Todos':
+ query += f'and genero = "{desc_genero}"'
+
+ etapas_modos = levanto_tabla_sql('datos_particion_modal', query=query)
+
+ fig, modal_etapas, modal_viajes = plot_venn_diagram(etapas_modos)
+ col2.pyplot(fig)
+ col3.write('Etapas')
+ col3.dataframe(modal_etapas.set_index('Modo'), height=300, width=300)
+ col4.write('Viajes')
+ col4.dataframe(modal_viajes.set_index('Modo'), height=300, width=300)
+
with st.expander('Distancias de viajes'):
col1, col2 = st.columns([1, 4])
@@ -112,18 +307,16 @@ def crear_mapa_folium(df_agg,
if col2.checkbox('Ver datos: distribución de viajes'):
col2.write(hist_values)
- desc_dia_d = col1.selectbox(
- 'Periodo', options=hist_values.desc_dia.unique(), key='desc_dia_d')
- tipo_dia_d = col1.selectbox(
- 'Tipo de dia', options=hist_values.tipo_dia.unique(), key='tipo_dia_d')
-
dist = hist_values.Modo.unique().tolist()
dist.remove('Todos')
dist = ['Todos'] + dist
modo_d = col1.selectbox('Modo', options=dist)
+ col1.write(f'Mes: {desc_mes}')
+ col1.write(f'Tipo de día: {desc_tipo_dia}')
- hist_values = hist_values[(hist_values.desc_dia == desc_dia_d) & (
- hist_values.tipo_dia == tipo_dia_d) & (hist_values.Modo == modo_d)]
+
+ hist_values = hist_values[(hist_values.desc_dia == desc_mes) & (
+ hist_values.tipo_dia == desc_tipo_dia) & (hist_values.Modo == modo_d)]
fig = px.histogram(hist_values, x='Distancia (kms)',
y='Viajes', nbins=len(hist_values))
@@ -176,19 +369,18 @@ def crear_mapa_folium(df_agg,
viajes_hora = levanto_tabla_sql('viajes_hora')
- desc_dia_h = col1.selectbox(
- 'Periodo', options=viajes_hora.desc_dia.unique(), key='desc_dia_h')
- tipo_dia_h = col1.selectbox(
- 'Tipo de dia', options=viajes_hora.tipo_dia.unique(), key='tipo_dia_h')
modo_h = col1.selectbox(
'Modo', options=['Todos', 'Por modos'], key='modo_h')
if modo_h == 'Todos':
- viajes_hora = viajes_hora[(viajes_hora.desc_dia == desc_dia_h) & (
- viajes_hora.tipo_dia == tipo_dia_h) & (viajes_hora.Modo == 'Todos')]
+ viajes_hora = viajes_hora[(viajes_hora.desc_dia == desc_mes) & (
+ viajes_hora.tipo_dia == desc_tipo_dia) & (viajes_hora.Modo == 'Todos')]
else:
- viajes_hora = viajes_hora[(viajes_hora.desc_dia == desc_dia_h) & (
- viajes_hora.tipo_dia == tipo_dia_h) & (viajes_hora.Modo != 'Todos')]
+ viajes_hora = viajes_hora[(viajes_hora.desc_dia == desc_mes) & (
+ viajes_hora.tipo_dia == desc_tipo_dia) & (viajes_hora.Modo != 'Todos')]
+
+ col1.write(f'Mes: {desc_mes}')
+ col1.write(f'Tipo de día: {desc_tipo_dia}')
viajes_hora = viajes_hora.sort_values('Hora')
if col2.checkbox('Ver datos: viajes por hora'):
@@ -203,163 +395,55 @@ def crear_mapa_folium(df_agg,
col2.plotly_chart(fig_horas)
-# with st.expander('Líneas de deseo'):
-
-# col1, col2 = st.columns([1, 4])
-
-# lineas_deseo = levanto_tabla_sql('lineas_deseo')
-
-# if len(lineas_deseo) > 0:
-
-# lineas_deseo = create_linestring_od(lineas_deseo)
-
-# desc_dia = col1.selectbox(
-# 'Periodo', options=lineas_deseo.desc_dia.unique())
-# tipo_dia = col1.selectbox(
-# 'Tipo de dia', options=lineas_deseo.tipo_dia.unique())
-# var_zona = col1.selectbox(
-# 'Zonificación', options=lineas_deseo.var_zona.unique())
-# filtro1 = col1.selectbox(
-# 'Filtro', options=lineas_deseo.filtro1.unique())
-
-# df_agg = lineas_deseo[(
-# (lineas_deseo.desc_dia == desc_dia) &
-# (lineas_deseo.tipo_dia == tipo_dia) &
-# (lineas_deseo.var_zona == var_zona) &
-# (lineas_deseo.filtro1 == filtro1)
-# )].copy()
-
-# if len(df_agg) > 0:
-
-# map = crear_mapa_folium(df_agg,
-# cmap='BuPu',
-# var_fex='Viajes',
-# k_jenks=5)
-
-# with col2:
-# st_map = st_folium(map, width=900, height=700)
-# else:
-
-# col2.markdown("""
-#
-# """, unsafe_allow_html=True)
-
-# col2.markdown(
-# '
¡¡ No hay datos para mostrar !!
', unsafe_allow_html=True)
-
-# else:
-# # Usar HTML para personalizar el estilo del texto
-# texto_html = """
-#
-#
-# No hay datos para mostrar
-#
-# """
-# col2.markdown(texto_html, unsafe_allow_html=True)
-# texto_html = """
-#
-#
-# Verifique que los procesos se corrieron correctamente
-#
-# """
-# col2.markdown(texto_html, unsafe_allow_html=True)
-# with st.expander('Matrices OD'):
-# col1, col2 = st.columns([1, 4])
-
-# matriz = levanto_tabla_sql('matrices')
-
-# if len(matriz) > 0:
-
-# if col1.checkbox('Normalizar', value=True):
-# normalize = True
-# else:
-# normalize = False
-
-# desc_dia_ = col1.selectbox(
-# 'Periodo ', options=matriz.desc_dia.unique())
-# tipo_dia_ = col1.selectbox(
-# 'Tipo de dia ', options=matriz.tipo_dia.unique())
-# var_zona_ = col1.selectbox(
-# 'Zonificación ', options=matriz.var_zona.unique())
-# filtro1_ = col1.selectbox('Filtro ', options=matriz.filtro1.unique())
-
-# matriz = matriz[((matriz.desc_dia == desc_dia_) &
-# (matriz.tipo_dia == tipo_dia_) &
-# (matriz.var_zona == var_zona_) &
-# (matriz.filtro1 == filtro1_)
-# )].copy()
-
-# od_heatmap = pd.crosstab(
-# index=matriz['Origen'],
-# columns=matriz['Destino'],
-# values=matriz['Viajes'],
-# aggfunc="sum",
-# normalize=normalize,
-# )
-# od_heatmap = (od_heatmap * 100).round(1)
-
-# od_heatmap = od_heatmap.reset_index()
-# od_heatmap['Origen'] = od_heatmap['Origen'].str[4:]
-# od_heatmap = od_heatmap.set_index('Origen')
-# od_heatmap.columns = [i[4:] for i in od_heatmap.columns]
-
-# fig = px.imshow(od_heatmap, text_auto=True,
-# color_continuous_scale='Blues',)
-
-# fig.update_coloraxes(showscale=False)
-
-# if len(od_heatmap) <= 20:
-# fig.update_layout(width=800, height=800)
-# elif (len(od_heatmap) > 20) & (len(od_heatmap) <= 40):
-# fig.update_layout(width=1000, height=1000)
-# elif len(od_heatmap) > 40:
-# fig.update_layout(width=1200, height=1200)
-
-# col2.plotly_chart(fig)
-
-# else:
-# st.write('No hay datos para mostrar')
-
-# zonas = levanto_tabla_sql('zonas')
-# zonas = zonas[zonas.tipo_zona == var_zona_]
-
-# col1, col2 = st.columns([1, 4])
-
-# if col1.checkbox('Mostrar zonificacion'):
-
-# # Create a folium map centered on the data
-# map_center = [zonas.geometry.centroid.y.mean(
-# ), zonas.geometry.centroid.x.mean()]
-
-# fig = Figure(width=800, height=800)
-# m = folium.Map(location=map_center, zoom_start=10,
-# tiles='cartodbpositron')
-
-# # Add GeoDataFrame to the map
-# folium.GeoJson(zonas).add_to(m)
-
-# for idx, row in zonas.iterrows():
-# # Replace 'column_name' with the name of the column containing the detail
-# detail = row['Zona']
-# point = [row['geometry'].representative_point(
-# ).y, row['geometry'].representative_point().x]
-# marker = folium.Marker(location=point, popup=detail)
-# marker.add_to(m)
-
-# # Display the map using folium_static
-# with col2:
-# folium_static(m)
+with st.expander('Género y tarifas'):
+ col1, col2, col3, col4 = st.columns([1, 2, 2, 2])
+ socio_indicadores = levanto_tabla_sql('socio_indicadores')
+
+ col1.write(f'Mes: {desc_mes}')
+ col1.write(f'Tipo de día: {desc_tipo_dia}')
+
+
+ if desc_mes != 'Todos':
+ st.session_state.socio_indicadores_ = socio_indicadores[(socio_indicadores.mes==desc_mes)&(socio_indicadores.tipo_dia==desc_tipo_dia)].copy()
+
+ else:
+ st.session_state.socio_indicadores_ = socio_indicadores[(socio_indicadores.tipo_dia==desc_tipo_dia)].copy()
+
+ totals, totals_porc, avg_distances, avg_times, avg_velocity, modos_genero_abs, modos_genero_porc, modos_tarifa_abs, modos_tarifa_porc, avg_viajes, avg_etapas, avg_tiempo_entre_viajes = traigo_socio_indicadores(st.session_state.socio_indicadores_)
+
+
+ if totals is not None:
+ col2.markdown("Total de viajes por género y tarifa
", unsafe_allow_html=True)
+ col2.table(totals)
+ col3.markdown("Porcentaje de viajes por género y tarifa
", unsafe_allow_html=True)
+ col3.table(totals_porc.round(2).astype(str))
+
+ col2.markdown("Cantidad promedio de viajes por género y tarifa
", unsafe_allow_html=True)
+ col2.table(avg_viajes.round(2).astype(str))
+ col3.markdown("Cantidad promedio de etapas por género y tarifa
", unsafe_allow_html=True)
+ col3.table(avg_etapas.round(2).astype(str))
+
+
+ col2.markdown("Total de etapas por género y modo
", unsafe_allow_html=True)
+ col2.table(modos_genero_abs)
+ col3.markdown("Porcentaje de etapas por género y modo
", unsafe_allow_html=True)
+ col3.table(modos_genero_porc.round(2).astype(str))
+
+ col2.markdown("Total de etapas por tarifa y modo
", unsafe_allow_html=True)
+ col2.table(modos_tarifa_abs)
+ col3.markdown("Porcentaje de etapas por tarifa y modo
", unsafe_allow_html=True)
+ col3.table(modos_tarifa_porc.round(2).astype(str))
+
+ col2.markdown("Distancias promedio (kms)
", unsafe_allow_html=True)
+ col2.table(avg_distances.round(2).astype(str))
+
+ col3.markdown("Tiempos promedio (minutos)
", unsafe_allow_html=True)
+ col3.table(avg_times.round(2).astype(str))
+
+ col2.markdown("Velocidades promedio (kms/hora)
", unsafe_allow_html=True)
+ col2.table(avg_velocity.round(2).astype(str))
+
+ col3.markdown("Tiempos promedio entre viajes (minutos)
", unsafe_allow_html=True)
+ col3.table(avg_tiempo_entre_viajes.round(2).astype(str))
+ else:
+ col2.write('No hay datos para mostrar')
diff --git "a/urbantrips/dashboard/pages/3_L\303\255neas de Deseo.py" "b/urbantrips/dashboard/pages/3_L\303\255neas de Deseo.py"
index 8d1bc33..95dc3af 100644
--- "a/urbantrips/dashboard/pages/3_L\303\255neas de Deseo.py"
+++ "b/urbantrips/dashboard/pages/3_L\303\255neas de Deseo.py"
@@ -13,7 +13,7 @@
create_data_folium, traigo_indicadores,
extract_hex_colors_from_cmap,
iniciar_conexion_db, normalize_vars,
- bring_latlon, traigo_zonas_values
+ bring_latlon, traigo_zonas_values, get_h3_indices_in_geometry
)
def crear_mapa_lineas_deseo(df_viajes,
@@ -71,6 +71,10 @@ def crear_mapa_lineas_deseo(df_viajes,
bins = [df_etapas[var_fex].min()-1] + \
mapclassify.FisherJenks(
df_etapas[var_fex], k=k_jenks-3).bins.tolist()
+ except ValueError:
+ bins = [df_etapas[var_fex].min()-1] + \
+ mapclassify.FisherJenks(
+ df_etapas[var_fex], k=1).bins.tolist()
range_bins = range(0, len(bins)-1)
bins_labels = [
@@ -94,20 +98,40 @@ def crear_mapa_lineas_deseo(df_viajes,
# Viajes
line_w = 0.5
if len(df_viajes) > 0:
+
try:
- bins = [df_viajes[var_fex].min()-1] + \
- mapclassify.FisherJenks(
- df_viajes[var_fex], k=k_jenks).bins.tolist()
+ # Intentar clasificar con k clases
+ bins = [df_viajes[var_fex].min() - 1] + \
+ mapclassify.FisherJenks(df_viajes[var_fex], k=k_jenks).bins.tolist()
except ValueError:
- bins = [df_viajes[var_fex].min()-1] + \
- mapclassify.FisherJenks(
- df_viajes[var_fex], k=k_jenks-2).bins.tolist()
-
+ # Si falla, reducir k dinámicamente
+ while k_jenks > 1:
+ try:
+ bins = [df_viajes[var_fex].min() - 1] + \
+ mapclassify.FisherJenks(df_viajes[var_fex], k=k_jenks - 1).bins.tolist()
+ break
+ except ValueError:
+ k_jenks -= 1
+ else:
+ # Si no se puede crear ni una categoría, asignar un único bin
+ bins = [df_viajes[var_fex].min() - 1, df_viajes[var_fex].max()]
+
+ # Eliminar duplicados en bins
+ bins = sorted(set(bins))
+
+ # Crear etiquetas únicas para los bins
range_bins = range(0, len(bins)-1)
bins_labels = [
- f'{int(bins[n])} a {int(bins[n+1])} viajes' for n in range_bins]
+ f'{int(bins[n])} a {int(bins[n+1])} viajes' for n in range_bins
+ ]
+
+ # Garantizar que las etiquetas sean únicas
+ bins_labels = [f"{label} ({i})" for i, label in enumerate(bins_labels)]
+
+ # Aplicar pd.cut con ordered=False para evitar el error
df_viajes['cuts'] = pd.cut(
- df_viajes[var_fex], bins=bins, labels=bins_labels)
+ df_viajes[var_fex], bins=bins, labels=bins_labels, ordered=False
+ )
n = 0
for i in bins_labels:
@@ -124,13 +148,25 @@ def crear_mapa_lineas_deseo(df_viajes,
if len(origenes) > 0:
try:
- bins = [origenes['factor_expansion_linea'].min()-1] + \
- mapclassify.FisherJenks(
- origenes['factor_expansion_linea'], k=5).bins.tolist()
+ # Intentar clasificar con k inicial
+ bins = [origenes['factor_expansion_linea'].min() - 1] + \
+ mapclassify.FisherJenks(origenes['factor_expansion_linea'], k=5).bins.tolist()
except ValueError:
- bins = [origenes['factor_expansion_linea'].min()-1] + \
- mapclassify.FisherJenks(
- origenes['factor_expansion_linea'], k=5-3).bins.tolist()
+ # Reducir k dinámicamente en caso de error
+ k = 5
+ while k > 1:
+ try:
+ bins = [origenes['factor_expansion_linea'].min() - 1] + \
+ mapclassify.FisherJenks(origenes['factor_expansion_linea'], k=k).bins.tolist()
+ break
+ except ValueError:
+ k -= 1
+ else:
+ # Si no se pueden generar bins, usar un único bin
+ bins = [origenes['factor_expansion_linea'].min() - 1, origenes['factor_expansion_linea'].max()]
+
+ print(bins)
+
range_bins = range(0, len(bins)-1)
bins_labels = [
@@ -265,54 +301,7 @@ def levanto_tabla_sql_local(tabla_sql, tabla_tipo="dash", query=''):
return tabla
-def traigo_socio_indicadores(socio_indicadores):
- totals = None
- totals_porc = 0
- avg_distances = 0
- avg_times = 0
- avg_velocity = 0
- modos_genero_abs = 0
- modos_genero_porc = 0
- modos_tarifa_abs = 0
- modos_tarifa_porc = 0
- avg_viajes = 0
- avg_etapas = 0
- avg_tiempo_entre_viajes = 0
-
- if len(socio_indicadores) > 0:
-
- df = socio_indicadores[socio_indicadores.tabla=='viajes-genero-tarifa'].copy()
- totals = pd.crosstab(values=df.factor_expansion_linea, columns=df.Genero, index=df.Tarifa, aggfunc='sum', margins=True, margins_name='Total', normalize=False).fillna(0).round().astype(int).apply(lambda col: col.map(lambda x: f'{x:,.0f}'.replace(',', '.')))
- totals_porc = (pd.crosstab(values=df.factor_expansion_linea, columns=df.Genero, index=df.Tarifa, aggfunc='sum', margins=True, margins_name='Total', normalize=True) * 100).round(2)
-
- modos = socio_indicadores[socio_indicadores.tabla=='etapas-genero-modo'].copy()
- modos_genero_abs = pd.crosstab(values=modos.factor_expansion_linea, index=[modos.Genero], columns=modos.Modo, aggfunc='sum', normalize=False, margins=True, margins_name='Total').fillna(0).astype(int).apply(lambda col: col.map(lambda x: f'{x:,.0f}'.replace(',', '.')))
- modos_genero_porc = (pd.crosstab(values=modos.factor_expansion_linea, index=modos.Genero, columns=modos.Modo, aggfunc='sum', normalize=True, margins=True, margins_name='Total') * 100).round(2)
-
- modos = socio_indicadores[socio_indicadores.tabla=='etapas-tarifa-modo'].copy()
- modos_tarifa_abs = pd.crosstab(values=modos.factor_expansion_linea, index=[modos.Tarifa], columns=modos.Modo, aggfunc='sum', normalize=False, margins=True, margins_name='Total').fillna(0).astype(int).apply(lambda col: col.map(lambda x: f'{x:,.0f}'.replace(',', '.')))
- modos_tarifa_porc = (pd.crosstab(values=modos.factor_expansion_linea, index=modos.Tarifa, columns=modos.Modo, aggfunc='sum', normalize=True, margins=True, margins_name='Total') * 100).round(2)
-
- avg_distances = pd.crosstab(values=df.Distancia, columns=df.Genero, index=df.Tarifa, margins=True, margins_name='Total',aggfunc=lambda x: (x * df.loc[x.index, 'factor_expansion_linea']).sum() / df.loc[x.index, 'factor_expansion_linea'].sum(), ).fillna(0).round(2)
- avg_times = pd.crosstab(values=df['Tiempo de viaje'], columns=df.Genero, index=df.Tarifa, margins=True, margins_name='Total',aggfunc=lambda x: (x * df.loc[x.index, 'factor_expansion_linea']).sum() / df.loc[x.index, 'factor_expansion_linea'].sum(), ).fillna(0).round(2)
- avg_velocity = pd.crosstab(values=df['Velocidad'], columns=df.Genero, index=df.Tarifa, margins=True, margins_name='Total',aggfunc=lambda x: (x * df.loc[x.index, 'factor_expansion_linea']).sum() / df.loc[x.index, 'factor_expansion_linea'].sum(), ).fillna(0).round(2)
- avg_etapas = pd.crosstab(values=df['Etapas promedio'], columns=df.Genero, index=df.Tarifa, margins=True, margins_name='Total',aggfunc=lambda x: (x * df.loc[x.index, 'factor_expansion_linea']).sum() / df.loc[x.index, 'factor_expansion_linea'].sum(), ).round(2).fillna('')
- user = socio_indicadores[socio_indicadores.tabla=='usuario-genero-tarifa'].copy()
- avg_viajes = pd.crosstab(values=user['Viajes promedio'],
- index=[user.Tarifa],
- columns=user.Genero,
- margins=True,
- margins_name='Total',
- aggfunc=lambda x: (x * user.loc[x.index, 'factor_expansion_linea']).sum() / user.loc[x.index, 'factor_expansion_linea'].sum(),).round(2).fillna('')
-
- avg_tiempo_entre_viajes = pd.crosstab(values=df['Tiempo entre viajes'],
- columns=df.Genero,
- index=df.Tarifa,
- margins=True,
- margins_name='Total',
- aggfunc=lambda x: (x * df.loc[x.index, 'factor_expansion_linea']).sum() / df.loc[x.index, 'factor_expansion_linea'].sum(), ).fillna(0).round(2)
-
- return totals, totals_porc, avg_distances, avg_times, avg_velocity, modos_genero_abs, modos_genero_porc, modos_tarifa_abs, modos_tarifa_porc, avg_viajes, avg_etapas, avg_tiempo_entre_viajes
+
# Función para detectar cambios
def hay_cambios_en_filtros(current, last):
@@ -354,7 +343,7 @@ def hay_cambios_en_filtros(current, last):
# st.session_state.etapas_all = st.session_state.etapas_all[st.session_state.etapas_all.factor_expansion_linea > 0].copy()
- general, modal, distancias = traigo_indicadores('all')
+ # general, modal, distancias = traigo_indicadores('all')
# Inicializar valores de `st.session_state` solo si no existen
if 'last_filters' not in st.session_state:
@@ -403,7 +392,10 @@ def hay_cambios_en_filtros(current, last):
desc_etapas = False
zonas_values_all = ['Todos'] + zonas_values[zonas_values.zona == desc_zona].Nombre.unique().tolist()
- desc_zonas_values = col1.selectbox('Filtro', options=zonas_values_all)
+ desc_zonas_values1 = col1.selectbox('Filtro 1', options=zonas_values_all, key='filtro1')
+ desc_zonas_values2 = col1.selectbox('Filtro 2', options=zonas_values_all, key='filtro2')
+
+
desc_origenes = col1.checkbox(
@@ -433,7 +425,8 @@ def hay_cambios_en_filtros(current, last):
'modo_agregado': None if modos_list == 'Todos' else modos_list,
'rango_hora': None if rango_hora == 'Todos' else rango_hora,
'distancia': None if distancia == 'Todas' else distancia,
- 'desc_zonas_values': None if desc_zonas_values == 'Todos' else desc_zonas_values,
+ 'desc_zonas_values1': None if desc_zonas_values1 == 'Todos' else desc_zonas_values1,
+ 'desc_zonas_values2': None if desc_zonas_values2 == 'Todos' else desc_zonas_values2,
}
current_options = { 'desc_etapas': desc_etapas,
@@ -451,17 +444,35 @@ def hay_cambios_en_filtros(current, last):
if hay_cambios_en_filtros(current_filters, st.session_state.last_filters):
query = ""
- conditions = " AND ".join(f"{key} = '{value}'" for key, value in current_filters.items() if (value is not None)&(key != 'desc_zonas_values'))
+ conditions = " AND ".join(f"{key} = '{value}'" for key, value in current_filters.items() if (value is not None)&(key != 'desc_zonas_values1')&(key != 'desc_zonas_values2'))
if conditions:
query += f" WHERE {conditions}"
- conditions_etapas = ''
- conditions_matrices = ''
- if desc_zonas_values != 'Todos':
- conditions_etapas = f" AND (inicio_norm = '{desc_zonas_values}' OR transfer1_norm = '{desc_zonas_values}' OR transfer2_norm = '{desc_zonas_values}' OR fin_norm = '{desc_zonas_values}')"
- conditions_matrices = f" AND (inicio = '{desc_zonas_values}' OR fin = '{desc_zonas_values}')"
- query_etapas = query + conditions_etapas
- query_matrices = query + conditions_matrices
+ conditions_etapas1 = ''
+ conditions_matrices1 = ''
+ st.session_state['zona_1'] = []
+
+ if desc_zonas_values1 != 'Todos':
+
+ conditions_etapas1 = f" AND (inicio_norm = '{desc_zonas_values1}' OR transfer1_norm = '{desc_zonas_values1}' OR transfer2_norm = '{desc_zonas_values1}' OR fin_norm = '{desc_zonas_values1}')"
+ conditions_matrices1 = f" AND (inicio = '{desc_zonas_values1}' OR fin = '{desc_zonas_values1}')"
+
+ geometry = zonificaciones[(zonificaciones.zona == desc_zona)&(zonificaciones.id==desc_zonas_values1)].geometry.values[0]
+ h3_indices = get_h3_indices_in_geometry(geometry, 8)
+ st.session_state['zona_1'].extend(h3_indices)
+
+ conditions_etapas2 = ''
+ conditions_matrices2 = ''
+ st.session_state['zona_2'] = []
+ if desc_zonas_values2 != 'Todos':
+ conditions_etapas2 = f" AND (inicio_norm = '{desc_zonas_values2}' OR transfer1_norm = '{desc_zonas_values2}' OR transfer2_norm = '{desc_zonas_values2}' OR fin_norm = '{desc_zonas_values2}')"
+ conditions_matrices2 = f" AND (inicio = '{desc_zonas_values2}' OR fin = '{desc_zonas_values2}')"
+ geometry = zonificaciones[(zonificaciones.zona == desc_zona)&(zonificaciones.id==desc_zonas_values2)].geometry.values[0]
+ h3_indices = get_h3_indices_in_geometry(geometry, 8)
+ st.session_state['zona_2'].extend(h3_indices)
+
+ query_etapas = query + conditions_etapas1 + conditions_etapas2
+ query_matrices = query + conditions_matrices1 + conditions_matrices2
st.session_state.etapas_ = levanto_tabla_sql_local('agg_etapas', tabla_tipo='dash', query=f"SELECT * FROM agg_etapas{query_etapas}")
st.session_state.matrices_ = levanto_tabla_sql_local('agg_matrices', tabla_tipo='dash', query=f"SELECT * FROM agg_matrices{query_matrices}")
@@ -523,10 +534,6 @@ def hay_cambios_en_filtros(current, last):
]] .mean().round(2)
- st.session_state.general_ = general.loc[general.mes==desc_mes, ['Tipo', 'Indicador', 'Valor']].set_index('Tipo')
- st.session_state.modal_ = modal.loc[modal.mes==desc_mes, ['Tipo', 'Indicador', 'Valor']].set_index('Tipo')
- st.session_state.distancias_ = distancias.loc[distancias.mes==desc_mes, ['Tipo', 'Indicador', 'Valor']].set_index('Tipo')
-
if transf_list == 'Todos':
st.session_state.desc_transfers = True
else:
@@ -633,28 +640,27 @@ def hay_cambios_en_filtros(current, last):
col2.text("No hay datos suficientes para mostrar el mapa.")
-with st.expander('Indicadores'):
- col1, col2, col3 = st.columns([2, 2, 2])
-
- if len(st.session_state.etapas_) > 0:
- col1.table(st.session_state.general_)
- col2.table(st.session_state.modal_)
- col3.table(st.session_state.distancias_)
-
with st.expander('Matrices'):
col1, col2 = st.columns([1, 4])
+
if len(st.session_state.matriz) > 0:
- # col2.table(st.session_state.matriz)
-
tipo_matriz = col1.selectbox(
'Variable', options=['Viajes', 'Distancia promedio (kms)', 'Tiempo promedio (min)', 'Velocidad promedio (km/h)'])
-
+
normalize = False
if tipo_matriz == 'Viajes':
var_matriz = 'factor_expansion_linea'
normalize = col1.checkbox('Normalizar', value=True)
+
+ col1.write(f'Mes: {desc_mes}')
+ col1.write(f'Tipo día: {desc_tipo_dia}')
+ col1.write(f'Transferencias: {transf_list}')
+ col1.write(f'Modos: {modos_list}')
+ col1.write(f'Rango hora: {rango_hora}')
+ col1.write(f'Distancias: {distancia}')
+
if tipo_matriz == 'Distancia promedio (kms)':
var_matriz = 'distance_osm_drive'
if tipo_matriz == 'Tiempo promedio (min)':
@@ -696,45 +702,265 @@ def hay_cambios_en_filtros(current, last):
else:
col2.text('No hay datos para mostrar')
-with st.expander('Género y tarifas'):
- col1, col2, col3, col4 = st.columns([1, 2, 2, 2])
- totals, totals_porc, avg_distances, avg_times, avg_velocity, modos_genero_abs, modos_genero_porc, modos_tarifa_abs, modos_tarifa_porc, avg_viajes, avg_etapas, avg_tiempo_entre_viajes = traigo_socio_indicadores(st.session_state.socio_indicadores_)
- if totals is not None:
- col2.markdown("Total de viajes por género y tarifa
", unsafe_allow_html=True)
- col2.table(totals)
- col3.markdown("Porcentaje de viajes por género y tarifa
", unsafe_allow_html=True)
- col3.table(totals_porc.round(2).astype(str))
+with st.expander('Zonas', expanded=False):
+ col1, col2, col3, col4, col5 = st.columns([1, 2, 2, 2, 2])
+ zona1 = st.session_state['zona_1']
+ zona2 = st.session_state['zona_2']
+
+
+ if len(zona1) > 0:
+ query1 = f"SELECT * FROM etapas_agregadas WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND ({desc_zona}_o = '{desc_zonas_values1}');"
+ etapas1 = levanto_tabla_sql_local('etapas_agregadas', tabla_tipo='dash', query=query1)
+
+
+ if len(etapas1) > 0:
+ etapas1['Zona_1'] = 'Zona 1'
+
+ ## Viajes
+ query1 = f"SELECT * FROM viajes_agregados WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND {desc_zona}_o = '{desc_zonas_values1}';"
+ viajes1 = levanto_tabla_sql_local('viajes_agregados', tabla_tipo='dash', query=query1)
+ viajes1['Zona_1'] = 'Zona 1'
+
+ modos_e1 = etapas1.groupby(['modo', 'nombre_linea'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Etapas',
+ 'nombre_linea': 'Línea', 'modo': 'Modo'})
+
+ modos_v1 = viajes1.groupby(['modo'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Viajes',
+ 'modo': 'Modo'})
+
+ # Calculate the total and append as a new row
+ total_row1e = pd.DataFrame({
+ 'Modo': ['Total'],
+ 'Línea': ['-'],
+ 'Etapas': [modos_e1['Etapas'].sum()]
+ })
+ modos_e1 = pd.concat([modos_e1, total_row1e], ignore_index=True)
+
+
+ # Calculate the total and append as a new row
+ total_row1 = pd.DataFrame({
+ 'Modo': ['Total'],
+ 'Viajes': [modos_v1['Viajes'].sum()]
+ })
+ modos_v1 = pd.concat([modos_v1, total_row1], ignore_index=True)
+
+ col2.markdown(
+ f"""
+ {desc_zonas_values1}
+ """,
+ unsafe_allow_html=True
+ )
+
+ col2.write('Etapas')
+ modos_e1['Etapas'] = modos_e1['Etapas'].round()
+ col2.dataframe(modos_e1.set_index('Modo'), height=400, width=400)
+
+ col3.markdown(
+ f"""
+
+ """,
+ unsafe_allow_html=True
+ )
+ col3.write('Viajes')
+ modos_v1['Viajes'] = modos_v1['Viajes'].round()
+ col3.dataframe(modos_v1.set_index('Modo'), height=400, width=300)
- col2.markdown("Cantidad promedio de viajes por género y tarifa
", unsafe_allow_html=True)
- col2.table(avg_viajes.round(2).astype(str))
- col3.markdown("Cantidad promedio de etapas por género y tarifa
", unsafe_allow_html=True)
- col3.table(avg_etapas.round(2).astype(str))
+ if len(zona2) > 0:
+
+ query2 = f"SELECT * FROM etapas_agregadas WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND ({desc_zona}_o = '{desc_zonas_values2}');"
+ etapas2 = levanto_tabla_sql_local('etapas_agregadas', tabla_tipo='dash', query=query2)
+
+ if len(etapas2) > 0:
+
+ ## Etapas
+ if len(etapas2) > 0:
+ etapas2['Zona_2'] = 'Zona 2'
+
+ ## Viajes
+ query2 = f"SELECT * FROM viajes_agregados WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND {desc_zona}_o = '{desc_zonas_values2}';"
+ viajes2 = levanto_tabla_sql_local('viajes_agregados', tabla_tipo='dash', query=query2)
+ viajes2['Zona_2'] = 'Zona 2'
-
- col2.markdown("Total de etapas por género y modo
", unsafe_allow_html=True)
- col2.table(modos_genero_abs)
- col3.markdown("Porcentaje de etapas por género y modo
", unsafe_allow_html=True)
- col3.table(modos_genero_porc.round(2).astype(str))
+ modos_e2 = etapas2.groupby(['modo', 'nombre_linea'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Etapas',
+ 'nombre_linea': 'Línea', 'modo': 'Modo'})
- col2.markdown("Total de etapas por tarifa y modo
", unsafe_allow_html=True)
- col2.table(modos_tarifa_abs)
- col3.markdown("Porcentaje de etapas por tarifa y modo
", unsafe_allow_html=True)
- col3.table(modos_tarifa_porc.round(2).astype(str))
+ modos_v2 = viajes2.groupby(['modo'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Viajes',
+ 'modo': 'Modo'})
+ # Calculate the total and append as a new row
+ total_row2e = pd.DataFrame({
+ 'Modo': ['Total'],
+ 'Línea': ['-'],
+ 'Etapas': [modos_e2['Etapas'].sum()]
+ })
+ modos_e2 = pd.concat([modos_e2, total_row2e], ignore_index=True)
+
+ # Calculate the total and append as a new row
+ total_row2 = pd.DataFrame({
+ 'Modo': ['Total'],
+ 'Viajes': [modos_v2['Viajes'].sum()]
+ })
+ modos_v2 = pd.concat([modos_v2, total_row2], ignore_index=True)
+
+ col4.markdown(
+ f"""
+ {desc_zonas_values2}
+ """,
+ unsafe_allow_html=True
+ )
+ col4.write('Etapas')
+ modos_e2['Etapas'] = modos_e2['Etapas'].round()
+ col4.dataframe(modos_e2.set_index('Modo'), height=400, width=400)
- col2.markdown("Distancias promedio (kms)
", unsafe_allow_html=True)
- col2.table(avg_distances.round(2).astype(str))
+ modos_v2['Viajes'] = modos_v2['Viajes'].round()
+ col5.markdown(
+ f"""
+
+ """,
+ unsafe_allow_html=True
+ )
- col3.markdown("Tiempos promedio (minutos)
", unsafe_allow_html=True)
- col3.table(avg_times.round(2).astype(str))
+ col5.write('Viajes')
+ col5.dataframe(modos_v2.set_index('Modo'), height=400, width=300)
+
+with st.expander('Viajes entre zonas', expanded=True):
+ col1, col2, col3 = st.columns([1, 2, 4])
+
+ transferencias_modos = pd.DataFrame([])
+ modos_e = pd.DataFrame([])
+ modos_v = pd.DataFrame([])
+ transferencias = pd.DataFrame([])
+ zonasod_e = pd.DataFrame([])
+ zonasod_v = pd.DataFrame([])
- col2.markdown("Velocidades promedio (kms/hora)
", unsafe_allow_html=True)
- col2.table(avg_velocity.round(2).astype(str))
+ if len(zona1) > 0 and len(zona2) > 0:
+
+ col1.write(f'Mes: {desc_mes}')
+ col1.write(f'Tipo día: {desc_tipo_dia}')
+ col1.write(f'Zona 1: {desc_zonas_values1}')
+ col1.write(f'Zona 2: {desc_zonas_values2}')
+
+ ## Etapas
+ h3_values = [desc_zonas_values1, desc_zonas_values2]
+ h3_values = ', '.join(f"'{valor}'" for valor in h3_values)
+ query = f"SELECT * FROM etapas_agregadas WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND ({desc_zona}_o IN ({h3_values}) OR {desc_zona}_d IN ({h3_values}));"
+ etapas = levanto_tabla_sql_local('etapas_agregadas', tabla_tipo='dash', query=query)
+
+ if len(etapas) > 0:
+
+ etapas['Zona_1'] = ''
+ etapas['Zona_2'] = ''
+ etapas.loc[etapas.h3_o.isin(zona1), 'Zona_1'] = 'Zona 1'
+ etapas.loc[etapas.h3_o.isin(zona2), 'Zona_1'] = 'Zona 2'
+ etapas.loc[etapas.h3_d.isin(zona1), 'Zona_2'] = 'Zona 1'
+ etapas.loc[etapas.h3_d.isin(zona2), 'Zona_2'] = 'Zona 2'
+ etapas = etapas[(etapas.Zona_1 != '') & (etapas.Zona_2 != '') & (etapas.Zona_1 != etapas.Zona_2)]
+
+ etapas = etapas.fillna('')
+
+ zonasod_e = etapas.groupby(['Zona_1', 'Zona_2'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Etapas'}) #.round()
+ zonasod_e['Etapas'] = zonasod_e['Etapas'].apply(lambda x: f"{int(x):,}")
+
+ zonasod_e['Zonas'] = zonasod_e['Zona_1'] + ' - ' + zonasod_e['Zona_2']
+ zonasod_e = zonasod_e[['Zonas', 'Etapas']]
+
+ modos_e = etapas.groupby(['modo', 'nombre_linea'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Viajes',
+ 'nombre_linea': 'Líneas',
+ 'modo': 'Modo'}) #.round()
+
+
+ ## Viajes
+ # ({desc_zona}_o = '{desc_zonas_values2}')
+ h3_values = [desc_zonas_values1, desc_zonas_values2]
+ h3_values = ', '.join(f"'{valor}'" for valor in h3_values)
+ query = f"SELECT * FROM viajes_agregados WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND ({desc_zona}_o IN ({h3_values}) OR {desc_zona}_d IN ({h3_values}));"
+ viajes = levanto_tabla_sql_local('viajes_agregados', tabla_tipo='dash', query=query)
+ if len(viajes) > 0:
+
+ viajes['Zona_1'] = ''
+ viajes['Zona_2'] = ''
+ viajes.loc[viajes.h3_o.isin(zona1), 'Zona_1'] = 'Zona 1'
+ viajes.loc[viajes.h3_o.isin(zona2), 'Zona_1'] = 'Zona 2'
+ viajes.loc[viajes.h3_d.isin(zona1), 'Zona_2'] = 'Zona 1'
+ viajes.loc[viajes.h3_d.isin(zona2), 'Zona_2'] = 'Zona 2'
+ viajes = viajes[(viajes.Zona_1 != '') & (viajes.Zona_2 != '') & (viajes.Zona_1 != viajes.Zona_2)]
+
+ zonasod_v = viajes.groupby(['Zona_1', 'Zona_2'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Viajes'})
+
+ zonasod_v['Zonas'] = zonasod_v['Zona_1'] + ' - ' + zonasod_v['Zona_2']
+ zonasod_v = zonasod_v[['Zonas', 'Viajes']]
+ zonasod_v['Viajes'] = zonasod_v['Viajes'].apply(lambda x: f"{int(x):,}")
+
+ modos_v = viajes.groupby(['modo'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Viajes',
+ 'modo': 'Modo'})
+
+ if len(modos_v)>0:
+ # Calculate the total and append as a new row
+ total_row = pd.DataFrame({
+ 'Modo': ['Total'],
+ 'Viajes': [modos_v['Viajes'].sum()]
+ })
+ modos_v = pd.concat([modos_v, total_row], ignore_index=True)
+ modos_v['Viajes'] = modos_v['Viajes'].apply(lambda x: f"{int(x):,}")
+
+ # Transferencias
+ h3_values = [desc_zonas_values1, desc_zonas_values2]
+ h3_values = ', '.join(f"'{valor}'" for valor in h3_values)
+ query = f"SELECT * FROM transferencias_agregadas WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND ({desc_zona}_o IN ({h3_values}) OR {desc_zona}_d IN ({h3_values}));"
+ transferencias = levanto_tabla_sql_local('transferencias_agregadas', tabla_tipo='dash', query=query)
+
+ if len(transferencias) > 0:
- col3.markdown("Tiempos promedio entre viajes (minutos)
", unsafe_allow_html=True)
- col3.table(avg_tiempo_entre_viajes.round(2).astype(str))
- else:
- col2.write('No hay datos para mostrar')
+ transferencias['Zona_1'] = ''
+ transferencias['Zona_2'] = ''
+ transferencias.loc[transferencias.h3_o.isin(zona1), 'Zona_1'] = 'Zona 1'
+ transferencias.loc[transferencias.h3_o.isin(zona2), 'Zona_1'] = 'Zona 2'
+ transferencias.loc[transferencias.h3_d.isin(zona1), 'Zona_2'] = 'Zona 1'
+ transferencias.loc[transferencias.h3_d.isin(zona2), 'Zona_2'] = 'Zona 2'
+ transferencias = transferencias[(transferencias.Zona_1 != '') & (transferencias.Zona_2 != '') & (transferencias.Zona_1 != transferencias.Zona_2)]
+
+ transferencias = transferencias.fillna('')
+
+ transferencias = transferencias.groupby(['modo',
+ 'seq_lineas'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Viajes',
+ 'modo':'Modo', 'seq_lineas':'Líneas'}).sort_values('Viajes', ascending=False)
+
+ # Calculate the total and append as a new row
+ if len(transferencias)>0:
+ total_rowe = pd.DataFrame({
+ 'Modo': ['Total'],
+ 'Líneas': ['-'],
+ 'Viajes': [transferencias['Viajes'].sum()]
+ })
+ transferencias = pd.concat([transferencias, total_rowe], ignore_index=True)
+ transferencias['Viajes'] = transferencias['Viajes'].apply(lambda x: f"{int(x):,}")
+
+
+ # Muestro resultados en el dashboard
+ col2.write('Etapas')
+ if len(zonasod_e) > 0:
+ col2.dataframe(zonasod_e.set_index('Zonas'), height=100, width=300)
+ else:
+ col2.write('No hay datos para mostrar')
+
+ col2.write('Viajes')
+ if len(zonasod_v):
+ col2.dataframe(zonasod_v.set_index('Zonas'), height=100, width=300)
+ else:
+ col2.write('No hay datos para mostrar')
+
+ col2.write('Modal')
+ if len(modos_v)>0:
+ col2.dataframe(modos_v.set_index('Modo'), height=300, width=300)
+ else:
+ col2.write('No hay datos para mostrar')
+
+ col3.write('Viajes por líneas')
+ if len(transferencias)>0:
+ col3.dataframe(transferencias.set_index('Modo'), height=700, width=800)
+ else:
+ col3.write('No hay datos para mostrar')
+
+
diff --git a/urbantrips/dashboard/pages/4_Poligonos.py b/urbantrips/dashboard/pages/4_Poligonos.py
index 43b82e2..3891c42 100644
--- a/urbantrips/dashboard/pages/4_Poligonos.py
+++ b/urbantrips/dashboard/pages/4_Poligonos.py
@@ -53,6 +53,10 @@ def crear_mapa_poligonos(df_viajes,
bins = [df_etapas[var_fex].min()-1] + \
mapclassify.FisherJenks(
df_etapas[var_fex], k=k_jenks-3).bins.tolist()
+ except ValueError:
+ bins = [df_etapas[var_fex].min()-1] + \
+ mapclassify.FisherJenks(
+ df_etapas[var_fex], k=1).bins.tolist()
range_bins = range(0, len(bins)-1)
bins_labels = [
@@ -77,13 +81,21 @@ def crear_mapa_poligonos(df_viajes,
line_w = 0.5
if len(df_viajes) > 0:
try:
- bins = [df_viajes[var_fex].min()-1] + \
- mapclassify.FisherJenks(
- df_viajes[var_fex], k=k_jenks).bins.tolist()
+ # Intentar clasificar con k clases
+ bins = [df_viajes[var_fex].min() - 1] + \
+ mapclassify.FisherJenks(df_viajes[var_fex], k=k_jenks).bins.tolist()
except ValueError:
- bins = [df_viajes[var_fex].min()-1] + \
- mapclassify.FisherJenks(
- df_viajes[var_fex], k=k_jenks-2).bins.tolist()
+ # Si falla, reducir k dinámicamente
+ while k_jenks > 1:
+ try:
+ bins = [df_viajes[var_fex].min() - 1] + \
+ mapclassify.FisherJenks(df_viajes[var_fex], k=k_jenks - 1).bins.tolist()
+ break
+ except ValueError:
+ k_jenks -= 1
+ else:
+ # Si no se puede crear ni una categoría, asignar un único bin
+ bins = [df_viajes[var_fex].min() - 1, df_viajes[var_fex].max()]
range_bins = range(0, len(bins)-1)
bins_labels = [
@@ -177,7 +189,7 @@ def crear_mapa_poligonos(df_viajes,
name=poly.id.values[0],
style_function=lambda feature: {
'fillColor': 'grey',
- 'color': 'black',
+ 'color': 'white',
'weight': 2,
'fillOpacity': .5,
@@ -361,7 +373,8 @@ def hay_cambios_en_filtros(current, last):
desc_etapas = False
zonas_values_all = ['Todos'] + zonas_values[zonas_values.zona == desc_zona].Nombre.unique().tolist()
- desc_zonas_values = col1.selectbox('Filtro', options=zonas_values_all)
+ desc_zonas_values1 = col1.selectbox('Filtro 1', options=zonas_values_all, key='filtro1')
+ desc_zonas_values2 = col1.selectbox('Filtro 2', options=zonas_values_all, key='filtro2')
desc_origenes = col1.checkbox(
':blue[Origenes]', value=False)
@@ -370,7 +383,7 @@ def hay_cambios_en_filtros(current, last):
':orange[Destinos]', value=False)
desc_zonif = col1.checkbox(
- 'Mostrar zonificación', value=False)
+ 'Mostrar zonificación', value=True)
if desc_zonif:
st.session_state.zonif = zonificaciones[zonificaciones.zona == desc_zona]
else:
@@ -401,7 +414,8 @@ def hay_cambios_en_filtros(current, last):
'distancia': None if distancia == 'Todas' else distancia,
'coincidencias': None if desc_cuenca == False else True,
'id_polygon': st.session_state.desc_poly,
- 'desc_zonas_values': None if desc_zonas_values == 'Todos' else desc_zonas_values,
+ 'desc_zonas_values1': None if desc_zonas_values1 == 'Todos' else desc_zonas_values1,
+ 'desc_zonas_values2': None if desc_zonas_values2 == 'Todos' else desc_zonas_values2,
}
current_options = { 'desc_etapas': desc_etapas,
'desc_viajes': desc_viajes,
@@ -420,23 +434,31 @@ def hay_cambios_en_filtros(current, last):
if hay_cambios_en_filtros(current_filters, st.session_state.last_filters):
query = ""
- conditions = " AND ".join(f"{key} = '{value}'" for key, value in current_filters.items() if (value is not None)&(key != 'desc_zonas_values'))
+ conditions = " AND ".join(f"{key} = '{value}'" for key, value in current_filters.items() if (value is not None)&(key != 'desc_zonas_values1')&(key != 'desc_zonas_values2'))
if conditions:
query += f" WHERE {conditions}"
- conditions_etapas = ''
- conditions_matrices = ''
- if desc_zonas_values != 'Todos':
- conditions_etapas = f" AND (inicio_norm = '{desc_zonas_values}' OR transfer1_norm = '{desc_zonas_values}' OR transfer2_norm = '{desc_zonas_values}' OR fin_norm = '{desc_zonas_values}')"
- conditions_matrices = f" AND (inicio = '{desc_zonas_values}' OR fin = '{desc_zonas_values}')"
- query_etapas = query + conditions_etapas
- query_matrices = query + conditions_matrices
+ conditions_etapas1 = ''
+ conditions_matrices1 = ''
+ if desc_zonas_values1 != 'Todos':
+ conditions_etapas1 = f" AND (inicio_norm = '{desc_zonas_values1}' OR transfer1_norm = '{desc_zonas_values1}' OR transfer2_norm = '{desc_zonas_values1}' OR fin_norm = '{desc_zonas_values1}')"
+ conditions_matrices1 = f" AND (inicio = '{desc_zonas_values1}' OR fin = '{desc_zonas_values1}')"
+
+
+ conditions_etapas2 = ''
+ conditions_matrices2 = ''
+ if desc_zonas_values2 != 'Todos':
+ conditions_etapas2 = f" AND (inicio_norm = '{desc_zonas_values2}' OR transfer1_norm = '{desc_zonas_values2}' OR transfer2_norm = '{desc_zonas_values2}' OR fin_norm = '{desc_zonas_values2}')"
+ conditions_matrices2 = f" AND (inicio = '{desc_zonas_values2}' OR fin = '{desc_zonas_values2}')"
+
+ query_etapas = query + conditions_etapas1 + conditions_etapas2
+ query_matrices = query + conditions_matrices1 + conditions_matrices2
+
st.session_state.etapas_ = levanto_tabla_sql_local('poly_etapas', tabla_tipo='dash', query=f"SELECT * FROM poly_etapas{query_etapas}")
st.session_state.matrices_ = levanto_tabla_sql_local('poly_matrices', tabla_tipo='dash', query=f"SELECT * FROM poly_matrices{query_matrices}")
-
if len(st.session_state.etapas_)==0:
col2.write('No hay datos para mostrar')
else:
diff --git "a/urbantrips/dashboard/pages/5_An\303\241lisis de zonas.py" "b/urbantrips/dashboard/pages/5_An\303\241lisis de zonas.py"
index 18f6c69..4d50fad 100644
--- "a/urbantrips/dashboard/pages/5_An\303\241lisis de zonas.py"
+++ "b/urbantrips/dashboard/pages/5_An\303\241lisis de zonas.py"
@@ -10,7 +10,7 @@
from folium import plugins
from shapely import wkt
from dash_utils import (
- iniciar_conexion_db, get_logo, bring_latlon
+ iniciar_conexion_db, get_logo, bring_latlon, get_h3_indices_in_geometry
)
from streamlit_folium import folium_static
pd.options.display.float_format = '{:,.0f}'.format
@@ -48,11 +48,7 @@ def traigo_mes_dia():
tipo_dia = mes_dia.tipo_dia.values.tolist()
return mes, tipo_dia
-# Convert geometry to H3 indices
-def get_h3_indices_in_geometry(geometry, resolution):
- geojson = mapping(geometry)
- h3_indices = list(h3.polyfill(geojson, resolution, geo_json_conformant=True))
- return h3_indices
+
# Convert H3 indices to GeoDataFrame
def h3_indices_to_gdf(h3_indices):
@@ -66,7 +62,6 @@ def h3_indices_to_gdf(h3_indices):
st.session_state['zona_2'] = []
def main():
-
st.set_page_config(layout="wide")
logo = get_logo()
@@ -221,7 +216,9 @@ def main():
col5.dataframe(modos_v2.set_index('Modo'), height=400, width=300)
with st.expander('Viajes entre zonas', expanded=True):
- col1, col2, col3, col4 = st.columns([1, 2, 2, 3])
+ col1, col2, col3, col4 = st.columns([1, 2, 2, 3])
+
+
if len(zona1) > 0 and len(zona2) > 0:
h3_values = ", ".join(f"'{item}'" for item in zona1 + zona2)
@@ -230,6 +227,7 @@ def main():
etapas = levanto_tabla_sql_local('etapas_agregadas', tabla_tipo='dash', query=query)
if len(etapas) > 0:
+
etapas['Zona_1'] = ''
etapas['Zona_2'] = ''
@@ -240,16 +238,15 @@ def main():
etapas = etapas[(etapas.Zona_1 != '') & (etapas.Zona_2 != '') & (etapas.Zona_1 != etapas.Zona_2)]
etapas = etapas.fillna('')
-
- zonasod_e = etapas.groupby(['Zona_1', 'Zona_2'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Etapas'})
+
+
+ zonasod_e = etapas.groupby(['Zona_1', 'Zona_2'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Etapas'}).round(0)
modos_e = etapas.groupby(['modo', 'nombre_linea'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Etapas',
'nombre_linea': 'Línea',
- 'modo': 'Modo'})
-
- col2.write(zonasod_e)
-
+ 'modo': 'Modo'}).round(0)
+
# Calculate the total and append as a new row
total_rowe = pd.DataFrame({
'Modo': ['Total'],
@@ -259,10 +256,18 @@ def main():
modos_e = pd.concat([modos_e, total_rowe], ignore_index=True)
modos_e['Etapas'] = modos_e['Etapas'].round()
+
+
+ zonasod_e['Zonas'] = zonasod_e['Zona_1'] + ' - ' + zonasod_e['Zona_2']
+ zonasod_e = zonasod_e[['Zonas', 'Etapas']]
+ zonasod_e['Etapas'] = zonasod_e['Etapas'].apply(lambda x: f"{int(x):,}")
+
- col2.write('Etapas')
- col2.markdown(zonasod_e.to_html(index=False), unsafe_allow_html=True)
- col2.dataframe(modos_e.set_index('Modo'), height=500, width=400)
+ col2.write('Etapas')
+ if len(zonasod_e) > 0:
+ col2.dataframe(zonasod_e.set_index('Zonas'), height=100, width=300)
+ else:
+ col2.write('No hay datos para mostrar')
## Viajes
@@ -279,8 +284,10 @@ def main():
viajes = viajes[(viajes.Zona_1 != '') & (viajes.Zona_2 != '') & (viajes.Zona_1 != viajes.Zona_2)]
zonasod_v = viajes.groupby(['Zona_1', 'Zona_2'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Viajes'})
-
-
+ zonasod_v['Zonas'] = zonasod_v['Zona_1'] + ' - ' + zonasod_v['Zona_2']
+ zonasod_v = zonasod_v[['Zonas', 'Viajes']]
+ zonasod_v['Viajes'] = zonasod_v['Viajes'].apply(lambda x: f"{int(x):,}")
+
modos_v = viajes.groupby(['modo'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Viajes',
'modo': 'Modo'})
@@ -292,11 +299,15 @@ def main():
})
modos_v = pd.concat([modos_v, total_row], ignore_index=True)
- col3.write('Viajes')
- col3.markdown(zonasod_v.to_html(index=False), unsafe_allow_html=True)
+ col3.write('Viajes')
+ if len(zonasod_v):
+ col3.dataframe(zonasod_v.set_index('Zonas'), height=100, width=300)
+ else:
+ col3.write('No hay datos para mostrar')
+
modos_v['Viajes'] = modos_v['Viajes'].round()
- # col3.markdown(modos_v.to_html(index=False), unsafe_allow_html=True)
- col3.dataframe(modos_v.set_index('Modo'), height=500, width=300)
+ col2.write('Modal')
+ col2.dataframe(modos_v.set_index('Modo'), height=200, width=300)
## Mapa
@@ -319,31 +330,30 @@ def zona_to_geometry(h3_list):
with col4:
output2 = st_folium(m2, width=700, height=700)
- with st.expander('Viajes con transferencias', expanded=False):
- col1, col2 = st.columns([1, 3])
- ## Transferencias
- h3_values = ", ".join(f"'{item}'" for item in zona1 + zona2)
- query = f"SELECT * FROM transferencias_agregadas WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND (h3_o IN ({h3_values}) OR h3_d IN ({h3_values}));"
- transferencias = levanto_tabla_sql_local('transferencias_agregadas', tabla_tipo='dash', query=query)
-
- if len(transferencias) > 0:
-
- transferencias['Zona_1'] = ''
- transferencias['Zona_2'] = ''
- transferencias.loc[transferencias.h3_o.isin(zona1), 'Zona_1'] = 'Zona 1'
- transferencias.loc[transferencias.h3_o.isin(zona2), 'Zona_1'] = 'Zona 2'
- transferencias.loc[transferencias.h3_d.isin(zona1), 'Zona_2'] = 'Zona 1'
- transferencias.loc[transferencias.h3_d.isin(zona2), 'Zona_2'] = 'Zona 2'
- transferencias = transferencias[(transferencias.Zona_1 != '') & (transferencias.Zona_2 != '') & (transferencias.Zona_1 != transferencias.Zona_2)]
-
- transferencias = transferencias.fillna('')
-
- transferencias = transferencias.groupby(['modo',
- 'seq_lineas'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Viajes',
- 'modo':'Modo', 'seq_lineas':'Líneas'}).sort_values('Viajes', ascending=False)
- transferencias['Viajes'] = transferencias['Viajes'].astype(int)
+ ## Transferencias
+ h3_values = ", ".join(f"'{item}'" for item in zona1 + zona2)
+ query = f"SELECT * FROM transferencias_agregadas WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND (h3_o IN ({h3_values}) OR h3_d IN ({h3_values}));"
+ transferencias = levanto_tabla_sql_local('transferencias_agregadas', tabla_tipo='dash', query=query)
- col2.dataframe(transferencias.set_index('Modo'), height=500, width=500)
+ if len(transferencias) > 0:
+
+ transferencias['Zona_1'] = ''
+ transferencias['Zona_2'] = ''
+ transferencias.loc[transferencias.h3_o.isin(zona1), 'Zona_1'] = 'Zona 1'
+ transferencias.loc[transferencias.h3_o.isin(zona2), 'Zona_1'] = 'Zona 2'
+ transferencias.loc[transferencias.h3_d.isin(zona1), 'Zona_2'] = 'Zona 1'
+ transferencias.loc[transferencias.h3_d.isin(zona2), 'Zona_2'] = 'Zona 2'
+ transferencias = transferencias[(transferencias.Zona_1 != '') & (transferencias.Zona_2 != '') & (transferencias.Zona_1 != transferencias.Zona_2)]
+
+ transferencias = transferencias.fillna('')
+
+ transferencias = transferencias.groupby(['modo',
+ 'seq_lineas'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Viajes',
+ 'modo':'Modo', 'seq_lineas':'Líneas'}).sort_values('Viajes', ascending=False)
+ transferencias['Viajes'] = transferencias['Viajes'].astype(int)
+
+ col3.write('Viajes por líneas')
+ col3.dataframe(transferencias.set_index('Modo'), height=500, width=500)
if __name__ == '__main__':
diff --git "a/urbantrips/dashboard/pages/6_Comparaci\303\263n de l\303\255neas.py" "b/urbantrips/dashboard/pages/6_Comparaci\303\263n de l\303\255neas.py"
new file mode 100644
index 0000000..8e41fdc
--- /dev/null
+++ "b/urbantrips/dashboard/pages/6_Comparaci\303\263n de l\303\255neas.py"
@@ -0,0 +1,306 @@
+import pandas as pd
+import streamlit as st
+from streamlit_folium import st_folium
+from streamlit_folium import folium_static
+from dash_utils import (
+ get_logo)
+try:
+ from urbantrips.utils.utils import iniciar_conexion_db
+ from urbantrips.utils import utils
+ from urbantrips.kpi import overlapping as ovl
+ from urbantrips.viz import overlapping as ovl_viz
+except ImportError as e:
+ st.error(f"Falta una librería requerida: {e}. Algunas funcionalidades no estarán disponibles. \nSe requiere full acceso a Urbantrips para correr esta página")
+ st.stop()
+
+
+# --- Función para levantar tablas SQL y almacenar en session_state ---
+def cargar_tabla_sql(tabla_sql, tipo_conexion="dash", query=""):
+ if f"{tabla_sql}_{tipo_conexion}" not in st.session_state:
+ conn = iniciar_conexion_db(tipo=tipo_conexion)
+ try:
+ query = query or f"SELECT * FROM {tabla_sql}"
+ tabla = pd.read_sql_query(query, conn)
+ st.session_state[f"{tabla_sql}_{tipo_conexion}"] = tabla
+ except Exception:
+ st.error(f"{tabla_sql} no existe")
+ st.session_state[f"{tabla_sql}_{tipo_conexion}"] = pd.DataFrame()
+ finally:
+ conn.close()
+ return st.session_state[f"{tabla_sql}_{tipo_conexion}"]
+
+def seleccionar_linea(nombre_columna, key_input, key_select, branch_key, conn_insumos):
+ texto_a_buscar = st.text_input(
+ f"Ingrese el texto a buscar para {nombre_columna}", key=key_input
+ )
+ if texto_a_buscar:
+ if f"df_filtrado_{texto_a_buscar}_{branch_key}" not in st.session_state:
+ st.session_state[f"df_filtrado_{texto_a_buscar}_{branch_key}"] = (
+ metadata_lineas[
+ metadata_lineas.apply(
+ lambda row: row.astype(str)
+ .str.contains(texto_a_buscar, case=False, na=False)
+ .any(),
+ axis=1,
+ )
+ ]
+ )
+ df_filtrado = st.session_state[f"df_filtrado_{texto_a_buscar}_{branch_key}"]
+
+ if not df_filtrado.empty:
+ opciones = df_filtrado.apply(
+ lambda row: f"{row['nombre_linea']}", axis=1
+ ).tolist()
+ seleccion_texto = st.selectbox(
+ f"Seleccione una línea de colectivo para {nombre_columna}",
+ opciones,
+ key=key_select,
+ )
+ st.session_state[f"seleccion_{branch_key}"] = df_filtrado.iloc[
+ opciones.index(seleccion_texto)
+ ]
+
+ if use_branches:
+ if (
+ f"metadata_branches_{st.session_state[f'seleccion_{branch_key}']['id_linea']}"
+ not in st.session_state
+ ):
+ st.session_state[
+ f"metadata_branches_{st.session_state[f'seleccion_{branch_key}']['id_linea']}"
+ ] = pd.read_sql(
+ f"SELECT * FROM metadata_ramales WHERE id_linea = {st.session_state[f'seleccion_{branch_key}']['id_linea']}",
+ conn_insumos,
+ )
+ metadata_branches = st.session_state[
+ f"metadata_branches_{st.session_state[f'seleccion_{branch_key}']['id_linea']}"
+ ]
+
+ selected_branch = st.selectbox(
+ "Seleccione un ramal",
+ metadata_branches.nombre_ramal.unique(),
+ key=f"branch_{branch_key}",
+ )
+ st.session_state[f"seleccion_{branch_key}"]["branch_id"] = (
+ metadata_branches.loc[
+ metadata_branches.nombre_ramal == selected_branch, "id_ramal"
+ ].values[0]
+ )
+ st.session_state[f"seleccion_{branch_key}"][
+ "branch_name"
+ ] = selected_branch
+ else:
+ st.warning("No se encontró ninguna coincidencia.")
+
+
+st.set_page_config(layout="wide")
+logo = get_logo()
+st.image(logo)
+
+try:
+ # --- Cargar configuraciones y conexiones en session_state ---
+ if "configs" not in st.session_state:
+ st.session_state.configs = utils.leer_configs_generales()
+
+ configs = st.session_state.configs
+ h3_legs_res = configs["resolucion_h3"]
+ alias = configs["alias_db_data"]
+ use_branches = configs["lineas_contienen_ramales"]
+ metadata_lineas = cargar_tabla_sql("metadata_lineas", "insumos")[
+ ["id_linea", "nombre_linea"]
+ ]
+ conn_insumos = iniciar_conexion_db(tipo="insumos")
+except ValueError as e:
+ st.error(f"Falta una base de datos requerida: {e}. \nSe requiere full acceso a Urbantrips para correr esta página")
+ st.stop()
+
+
+# --- Inicializar variables en session_state ---
+for var in [
+ "id_linea_1",
+ "nombre_linea_1",
+ "branch_id_1",
+ "branch_name_1",
+ "id_linea_2",
+ "nombre_linea_2",
+ "branch_id_2",
+ "branch_name_2",
+]:
+ if var not in st.session_state:
+ st.session_state[var] = None
+
+# --- Selección de líneas y ramales con almacenamiento en session_state ---
+with st.expander("Seleccionar líneas", expanded=True):
+ col1, col2, col3 = st.columns([1, 3, 3])
+
+ with col1:
+ h3_res_comp = st.slider(
+ "Resolución H3", min_value=7, max_value=h3_legs_res, value=h3_legs_res
+ )
+
+ if st.button("Comparar líneas"):
+ for i in [1, 2]:
+ if f"seleccion_{i}" in st.session_state:
+ st.session_state[f"id_linea_{i}"] = st.session_state[
+ f"seleccion_{i}"
+ ]["id_linea"]
+ st.session_state[f"nombre_linea_{i}"] = st.session_state[
+ f"seleccion_{i}"
+ ]["nombre_linea"]
+ st.session_state[f"branch_id_{i}"] = st.session_state[
+ f"seleccion_{i}"
+ ].get("branch_id")
+ st.session_state[f"branch_name_{i}"] = st.session_state[
+ f"seleccion_{i}"
+ ].get("branch_name")
+ st.write(
+ f"Línea {i} guardada:",
+ st.session_state[f"nombre_linea_{i}"],
+ "ramal",
+ (
+ st.session_state[f"branch_name_{i}"]
+ if st.session_state[f"branch_name_{i}"]
+ else "N/A"
+ ),
+ )
+ else:
+ st.write(
+ f"No hay ninguna línea seleccionada para guardar como Línea {i}."
+ )
+
+ with col2:
+ st.subheader("Línea base:")
+ seleccionar_linea("Línea base", "base_input", "base_select", "1", conn_insumos)
+ with col3:
+ st.subheader("Línea comparación:")
+ seleccionar_linea(
+ "Línea comparación", "comp_input", "comp_select", "2", conn_insumos
+ )
+
+# --- Comparación de líneas ---
+with st.expander("Comparación de líneas", expanded=True):
+ col1, col2 = st.columns([2, 2])
+
+ if st.session_state.id_linea_1 and st.session_state.id_linea_2:
+ if use_branches:
+ base_route_id, comp_route_id = int(st.session_state.branch_id_1), int(
+ st.session_state.branch_id_2
+ )
+ else:
+ base_route_id, comp_route_id = int(st.session_state.id_linea_1), int(
+ st.session_state.id_linea_2
+ )
+
+ # Evita cálculos repetidos si ya se han realizado para las mismas líneas
+ if (
+ f"overlapping_dict_{base_route_id}_{comp_route_id}_res{h3_res_comp}"
+ not in st.session_state
+ ):
+
+ overlapping_dict = ovl.compute_supply_overlapping(
+ "weekday",
+ base_route_id,
+ comp_route_id,
+ "branches" if use_branches else "lines",
+ h3_res_comp,
+ )
+ st.session_state[
+ f"overlapping_dict_{base_route_id}_{comp_route_id}_res{h3_res_comp}"
+ ] = overlapping_dict
+ st.session_state[f"supply_overlapping_{base_route_id}_{comp_route_id}"] = (
+ overlapping_dict["text_base_v_comp"]
+ )
+ st.session_state[f"supply_overlapping_{comp_route_id}_{base_route_id}"] = (
+ overlapping_dict["text_comp_v_base"]
+ )
+
+ overlapping_dict = st.session_state[
+ f"overlapping_dict_{base_route_id}_{comp_route_id}_res{h3_res_comp}"
+ ]
+
+ # Renderiza el primer mapa
+ f = ovl_viz.plot_interactive_supply_overlapping(overlapping_dict)
+ # Muestra la salida solo en col1
+ with col1:
+ if f is not None:
+ folium_static(f, width=800, height=600)
+ st.write(
+ st.session_state[
+ f"supply_overlapping_{base_route_id}_{comp_route_id}"
+ ]
+ )
+ st.write(
+ st.session_state[
+ f"supply_overlapping_{comp_route_id}_{base_route_id}"
+ ]
+ )
+ else:
+ st.error(overlapping_dict["text_base_v_comp"])
+
+ # Cálculo y visualización de la demanda, si no se ha realizado previamente
+ if (
+ f"base_demand_comp_demand_{base_route_id}_{comp_route_id}"
+ not in st.session_state
+ ):
+ base_gdf = overlapping_dict["base"]["h3"]
+ comp_gdf = overlapping_dict["comp"]["h3"]
+ if (base_gdf is not None) and (comp_gdf is not None):
+ demand_overlapping = ovl.compute_demand_overlapping(
+ st.session_state.id_linea_1,
+ st.session_state.id_linea_2,
+ "weekday",
+ base_route_id,
+ comp_route_id,
+ base_gdf,
+ comp_gdf,
+ )
+ st.session_state[
+ f"base_demand_comp_demand_{base_route_id}_{comp_route_id}"
+ ] = demand_overlapping
+
+ st.session_state[
+ f"demand_overlapping_{base_route_id}_{comp_route_id}"
+ ] = demand_overlapping["base"]["output_text"]
+ st.session_state[
+ f"demand_overlapping_{comp_route_id}_{base_route_id}"
+ ] = demand_overlapping["comp"]["output_text"]
+ else:
+ st.session_state[
+ f"base_demand_comp_demand_{base_route_id}_{comp_route_id}"
+ ] = None
+
+ demand_overlapping = st.session_state[
+ f"base_demand_comp_demand_{base_route_id}_{comp_route_id}"
+ ]
+
+ # Renderiza el segundo mapa y muestra el texto justo después del mapa en col2
+ if demand_overlapping is not None:
+ base_demand = demand_overlapping["base"]["data"]
+ comp_demand = demand_overlapping["comp"]["data"]
+
+ demand_overlapping_fig = ovl_viz.plot_interactive_demand_overlapping(
+ base_demand, comp_demand, overlapping_dict
+ )
+ fig = demand_overlapping_fig["fig"]
+ base_gdf_to_db = demand_overlapping_fig["base_gdf_to_db"]
+ comp_gdf_to_db = demand_overlapping_fig["comp_gdf_to_db"]
+
+ with col2:
+ folium_static(fig, width=800, height=600)
+ st.write(
+ st.session_state[
+ f"demand_overlapping_{base_route_id}_{comp_route_id}"
+ ]
+ ) # Muestra la segunda salida justo después del mapa
+ st.write(
+ st.session_state[
+ f"demand_overlapping_{comp_route_id}_{base_route_id}"
+ ]
+ ) # Muestra la segunda salida justo después del mapa
+
+
+with st.expander("Exportar datos", expanded=True):
+ col1_db, col2_db = st.columns([2, 2])
+ if col1_db.checkbox("Ver datos recorrido base"):
+ col1_db.write(base_gdf_to_db)
+ if col2_db.checkbox("Ver datos recorrido comparacion"):
+ col2_db.write(comp_gdf_to_db)
diff --git a/urbantrips/lineas_deseo/lineas_deseo.py b/urbantrips/lineas_deseo/lineas_deseo.py
index 04599e8..398ed9e 100644
--- a/urbantrips/lineas_deseo/lineas_deseo.py
+++ b/urbantrips/lineas_deseo/lineas_deseo.py
@@ -791,6 +791,7 @@ def crea_socio_indicadores(etapas, viajes):
return socio_indicadores
def preparo_etapas_agregadas(etapas, viajes):
+
e_agg = etapas.groupby(['dia', 'mes', 'tipo_dia', 'h3_o', 'h3_d', 'modo', 'id_linea'], as_index=False).factor_expansion_linea.sum()
e_agg = e_agg.groupby(['mes', 'tipo_dia', 'h3_o', 'h3_d', 'modo', 'id_linea'], as_index=False).factor_expansion_linea.mean()
e_agg = e_agg[e_agg.h3_o!=e_agg.h3_d]
@@ -802,19 +803,38 @@ def preparo_etapas_agregadas(etapas, viajes):
v_agg = v_agg[v_agg.h3_o!=v_agg.h3_d]
etapas['etapas_max'] = etapas.groupby(['dia', 'id_tarjeta', 'id_viaje']).id_etapa.transform('max')
- transfers = etapas.loc[(etapas.etapas_max>1), ['dia', 'id_tarjeta', 'id_viaje', 'id_etapa', 'etapas_max', 'id_linea', 'h3_o', 'h3_d', 'factor_expansion_linea']]
+
+ transfers = etapas.loc[:, ['dia', 'id_tarjeta', 'id_viaje', 'id_etapa', 'etapas_max', 'id_linea', 'h3_o', 'h3_d', 'factor_expansion_linea']] #(etapas.etapas_max>1)
transfers = transfers.merge(lineas[['id_linea', 'nombre_linea']], how='left')
transfers = transfers.pivot(index=['dia', 'id_tarjeta', 'id_viaje'], columns='id_etapa', values='nombre_linea').reset_index().fillna('')
transfers['seq_lineas'] = ''
for i in range(1, etapas.etapas_max.max()+1):
transfers['seq_lineas'] += transfers[i] + ' -- '
transfers['seq_lineas'] = transfers['seq_lineas'].str.replace(' -- -- ', '')
-
- transfers['seq_lineas'] = transfers.seq_lineas.str[:-4]
+
+ transfers.loc[transfers.seq_lineas.str[-4:] == ' -- ', 'seq_lineas'] = transfers.loc[transfers.seq_lineas.str[-4:] == ' -- ', 'seq_lineas'].str[:-4]
transfers = viajes.merge(transfers[['dia', 'id_tarjeta', 'id_viaje', 'seq_lineas']])
transfers = transfers.groupby(['dia', 'mes', 'tipo_dia', 'h3_o', 'h3_d', 'modo', 'seq_lineas'], as_index=False).factor_expansion_linea.sum()
transfers = transfers.groupby(['mes', 'tipo_dia', 'h3_o', 'h3_d', 'modo', 'seq_lineas'], as_index=False).factor_expansion_linea.mean()
+ zonas = levanto_tabla_sql('zonas', 'insumos')
+ zonas_cols = zonas.columns.tolist()
+ zonas_cols = [item for item in zonas_cols if item not in ['fex', 'latitud', 'longitud']]
+ zonas = zonas[zonas_cols]
+
+ zonas_cols_o = [f'{item}_o' for item in zonas_cols]
+ zonas_cols_d = [f'{item}_d' for item in zonas_cols]
+
+ zonas.columns = zonas_cols_o
+ e_agg = e_agg.merge(zonas, how='left')
+ v_agg = v_agg.merge(zonas, how='left')
+ transfers = transfers.merge(zonas, how='left')
+
+ zonas.columns = zonas_cols_d
+ e_agg = e_agg.merge(zonas, how='left')
+ v_agg = v_agg.merge(zonas, how='left')
+ transfers = transfers.merge(zonas, how='left')
+
return e_agg, v_agg, transfers
def preparo_lineas_deseo(etapas_selec, viajes_selec, polygons_h3='', poligonos='', res=6):
@@ -1460,7 +1480,19 @@ def preparo_lineas_deseo(etapas_selec, viajes_selec, polygons_h3='', poligonos='
### return etapas_agrupadas_zon, viajes_matrices, zonificaciones
-
+def guarda_particion_modal(etapas):
+ df_dummies = pd.get_dummies(etapas.modo)
+ etapas = pd.concat([etapas, df_dummies], axis=1)
+ cols_dummies = df_dummies.columns.tolist()
+
+ etapas_modos = etapas.groupby(['mes', 'tipo_dia', 'genero', 'id_tarjeta', 'id_viaje'], as_index=False).factor_expansion_linea.mean().merge(
+ etapas.groupby(['dia', 'id_tarjeta', 'id_viaje'], as_index=False)[cols_dummies].sum(), how='left')
+
+ cols = ['mes', 'tipo_dia', 'genero', ]+cols_dummies
+ etapas_modos = etapas_modos.groupby(cols, as_index=False).factor_expansion_linea.sum().copy()
+ for i in cols_dummies:
+ etapas_modos = etapas_modos.rename(columns={i:i.capitalize()})
+ guardar_tabla_sql(etapas_modos, 'datos_particion_modal', filtros={'mes': etapas_modos.mes.unique().tolist()})
def proceso_poligonos(check_configs=True):
@@ -1490,17 +1522,6 @@ def proceso_poligonos(check_configs=True):
indicadores = construyo_indicadores(viajes_selec, poligonos=True)
-
- ## guardar_tabla_sql(etapas_agrupadas,
- ## 'poly_etapas',
- ## 'dash',
- ## {'mes': etapas_agrupadas.mes.unique().tolist()})
-
- ## guardar_tabla_sql(viajes_matrices,
- ## 'poly_matrices',
- ## 'dash',
- ## {'mes': viajes_matrices.mes.unique().tolist()})
-
guardar_tabla_sql(indicadores,
'poly_indicadores',
'dash',
@@ -1529,15 +1550,7 @@ def proceso_lineas_deseo(check_configs=False):
print('Guardo datos para dashboard')
- ## guardar_tabla_sql(etapas_agrupadas,
- ## 'agg_etapas',
- ## 'dash',
- ## {'mes': etapas_agrupadas.mes.unique().tolist()})
-
- ## guardar_tabla_sql(viajes_matrices,
- ## 'agg_matrices',
- ## 'dash',
- ## {'mes': viajes_matrices.mes.unique().tolist()})
+ guarda_particion_modal(etapas)
guardar_tabla_sql(indicadores,
'agg_indicadores',
@@ -1566,3 +1579,4 @@ def proceso_lineas_deseo(check_configs=False):
{'mes': v_agg.mes.unique().tolist()})
imprimo_matrices_od()
+
diff --git a/urbantrips/viz/viz.py b/urbantrips/viz/viz.py
index 823dade..5151639 100755
--- a/urbantrips/viz/viz.py
+++ b/urbantrips/viz/viz.py
@@ -2476,47 +2476,47 @@ def save_zones():
conn_dash.close()
-def particion_modal(viajes_dia, etapas_dia, tipo_dia, desc_dia):
-
- particion_viajes = (
- viajes_dia.groupby("modo", as_index=False).factor_expansion_linea.sum().round()
- )
- particion_viajes["modal"] = (
- particion_viajes["factor_expansion_linea"]
- / viajes_dia.factor_expansion_linea.sum()
- * 100
- ).round()
- particion_viajes = particion_viajes.sort_values("modal", ascending=False).drop(
- ["factor_expansion_linea"], axis=1
- )
- particion_viajes["tipo"] = "viajes"
- particion_viajes["tipo_dia"] = tipo_dia
- particion_viajes["desc_dia"] = desc_dia
- particion_etapas = (
- etapas_dia.groupby("modo", as_index=False).factor_expansion_linea.sum().round()
- )
-
- particion_etapas["modal"] = (
- particion_etapas["factor_expansion_linea"]
- / etapas_dia.factor_expansion_linea.sum()
- * 100
- ).round()
- particion_etapas = particion_etapas.sort_values("modal", ascending=False).drop(
- ["factor_expansion_linea"], axis=1
- )
- particion_etapas["tipo"] = "etapas"
- particion_etapas["desc_dia"] = desc_dia
- particion_etapas["tipo_dia"] = tipo_dia
- particion = pd.concat([particion_viajes, particion_etapas], ignore_index=True)
-
- conn_dash = iniciar_conexion_db(tipo="dash")
-
- query = f'DELETE FROM particion_modal WHERE desc_dia = "{desc_dia}" & tipo_dia = "{tipo_dia}"'
- conn_dash.execute(query)
- conn_dash.commit()
- particion["modo"] = particion.modo.str.capitalize()
- particion.to_sql("particion_modal", conn_dash, if_exists="append", index=False)
- conn_dash.close()
+# def particion_modal(viajes_dia, etapas_dia, tipo_dia, desc_dia):
+
+# particion_viajes = (
+# viajes_dia.groupby("modo", as_index=False).factor_expansion_linea.sum().round()
+# )
+# particion_viajes["modal"] = (
+# particion_viajes["factor_expansion_linea"]
+# / viajes_dia.factor_expansion_linea.sum()
+# * 100
+# ).round()
+# particion_viajes = particion_viajes.sort_values("modal", ascending=False).drop(
+# ["factor_expansion_linea"], axis=1
+# )
+# particion_viajes["tipo"] = "viajes"
+# particion_viajes["tipo_dia"] = tipo_dia
+# particion_viajes["desc_dia"] = desc_dia
+# particion_etapas = (
+# etapas_dia.groupby("modo", as_index=False).factor_expansion_linea.sum().round()
+# )
+
+# particion_etapas["modal"] = (
+# particion_etapas["factor_expansion_linea"]
+# / etapas_dia.factor_expansion_linea.sum()
+# * 100
+# ).round()
+# particion_etapas = particion_etapas.sort_values("modal", ascending=False).drop(
+# ["factor_expansion_linea"], axis=1
+# )
+# particion_etapas["tipo"] = "etapas"
+# particion_etapas["desc_dia"] = desc_dia
+# particion_etapas["tipo_dia"] = tipo_dia
+# particion = pd.concat([particion_viajes, particion_etapas], ignore_index=True)
+
+# conn_dash = iniciar_conexion_db(tipo="dash")
+
+# query = f'DELETE FROM particion_modal WHERE desc_dia = "{desc_dia}" & tipo_dia = "{tipo_dia}"'
+# conn_dash.execute(query)
+# conn_dash.commit()
+# particion["modo"] = particion.modo.str.capitalize()
+# particion.to_sql("particion_modal", conn_dash, if_exists="append", index=False)
+# conn_dash.close()
def plot_dispatched_services_wrapper():
@@ -3202,7 +3202,7 @@ def create_visualizations():
# )
# partición modal
- particion_modal(viajes_dia, etapas_dia, tipo_dia=i.tipo_dia, desc_dia=desc_dia)
+ # particion_modal(viajes_dia, etapas_dia, tipo_dia=i.tipo_dia, desc_dia=desc_dia)
print("Imprimiendo gráficos")
titulo = f"Cantidad de viajes en transporte público {desc_dia}"