diff --git a/.gitignore b/.gitignore index 459c006..3913445 100644 --- a/.gitignore +++ b/.gitignore @@ -145,3 +145,5 @@ dmypy.json .github/desktop.ini *.ini +urbantrips/lineas_deseo/lineas_deseo-Copy1.py +configs/configuraciones_generales.yaml diff --git a/configs/configuraciones_generales.yaml b/configs/configuraciones_generales.yaml index ab28df8..ccaf72b 100755 --- a/configs/configuraciones_generales.yaml +++ b/configs/configuraciones_generales.yaml @@ -1,86 +1,91 @@ # Archivo de configuración para urbantrips # Bases de datos -nombre_archivo_trx: "transacciones_amba_test.csv" # Especificar el archivo con las transacciones a consumir -alias_db_data: "amba_test" # nombre del sqlite donde se guardan los datos procesados -alias_db_insumos: "amba_test" # nombre del sqlite donde se guardan los insumos generales -alias_db_dashboard: "amba_test" # nombre del sqlite donde se guardan los datos a mostrar en el dashboard +nombre_archivo_trx: "UT_AMBA-2024-5-14-AP_m40.csv" # Especificar el archivo con las transacciones a consumir +alias_db_data: "amba_2024_m40" # nombre del sqlite donde se guardan los datos procesados +alias_db_insumos: "amba_2024_m40" # nombre del sqlite donde se guardan los insumos generales +alias_db_dashboard: "amba_2024_m40" # nombre del sqlite donde se guardan los datos a mostrar en el dashboard # Nombre de columnas en el archivo de transacciones nombres_variables_trx: id_trx: "id" # columna con id único del archivo de transacciones - fecha_trx: "fecha" # columna con fecha de la transacción - id_tarjeta_trx: "id_tarjeta" # columna con id de la tarjeta + fecha_trx: "fecha_trx" # columna con fecha de la transacción + id_tarjeta_trx: "id_tarjeta_trx" # columna con id de la tarjeta modo_trx: "modo" # columna con modo de transporte - hora_trx: "hora" # columna con hora de la transacción + hora_trx: # columna con hora de la transacción id_linea_trx: "id_linea" # columna con el id de la línea id_ramal_trx: "id_ramal" # columna con el ramal de la línea - interno_trx: "interno_bus" # columna con interno de la línea - orden_trx: "etapa_red_sube" # columna con el orden de la transacción (si falta hora/minuto en fecha_trx) - latitud_trx: "lat" # columna con la latitud de la transacción - longitud_trx: "lon" # columna con longitud de la transacción - factor_expansion: # columna con el factor de expansión + interno_trx: "interno" # columna con interno de la línea + orden_trx: # columna con el orden de la transacción (si falta hora/minuto en fecha_trx) + genero: "genero" # Indica el género asignado a la tarjeta + tarifa: "ats" # Indica el tipo de tarifa asignado a la transacción + latitud_trx: "latitude" # columna con la latitud de la transacción + longitud_trx: "longitude" # columna con longitud de la transacción + factor_expansion: "fex_linea" # columna con el factor de expansión # Parámetros de transacciones -ordenamiento_transacciones: "orden_trx" # especifica si ordena transacciones por fecha ("fecha_completa") o por variable orden_trx ("orden_trx") en la tabla nombres_variables_trx +ordenamiento_transacciones: "fecha_completa" # especifica si ordena transacciones por fecha ("fecha_completa") o por variable orden_trx ("orden_trx") en la tabla nombres_variables_trx ventana_viajes: 120 # ventana de tiempo para que una transacción sea de un mismo viaje (ej. 60 minutos) ventana_duplicado: 5 # ventana de tiempo si hay duplicado de transacción (ej. Viaje con acompañante) # Elimina transacciones inválidas de la tabla de transacciones tipo_trx_invalidas: tipo_trx_tren: [ # Lista con el contenido a eliminar de la variable seleccionada - "CHECK OUT SIN CHECKIN", - "CHECK OUT", + "COUT", + "COUTS", ] # Imputación de destino tolerancia_parada_destino: 2200 # Distancia para la validación de los destinos (metros) -imputar_destinos_min_distancia: False # Busca la parada que minimiza la distancia con respecto a la siguiente trancción +imputar_destinos_min_distancia: True # Busca la parada que minimiza la distancia con respecto a la siguiente trancción # Parámetros geográficos resolucion_h3: 8 # Resolución de los hexágonos -epsg_m: 9265 # Parámetros geográficos: crs +epsg_m: 5347 # Parámetros geográficos: crs -formato_fecha: "%d/%m/%Y" # Configuración fecha y hora -columna_hora: True +formato_fecha: "%d/%m/%Y %H:%M:%S" # Configuración fecha y hora +columna_hora: False geolocalizar_trx: False -nombre_archivo_gps: # Especificar el archivo con los datos gps de las líneas +nombre_archivo_gps: "UT_GPS-2024-5.csv" # Especificar el archivo con los datos gps de las líneas # Nombre de columnas en el archivo de GPS nombres_variables_gps: - id_gps: - id_linea_gps: - id_ramal_gps: - interno_gps: - fecha_gps: - latitud_gps: - longitud_gps: - velocity_gps: - servicios_gps: # Indica cuando se abre y cierra un servicio - distance_gps: + id_gps: "id" + id_linea_gps: "idlinea_gps" + id_ramal_gps: "idramal_gps" + interno_gps: "interno_gps" + fecha_gps: "fecha_gps" + latitud_gps: "lat_gps" + longitud_gps: "lon_gps" + velocity_gps: "vel_gps" + distance_gps: + servicios_gps: "serv_val" # Indica cuando se abre y cierra un servicio # Información para procesamiento de líneas -nombre_archivo_informacion_lineas: "lineas_amba_test.csv" # Archivo .csv con lineas, debe contener ("id_linea", "nombre_linea", "modo") +nombre_archivo_informacion_lineas: "UT_LINEAS-2024.csv" # Archivo .csv con lineas, debe contener ("id_linea", "nombre_linea", "modo") lineas_contienen_ramales: True # Especificar si las líneas de colectivo contienen ramales -nombre_archivo_paradas: "stops.csv" +nombre_archivo_paradas: "stops_amba_2023.csv" imprimir_lineas_principales: 5 # Imprimir las lineas principales - "All" imprime todas las líneas # Servicios GPS -utilizar_servicios_gps: False # Especifica si ve van a utilizar los servicios GPS -valor_inicio_servicio: # Valor de la variable que marca el inicio del servicio -valor_fin_servicio: # Valor de la variable que marca el fin del servicio +utilizar_servicios_gps: True # Especifica si ve van a utilizar los servicios GPS +valor_inicio_servicio: "INI" # Valor de la variable que marca el inicio del servicio +valor_fin_servicio: "FIN" # Valor de la variable que marca el fin del servicio modos: - autobus: "COL" - tren: "TRE" - metro: "SUB" + autobus: "COLE" + tren: "FFCC" + metro: "SUBTE" tranvia: brt: + cable: + lancha: + otros: # Capas geográficas con recorridos de líneas -recorridos_geojson: "recorridos_amba.geojson" # archivo geojson con el trazado de las líneas de transporte público +recorridos_geojson: "recorridos_amba_2023.geojson" # archivo geojson con el trazado de las líneas de transporte público filtro_latlong_bbox: minx: -59.3 @@ -90,12 +95,77 @@ filtro_latlong_bbox: # Zonificaciones zonificaciones: - geo1: - var1: + geo1: "zonas.geojson" + var1: "Zona" orden1: - geo2: - var2: - orden2: + geo2: "partidos.geojson" + var2: "Partido" + orden2: [ + "Comuna 1", + "Comuna 2", + "Comuna 3", + "Comuna 4", + "Comuna 5", + "Comuna 6", + "Comuna 7", + "Comuna 8", + "Comuna 9", + "Comuna 10", + "Comuna 11", + "Comuna 12", + "Comuna 13", + "Comuna 14", + "Comuna 15", + "Almirante Brown", + "Avellaneda", + "Berazategui", + "Berisso", + "Brandsen", + "Campana", + "Carmen de Areco", + "Cañuelas", + "Ensenada", + "Escobar", + "Esteban Echeverría", + "Exaltación de la Cruz", + "Ezeiza", + "Florencio Varela", + "General Las Heras", + "General Rodríguez", + "General San Martín", + "Hurlingham", + "Ituzaingó", + "José C. Paz", + "La Matanza", + "La Plata", + "Lanús", + "Lobos", + "Lomas de Zamora", + "Luján", + "Magdalena", + "Malvinas Argentinas", + "Marcos Paz", + "Mercedes", + "Merlo", + "Moreno", + "Morón", + "Navarro", + "Pilar", + "Presidente Perón", + "Punta Indio", + "Quilmes", + "San Andrés de Giles", + "San Antonio de Areco", + "San Fernando", + "San Isidro", + "San Miguel", + "San Vicente", + "Tigre", + "Tres de Febrero", + "Vicente López", + "Zárate", + ] + geo3: var3: orden3: @@ -106,5 +176,7 @@ zonificaciones: var5: orden5: -poligonos: # Especificar una capa geográfica de polígonos en formato .geojson. El archivo requiere las siguientes columnas: ['id', 'tipo', 'geometry']. 'id' es el id o nombre del polígono, tipo puede ser 'poligono' o 'cuenca'. -tiempos_viaje_estaciones: +poligonos: "poligonos.geojson" # Especificar una capa geográfica de polígonos en formato .geojson. El archivo requiere las siguientes columnas: ['id', 'tipo', 'geometry']. 'id' es el id o nombre del polígono, tipo puede ser 'poligono' o 'cuenca'. + +tiempos_viaje_estaciones: "travel_time_stations.csv" # Especificar una tabla de tiempo de viaje en minutos entre estaciones para modos sin gps + diff --git a/run_interactive_tools.py b/run_interactive_tools.py new file mode 100644 index 0000000..eb1738c --- /dev/null +++ b/run_interactive_tools.py @@ -0,0 +1,273 @@ +import pandas as pd +import streamlit as st +from streamlit_folium import st_folium +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 +from streamlit_folium import folium_static + +st.set_page_config(layout="wide") + + +# --- 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}"] + + +# --- 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 +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") + +# --- 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 + + +# --- Función para seleccionar líneas y ramales y almacenarlos en session_state --- +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") +# --- 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=9, value=8) + + 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: + 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}"] + ) + + # 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 + ): + 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, + overlapping_dict["base"]["h3"], + overlapping_dict["comp"]["h3"], + ) + 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"] + ) + + demand_overlapping = st.session_state[ + f"base_demand_comp_demand_{base_route_id}_{comp_route_id}" + ] + base_demand = demand_overlapping["base"]["data"] + comp_demand = demand_overlapping["comp"]["data"] + + # Renderiza el segundo mapa y muestra el texto justo después del mapa en col2 + 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/dashboard/dash_utils.py b/urbantrips/dashboard/dash_utils.py index 300e23f..dc644da 100644 --- a/urbantrips/dashboard/dash_utils.py +++ b/urbantrips/dashboard/dash_utils.py @@ -597,4 +597,29 @@ def bring_latlon(): latlon = [lat, lon] except: latlon = [-34.593, -58.451] - return latlon \ No newline at end of file + return latlon + +@st.cache_data +def traigo_zonas_values(tipo = 'etapas'): + + if tipo == 'etapas': + table = 'agg_etapas' + else: + table = 'poly_etapas' + + + query = f""" + SELECT DISTINCT zona, inicio_norm FROM {table} + UNION + SELECT DISTINCT zona, transfer1_norm FROM {table} + UNION + SELECT DISTINCT zona, transfer2_norm FROM {table} + UNION + SELECT DISTINCT zona, fin_norm FROM {table}; + """ + zonas_values = etapas=levanto_tabla_sql(table, 'dash', query) + zonas_values = zonas_values[(zonas_values.inicio_norm!='')& + (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 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 bf57c32..128f21b 100644 --- "a/urbantrips/dashboard/pages/3_L\303\255neas de Deseo.py" +++ "b/urbantrips/dashboard/pages/3_L\303\255neas de Deseo.py" @@ -12,7 +12,7 @@ create_data_folium, traigo_indicadores, extract_hex_colors_from_cmap, iniciar_conexion_db, normalize_vars, - bring_latlon + bring_latlon, traigo_zonas_values ) def crear_mapa_lineas_deseo(df_viajes, @@ -324,11 +324,12 @@ def hay_cambios_en_filtros(current, last): zonificaciones = levanto_tabla_sql('zonificaciones') socio_indicadores = levanto_tabla_sql('socio_indicadores') desc_tipo_dia_ = levanto_tabla_sql('agg_etapas', 'dash', 'SELECT DISTINCT tipo_dia FROM agg_etapas;') - desc_zona_ = levanto_tabla_sql('agg_etapas', 'dash', 'SELECT DISTINCT zona FROM agg_etapas;') + desc_zona_ = levanto_tabla_sql('agg_etapas', 'dash', 'SELECT DISTINCT zona FROM agg_etapas;').sort_values('zona') modos_list_all_ = levanto_tabla_sql('agg_etapas', 'dash', 'SELECT DISTINCT modo_agregado FROM agg_etapas;') rango_hora_all_ = levanto_tabla_sql('agg_etapas', 'dash', 'SELECT DISTINCT rango_hora FROM agg_etapas;') distancia_all_ = levanto_tabla_sql('agg_etapas', 'dash', 'SELECT DISTINCT distancia FROM agg_etapas;') - + zonas_values = traigo_zonas_values('etapas') + # 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') @@ -342,7 +343,8 @@ def hay_cambios_en_filtros(current, last): 'transferencia': 'Todos', 'modo_agregado': 'Todos', 'rango_hora': 'Todos', - 'distancia': 'Todas' + 'distancia': 'Todas', + 'desc_zonas_values':'Todos' } if 'data_cargada' not in st.session_state: @@ -362,7 +364,6 @@ def hay_cambios_en_filtros(current, last): modos_list = col1.selectbox('Modos', options=[text for text in modos_list_all]) rango_hora_all = ['Todos'] + rango_hora_all_[rango_hora_all_.rango_hora != '99'].rango_hora.unique().tolist() - # rango_hora = col1.selectbox('Rango hora', options=[text.capitalize() for text in rango_hora_all]) rango_hora = col1.selectbox('Rango hora', options=[text for text in rango_hora_all]) distancia_all = ['Todas'] + distancia_all_[distancia_all_.distancia != '99'].distancia.unique().tolist() @@ -379,6 +380,10 @@ def hay_cambios_en_filtros(current, last): desc_viajes = False 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_origenes = col1.checkbox( ':blue[Origenes]', value=False) @@ -394,6 +399,8 @@ def hay_cambios_en_filtros(current, last): zonif = zonificaciones[zonificaciones.zona == desc_zona] else: zonif = '' + + mtabla = col2.checkbox('Mostrar tabla', value=False) # Construye el diccionario de filtros actual current_filters = { @@ -404,6 +411,7 @@ 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, } current_options = { 'desc_etapas': desc_etapas, @@ -412,7 +420,8 @@ def hay_cambios_en_filtros(current, last): 'desc_destinos': desc_destinos, 'desc_et_vi': desc_et_vi, 'desc_transferencias': desc_transferencias, - 'desc_zonif': desc_zonif, } + 'desc_zonif': desc_zonif, + 'mtabla': mtabla} @@ -420,14 +429,20 @@ 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) + conditions = " AND ".join(f"{key} = '{value}'" for key, value in current_filters.items() if (value is not None)&(key != 'desc_zonas_values')) if conditions: query += f" WHERE {conditions}" - st.session_state.matrices_ = levanto_tabla_sql_local('agg_matrices', tabla_tipo='dash', query=f"SELECT * FROM agg_matrices{query}") - st.session_state.etapas_ = levanto_tabla_sql_local('agg_etapas', tabla_tipo='dash', query=f"SELECT * FROM agg_etapas{query}") - + 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 + 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}") if len(st.session_state.matrices_)==0: col2.write('No hay datos para mostrar') @@ -587,6 +602,9 @@ def hay_cambios_en_filtros(current, last): with col2: folium_static(st.session_state.map, width=1000, height=800) # output = st_folium(st.session_state.map, width=1000, height=800, key='m', returned_objects=["center"]) + if mtabla: + col2.dataframe(st.session_state.etapas_[['inicio_norm', 'transfer1_norm', 'transfer2_norm', 'fin_norm', 'factor_expansion_linea']]) # + else: col2.text("No hay datos suficientes para mostrar el mapa.") else: diff --git a/urbantrips/dashboard/pages/4_Poligonos.py b/urbantrips/dashboard/pages/4_Poligonos.py index 2a56783..43b82e2 100644 --- a/urbantrips/dashboard/pages/4_Poligonos.py +++ b/urbantrips/dashboard/pages/4_Poligonos.py @@ -11,8 +11,8 @@ levanto_tabla_sql, get_logo, create_data_folium, traigo_indicadores, extract_hex_colors_from_cmap, - iniciar_conexion_db, normalize_vars - + iniciar_conexion_db, normalize_vars, + traigo_zonas_values ) from streamlit_folium import folium_static @@ -297,12 +297,12 @@ def hay_cambios_en_filtros(current, last): zonificaciones = levanto_tabla_sql('zonificaciones') socio_indicadores = levanto_tabla_sql('socio_indicadores') desc_tipo_dia_ = levanto_tabla_sql('poly_etapas', 'dash', 'SELECT DISTINCT tipo_dia FROM poly_etapas;') - desc_zona_ = levanto_tabla_sql('poly_etapas', 'dash', 'SELECT DISTINCT zona FROM poly_etapas;') + desc_zona_ = levanto_tabla_sql('poly_etapas', 'dash', 'SELECT DISTINCT zona FROM poly_etapas;').sort_values('zona') modos_list_all_ = levanto_tabla_sql('poly_etapas', 'dash', 'SELECT DISTINCT modo_agregado FROM poly_etapas;') rango_hora_all_ = levanto_tabla_sql('poly_etapas', 'dash', 'SELECT DISTINCT rango_hora FROM poly_etapas;') distancia_all_ = levanto_tabla_sql('poly_etapas', 'dash', 'SELECT DISTINCT distancia FROM poly_etapas;') desc_poly_all_ = levanto_tabla_sql('poly_etapas', 'dash', 'SELECT DISTINCT id_polygon FROM poly_etapas;') - + zonas_values = traigo_zonas_values('poligonos') # 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('poligonos') @@ -316,11 +316,13 @@ def hay_cambios_en_filtros(current, last): 'transferencia': 'Todos', 'modo_agregado': 'Todos', 'rango_hora': 'Todos', - 'distancia': 'Todas' + 'distancia': 'Todas', + 'desc_zonas_values':'Todos' } if 'data_cargada' not in st.session_state: st.session_state.data_cargada = False + # Opciones de los filtros en Streamlit # st.session_state.etapas_lst = ['Todos'] + etapas_lst_.mes.unique().tolist() @@ -358,6 +360,9 @@ def hay_cambios_en_filtros(current, last): desc_viajes = False 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_origenes = col1.checkbox( ':blue[Origenes]', value=False) @@ -383,7 +388,7 @@ def hay_cambios_en_filtros(current, last): desc_cuenca = False - + mtabla = col2.checkbox('Mostrar tabla', value=False) # Construye el diccionario de filtros actual current_filters = { @@ -396,6 +401,7 @@ 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, } current_options = { 'desc_etapas': desc_etapas, 'desc_viajes': desc_viajes, @@ -404,7 +410,8 @@ def hay_cambios_en_filtros(current, last): 'desc_zonif': desc_zonif, 'show_poly' : st.session_state.show_poly, 'desc_cuenca': desc_cuenca, - 'desc_et_vi': desc_et_vi + 'desc_et_vi': desc_et_vi, + 'mtabla': mtabla } @@ -413,12 +420,22 @@ 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) + conditions = " AND ".join(f"{key} = '{value}'" for key, value in current_filters.items() if (value is not None)&(key != 'desc_zonas_values')) 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 + + + 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}") - st.session_state.matrices_ = levanto_tabla_sql_local('poly_matrices', tabla_tipo='dash', query=f"SELECT * FROM poly_matrices{query}") - st.session_state.etapas_ = levanto_tabla_sql_local('poly_etapas', tabla_tipo='dash', query=f"SELECT * FROM poly_etapas{query}") if len(st.session_state.etapas_)==0: col2.write('No hay datos para mostrar') @@ -531,6 +548,12 @@ def hay_cambios_en_filtros(current, last): if st.session_state.map: with col2: folium_static(st.session_state.map, width=1000, height=800) + + + if mtabla: + col2.dataframe(st.session_state.etapas_[['inicio_norm', 'transfer1_norm', 'transfer2_norm', 'fin_norm', 'factor_expansion_linea']]) + + else: col2.text("No hay datos suficientes para mostrar el mapa.") 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 3f58e68..18f6c69 100644 --- "a/urbantrips/dashboard/pages/5_An\303\241lisis de zonas.py" +++ "b/urbantrips/dashboard/pages/5_An\303\241lisis de zonas.py" @@ -136,86 +136,89 @@ def main(): ## Etapas query1 = f"SELECT * FROM etapas_agregadas WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND (h3_o IN ({h3_values1}));" etapas1 = levanto_tabla_sql_local('etapas_agregadas', tabla_tipo='dash', query=query1) - etapas1['Zona_1'] = 'Zona 1' - ## Viajes - query1 = f"SELECT * FROM viajes_agregados WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND (h3_o IN ({h3_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.title('Zona 1') - col2.write('Etapas') - modos_e1['Etapas'] = modos_e1['Etapas'].round() - col2.dataframe(modos_e1.set_index('Modo'), height=400, width=400) - col3.title('') - col3.write('Viajes') - modos_v1['Viajes'] = modos_v1['Viajes'].round() - col3.dataframe(modos_v1.set_index('Modo'), height=400, width=300) + 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 (h3_o IN ({h3_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.title('Zona 1') + col2.write('Etapas') + modos_e1['Etapas'] = modos_e1['Etapas'].round() + col2.dataframe(modos_e1.set_index('Modo'), height=400, width=400) + col3.title('') + col3.write('Viajes') + modos_v1['Viajes'] = modos_v1['Viajes'].round() + col3.dataframe(modos_v1.set_index('Modo'), height=400, width=300) if len(zona2) > 0: h3_values2 = ", ".join(f"'{item}'" for item in zona2) ## Etapas query2 = f"SELECT * FROM etapas_agregadas WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND (h3_o IN ({h3_values2}));" etapas2 = levanto_tabla_sql_local('etapas_agregadas', tabla_tipo='dash', query=query2) - etapas2['Zona_2'] = 'Zona 2' - - ## Viajes - query2 = f"SELECT * FROM viajes_agregados WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND (h3_o IN ({h3_values2}) );" - viajes2 = levanto_tabla_sql_local('viajes_agregados', tabla_tipo='dash', query=query2) - viajes2['Zona_2'] = 'Zona 2' - - 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'}) - - 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.title('Zona 2') - col4.write('Etapas') - modos_e2['Etapas'] = modos_e2['Etapas'].round() - col4.dataframe(modos_e2.set_index('Modo'), height=400, width=400) - - modos_v2['Viajes'] = modos_v2['Viajes'].round() - col5.title('') - col5.write('Viajes') - # col5.markdown(modos_v2.to_html(index=False), unsafe_allow_html=True) - col5.dataframe(modos_v2.set_index('Modo'), height=400, width=300) + 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 (h3_o IN ({h3_values2}) );" + viajes2 = levanto_tabla_sql_local('viajes_agregados', tabla_tipo='dash', query=query2) + viajes2['Zona_2'] = 'Zona 2' + + 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'}) + + 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.title('Zona 2') + col4.write('Etapas') + modos_e2['Etapas'] = modos_e2['Etapas'].round() + col4.dataframe(modos_e2.set_index('Modo'), height=400, width=400) + + modos_v2['Viajes'] = modos_v2['Viajes'].round() + col5.title('') + col5.write('Viajes') + # col5.markdown(modos_v2.to_html(index=False), unsafe_allow_html=True) + 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]) @@ -225,90 +228,123 @@ def main(): ## Etapas query = f"SELECT * FROM etapas_agregadas WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND (h3_o IN ({h3_values}) OR h3_d IN ({h3_values}));" etapas = levanto_tabla_sql_local('etapas_agregadas', tabla_tipo='dash', query=query) - - 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.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'}) - - 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'}) - # Calculate the total and append as a new row - total_rowe = pd.DataFrame({ - 'Modo': ['Total'], - 'Línea': ['-'], - 'Etapas': [modos_e['Etapas'].sum()] - }) - modos_e = pd.concat([modos_e, total_rowe], ignore_index=True) - - modos_e['Etapas'] = modos_e['Etapas'].round() + if len(etapas) > 0: - 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) - - - ## Viajes - query = f"SELECT * FROM viajes_agregados WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND (h3_o IN ({h3_values}) OR h3_d IN ({h3_values}));" - viajes = levanto_tabla_sql_local('viajes_agregados', tabla_tipo='dash', query=query) + 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'}) + + + 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) + + # Calculate the total and append as a new row + total_rowe = pd.DataFrame({ + 'Modo': ['Total'], + 'Línea': ['-'], + 'Etapas': [modos_e['Etapas'].sum()] + }) + modos_e = pd.concat([modos_e, total_rowe], ignore_index=True) + + modos_e['Etapas'] = modos_e['Etapas'].round() + + 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) + + + ## Viajes + h3_values = ", ".join(f"'{item}'" for item in zona1 + zona2) + query = f"SELECT * FROM viajes_agregados WHERE mes = '{desc_mes}' AND tipo_dia = '{desc_tipo_dia}' AND (h3_o IN ({h3_values}) OR h3_d IN ({h3_values}));" + viajes = levanto_tabla_sql_local('viajes_agregados', tabla_tipo='dash', query=query) + + 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'}) + + + + modos_v = viajes.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_row = pd.DataFrame({ + 'Modo': ['Total'], + 'Viajes': [modos_v['Viajes'].sum()] + }) + 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) + 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) + + ## Mapa + + # Create unified geometry for each zone + def zona_to_geometry(h3_list): + polygons = [Polygon(h3.h3_to_geo_boundary(h3_index, geo_json=True)) for h3_index in h3_list] + return unary_union(polygons) + + geometry_zona1 = zona_to_geometry(st.session_state['zona_1']) + geometry_zona2 = zona_to_geometry(st.session_state['zona_2']) + gdf = gpd.GeoDataFrame({ + 'zona': ['Zona 1', 'Zona 2'], + 'geometry': [geometry_zona1, geometry_zona2] + }, crs="EPSG:4326") + + # Plot the zones on a new Folium map + m2 = folium.Map(location=[gdf.geometry.centroid.y.mean(), gdf.geometry.centroid.x.mean()], zoom_start=10) + folium.GeoJson(gdf, name="GeoData").add_to(m2) + + 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)] - 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) & (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'}) - - - - modos_v = viajes.groupby(['modo'], as_index=False).factor_expansion_linea.sum().rename(columns={'factor_expansion_linea':'Viajes', - 'modo': 'Modo'}) + transferencias = transferencias.fillna('') - # 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) + 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') - col3.markdown(zonasod_v.to_html(index=False), unsafe_allow_html=True) - 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) - - ## Mapa - - # Create unified geometry for each zone - def zona_to_geometry(h3_list): - polygons = [Polygon(h3.h3_to_geo_boundary(h3_index, geo_json=True)) for h3_index in h3_list] - return unary_union(polygons) - - geometry_zona1 = zona_to_geometry(st.session_state['zona_1']) - geometry_zona2 = zona_to_geometry(st.session_state['zona_2']) - gdf = gpd.GeoDataFrame({ - 'zona': ['Zona 1', 'Zona 2'], - 'geometry': [geometry_zona1, geometry_zona2] - }, crs="EPSG:4326") - - # Plot the zones on a new Folium map - m2 = folium.Map(location=[gdf.geometry.centroid.y.mean(), gdf.geometry.centroid.x.mean()], zoom_start=10) - folium.GeoJson(gdf, name="GeoData").add_to(m2) + col2.dataframe(transferencias.set_index('Modo'), height=500, width=500) - with col4: - output2 = st_folium(m2, width=700, height=700) if __name__ == '__main__': main() diff --git a/urbantrips/lineas_deseo/lineas_deseo.py b/urbantrips/lineas_deseo/lineas_deseo.py index 9d059b5..04599e8 100644 --- a/urbantrips/lineas_deseo/lineas_deseo.py +++ b/urbantrips/lineas_deseo/lineas_deseo.py @@ -800,8 +800,22 @@ def preparo_etapas_agregadas(etapas, viajes): v_agg = viajes.groupby(['dia', 'mes', 'tipo_dia', 'h3_o', 'h3_d', 'modo'], as_index=False).factor_expansion_linea.sum() v_agg = v_agg.groupby(['mes', 'tipo_dia', 'h3_o', 'h3_d', 'modo'], as_index=False).factor_expansion_linea.mean() 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 = 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 = 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() - return e_agg, v_agg + return e_agg, v_agg, transfers def preparo_lineas_deseo(etapas_selec, viajes_selec, polygons_h3='', poligonos='', res=6): @@ -816,15 +830,17 @@ def preparo_lineas_deseo(etapas_selec, viajes_selec, polygons_h3='', poligonos=' viajes_selec['id_polygon'] = 'NONE' etapas_selec['coincidencias'] = 'NONE' viajes_selec['coincidencias'] = 'NONE' - - etapas_selec = etapas_selec[etapas_selec.distance_osm_drive.notna()].copy() + #### etapas_selec = etapas_selec[etapas_selec.distance_osm_drive.notna()].copy() + etapas_selec = etapas_selec.rename( columns={'distance_osm_drive': 'distance_osm_drive_etapas'}) distancias_all = etapas_selec.groupby( ['id_polygon', 'dia', 'id_tarjeta', 'id_viaje'], as_index=False)[['distance_osm_drive_etapas']].sum() + distancias_all = distancias_all.merge(viajes_selec.loc[viajes_selec.od_validado == 1, [ - 'id_polygon', 'dia', 'id_tarjeta', 'id_viaje', 'distance_osm_drive', 'travel_time_min', 'travel_speed']]) + 'id_polygon', 'dia', 'id_tarjeta', 'id_viaje', 'distance_osm_drive', 'travel_time_min', 'travel_speed']]) # + distancias_all['distancia'] = 'Viajes cortos (<=5kms)' distancias_all.loc[(distancias_all.distance_osm_drive > 5), 'distancia'] = 'Viajes largos (>5kms)' @@ -866,16 +882,11 @@ def preparo_lineas_deseo(etapas_selec, viajes_selec, polygons_h3='', poligonos=' etapas_selec.loc[(etapas_selec.hora >= 17) & ( etapas_selec.hora <= 24), 'rango_hora'] = '17-24' - etapas_agrupadas_all = pd.DataFrame([]) - gpd_viajes_agrupados_all = pd.DataFrame([]) - for id_polygon in polygons_h3.id_polygon.unique(): poly_h3 = polygons_h3[polygons_h3.id_polygon == id_polygon] poly = poligonos[poligonos.id == id_polygon] tipo_poly = poly.tipo.values[0] - print('') - print(f'Polígono {id_polygon} - Tipo: {tipo_poly}') # Preparo Etapas con inicio, transferencias y fin del viaje etapas_all = etapas_selec.loc[(etapas_selec.id_polygon == id_polygon), ['dia', @@ -940,8 +951,7 @@ def preparo_lineas_deseo(etapas_selec, viajes_selec, polygons_h3='', poligonos=' etapas_all = pd.concat([etapas_all, ultimo_viaje]).sort_values( ['dia', 'id_tarjeta', 'id_viaje', 'id_etapa']).reset_index(drop=True) - etapas_all['tipo_viaje'] = 'Transfer_' + \ - (etapas_all['id_etapa']-1).astype(str) + etapas_all['tipo_viaje'] = 'Transfer_' + (etapas_all['id_etapa']-1).astype(str) etapas_all.loc[etapas_all.ultimo_viaje == 1, 'tipo_viaje'] = 'Fin' etapas_all.loc[etapas_all.id_etapa == 1, 'tipo_viaje'] = 'Inicio' @@ -1012,10 +1022,10 @@ def preparo_lineas_deseo(etapas_selec, viajes_selec, polygons_h3='', poligonos=' 'tarifa', 'coincidencias', 'factor_expansion_linea']] - - for zona in zonas: + print('') + print(f'Polígono {id_polygon} - Tipo: {tipo_poly} - Zona: {zona}') if id_polygon != 'NONE': # print(id_polygon, zona) @@ -1136,264 +1146,320 @@ def preparo_lineas_deseo(etapas_selec, viajes_selec, polygons_h3='', poligonos=' etapas_agrupadas_zon = normalizo_zona(etapas_agrupadas_zon, zonificaciones[zonificaciones.zona == zona].copy()) - etapas_agrupadas_all = pd.concat( - [etapas_agrupadas_all, etapas_agrupadas_zon], ignore_index=True) - - etapas_agrupadas_all['transferencia'] = 0 - etapas_agrupadas_all.loc[(etapas_agrupadas_all.transfer1_norm != '') | ( - etapas_agrupadas_all.transfer2_norm != ''), 'transferencia'] = 1 - - etapas_agrupadas_all = etapas_agrupadas_all.merge( - distancias_all, how='left') - - etapas_agrupadas_all['tipo_dia_'] = pd.to_datetime(etapas_agrupadas_all.dia).dt.weekday.astype(str).copy() - etapas_agrupadas_all['tipo_dia'] = 'Hábil' - etapas_agrupadas_all.loc[etapas_agrupadas_all.tipo_dia_.astype(int)>=5, 'tipo_dia'] = 'Fin de Semana' - etapas_agrupadas_all = etapas_agrupadas_all.drop(['tipo_dia_'], axis=1) - etapas_agrupadas_all['mes'] = etapas_agrupadas_all.dia.str[:7] - - etapas_agrupadas_all = etapas_agrupadas_all[['id_polygon', 'zona', 'dia', 'mes', 'tipo_dia', 'id_tarjeta', 'id_viaje', - 'h3_inicio', 'h3_transfer1', 'h3_transfer2', 'h3_fin', - 'inicio', 'transfer1', 'transfer2', 'fin', - 'poly_inicio', 'poly_transfer1', 'poly_transfer2', 'poly_fin', - 'inicio_norm', 'transfer1_norm', 'transfer2_norm', 'fin_norm', - 'poly_inicio_norm', 'poly_transfer1_norm', 'poly_transfer2_norm', 'poly_fin_norm', - 'lon1', 'lat1', 'lon2', 'lat2', 'lon3', 'lat3', 'lon4', 'lat4', - 'lon1_norm', 'lat1_norm', 'lon2_norm', 'lat2_norm', 'lon3_norm', 'lat3_norm', 'lon4_norm', 'lat4_norm', - 'transferencia', 'modo_agregado', 'rango_hora', 'genero', 'tarifa', 'coincidencias', 'distancia', - 'distance_osm_drive', 'distance_osm_drive_etapas', - 'travel_time_min', 'travel_speed', - 'factor_expansion_linea']] - - etapas_sin_agrupar = etapas_agrupadas_all.copy() - - aggregate_cols = ['id_polygon', 'dia', 'mes', 'tipo_dia', 'zona', 'inicio', 'fin', 'poly_inicio', - 'poly_fin', 'transferencia', 'modo_agregado', 'rango_hora', 'genero', 'tarifa', 'coincidencias', 'distancia'] - viajes_matrices = construyo_matrices(etapas_sin_agrupar, - aggregate_cols, - zonificaciones, - False, - False, - False) - - # Agrupación de viajes - aggregate_cols = ['id_polygon', - 'dia', - 'mes', - 'tipo_dia', - 'zona', - 'inicio_norm', - 'transfer1_norm', - 'transfer2_norm', - 'fin_norm', - 'poly_inicio_norm', - 'poly_transfer1_norm', - 'poly_transfer2_norm', - 'poly_fin_norm', - 'transferencia', - 'modo_agregado', - 'rango_hora', - 'genero', - 'tarifa', - 'coincidencias', - 'distancia'] - - weighted_mean_cols = ['distance_osm_drive', - 'distance_osm_drive_etapas', - 'travel_time_min', - 'travel_speed', - 'lat1_norm', - 'lon1_norm', - 'lat2_norm', - 'lon2_norm', - 'lat3_norm', - 'lon3_norm', - 'lat4_norm', - 'lon4_norm'] - - weight_col = 'factor_expansion_linea' - - zero_to_nan = ['lat1_norm', - 'lon1_norm', - 'lat2_norm', - 'lon2_norm', - 'lat3_norm', - 'lon3_norm', - 'lat4_norm', - 'lon4_norm'] - - etapas_agrupadas_all = agrupar_viajes(etapas_agrupadas_all, - aggregate_cols, - weighted_mean_cols, - weight_col, - zero_to_nan, - agg_transferencias=False, - agg_modo=False, - agg_hora=False, - agg_distancia=False) - - zonificaciones['lat'] = zonificaciones.geometry.representative_point().y - zonificaciones['lon'] = zonificaciones.geometry.representative_point().x + ### etapas_agrupadas_zon = pd.concat( + ### [etapas_agrupadas_zon, etapas_agrupadas_zon], ignore_index=True) - n = 1 - poly_lst = ['poly_inicio', 'poly_transfer1', 'poly_transfer2', 'poly_fin'] - for i in ['inicio', 'transfer1', 'transfer2', 'fin']: - etapas_agrupadas_all = etapas_agrupadas_all.merge(zonificaciones[['zona', 'id', 'lat', 'lon']].rename(columns={'id': f'{i}_norm', 'lat': f'lat{n}_norm_tmp', 'lon': f'lon{n}_norm_tmp'}), - how='left', - on=['zona', f'{i}_norm']) - etapas_agrupadas_all.loc[etapas_agrupadas_all[f'{poly_lst[n-1]}_norm'] == '', - f'lat{n}_norm'] = etapas_agrupadas_all.loc[etapas_agrupadas_all[f'{poly_lst[n-1]}_norm'] == '', f'lat{n}_norm_tmp'] - etapas_agrupadas_all.loc[etapas_agrupadas_all[f'{poly_lst[n-1]}_norm'] == '', - f'lon{n}_norm'] = etapas_agrupadas_all.loc[etapas_agrupadas_all[f'{poly_lst[n-1]}_norm'] == '', f'lon{n}_norm_tmp'] - - etapas_agrupadas_all = etapas_agrupadas_all.drop( - [f'lat{n}_norm_tmp', f'lon{n}_norm_tmp'], axis=1) - - if (n == 1) | (n == 4): - viajes_matrices = viajes_matrices.merge(zonificaciones[['zona', 'id', 'lat', 'lon']].rename(columns={'id': f'{i}', 'lat': f'lat{n}_tmp', 'lon': f'lon{n}_tmp'}), - how='left', - on=['zona', f'{i}']) - viajes_matrices.loc[viajes_matrices[f'{poly_lst[n-1]}'] == '', - f'lat{n}'] = viajes_matrices.loc[viajes_matrices[f'{poly_lst[n-1]}'] == '', f'lat{n}_tmp'] - viajes_matrices.loc[viajes_matrices[f'{poly_lst[n-1]}'] == '', - f'lon{n}'] = viajes_matrices.loc[viajes_matrices[f'{poly_lst[n-1]}'] == '', f'lon{n}_tmp'] - viajes_matrices = viajes_matrices.drop( - [f'lat{n}_tmp', f'lon{n}_tmp'], axis=1) - - n += 1 - - - - # # Agrupar a nivel de mes y corregir factor de expansión - sum_viajes = etapas_agrupadas_all.groupby(['dia', - 'mes', - 'tipo_dia', - 'zona'], as_index=False).factor_expansion_linea.sum().groupby(['mes', - 'tipo_dia', - 'zona'], as_index=False).factor_expansion_linea.mean().round() + etapas_agrupadas_zon['transferencia'] = 0 + etapas_agrupadas_zon.loc[(etapas_agrupadas_zon.transfer1_norm != '') | ( + etapas_agrupadas_zon.transfer2_norm != ''), 'transferencia'] = 1 - aggregate_cols = ['mes', - 'tipo_dia', - 'id_polygon', - 'poly_inicio_norm', - 'poly_transfer1_norm', - 'poly_transfer2_norm', - 'poly_fin_norm', - 'zona', - 'inicio_norm', - 'transfer1_norm', - 'transfer2_norm', - 'fin_norm', - 'transferencia', - 'modo_agregado', - 'rango_hora', - 'genero', - 'tarifa', - 'coincidencias', - 'distancia', ] - weighted_mean_cols=['distance_osm_drive', - 'distance_osm_drive_etapas', - 'travel_time_min', - 'travel_speed', - 'lat1_norm', - 'lon1_norm', - 'lat2_norm', - 'lon2_norm', - 'lat3_norm', - 'lon3_norm', - 'lat4_norm', - 'lon4_norm'] - - etapas_agrupadas_all = calculate_weighted_means(etapas_agrupadas_all, - aggregate_cols=aggregate_cols, - weighted_mean_cols=weighted_mean_cols, - weight_col='factor_expansion_linea', - zero_to_nan=zero_to_nan, - var_fex_summed=False) + etapas_agrupadas_zon = etapas_agrupadas_zon.merge( + distancias_all, how='left') + + etapas_agrupadas_zon['tipo_dia_'] = pd.to_datetime(etapas_agrupadas_zon.dia).dt.weekday.astype(str).copy() + etapas_agrupadas_zon['tipo_dia'] = 'Hábil' + etapas_agrupadas_zon.loc[etapas_agrupadas_zon.tipo_dia_.astype(int)>=5, 'tipo_dia'] = 'Fin de Semana' + etapas_agrupadas_zon = etapas_agrupadas_zon.drop(['tipo_dia_'], axis=1) + etapas_agrupadas_zon['mes'] = etapas_agrupadas_zon.dia.str[:7] + + etapas_agrupadas_zon = etapas_agrupadas_zon[['id_polygon', 'zona', 'dia', 'mes', 'tipo_dia', 'id_tarjeta', 'id_viaje', + 'h3_inicio', 'h3_transfer1', 'h3_transfer2', 'h3_fin', + 'inicio', 'transfer1', 'transfer2', 'fin', + 'poly_inicio', 'poly_transfer1', 'poly_transfer2', 'poly_fin', + 'inicio_norm', 'transfer1_norm', 'transfer2_norm', 'fin_norm', + 'poly_inicio_norm', 'poly_transfer1_norm', 'poly_transfer2_norm', 'poly_fin_norm', + 'lon1', 'lat1', 'lon2', 'lat2', 'lon3', 'lat3', 'lon4', 'lat4', + 'lon1_norm', 'lat1_norm', 'lon2_norm', 'lat2_norm', 'lon3_norm', 'lat3_norm', 'lon4_norm', 'lat4_norm', + 'transferencia', 'modo_agregado', 'rango_hora', 'genero', 'tarifa', 'coincidencias', 'distancia', + 'distance_osm_drive', 'distance_osm_drive_etapas', + 'travel_time_min', 'travel_speed', + 'factor_expansion_linea']] + + aggregate_cols = ['id_polygon', 'dia', 'mes', 'tipo_dia', 'zona', 'inicio', 'fin', 'poly_inicio', + 'poly_fin', 'transferencia', 'modo_agregado', 'rango_hora', 'genero', 'tarifa', 'coincidencias', 'distancia'] + viajes_matrices = construyo_matrices(etapas_agrupadas_zon, + aggregate_cols, + zonificaciones, + False, + False, + False) + + # Agrupación de viajes + aggregate_cols = ['id_polygon', + 'dia', + 'mes', + 'tipo_dia', + 'zona', + 'inicio_norm', + 'transfer1_norm', + 'transfer2_norm', + 'fin_norm', + 'poly_inicio_norm', + 'poly_transfer1_norm', + 'poly_transfer2_norm', + 'poly_fin_norm', + 'transferencia', + 'modo_agregado', + 'rango_hora', + 'genero', + 'tarifa', + 'coincidencias', + 'distancia'] + + weighted_mean_cols = ['distance_osm_drive', + 'distance_osm_drive_etapas', + 'travel_time_min', + 'travel_speed', + 'lat1_norm', + 'lon1_norm', + 'lat2_norm', + 'lon2_norm', + 'lat3_norm', + 'lon3_norm', + 'lat4_norm', + 'lon4_norm'] + + weight_col = 'factor_expansion_linea' + + zero_to_nan = ['lat1_norm', + 'lon1_norm', + 'lat2_norm', + 'lon2_norm', + 'lat3_norm', + 'lon3_norm', + 'lat4_norm', + 'lon4_norm'] + + etapas_agrupadas_zon = agrupar_viajes(etapas_agrupadas_zon, + aggregate_cols, + weighted_mean_cols, + weight_col, + zero_to_nan, + agg_transferencias=False, + agg_modo=False, + agg_hora=False, + agg_distancia=False) + + zonificaciones['lat'] = zonificaciones.geometry.representative_point().y + zonificaciones['lon'] = zonificaciones.geometry.representative_point().x + + n = 1 + poly_lst = ['poly_inicio', 'poly_transfer1', 'poly_transfer2', 'poly_fin'] + for i in ['inicio', 'transfer1', 'transfer2', 'fin']: + etapas_agrupadas_zon = etapas_agrupadas_zon.merge(zonificaciones[['zona', 'id', 'lat', 'lon']].rename(columns={'id': f'{i}_norm', 'lat': f'lat{n}_norm_tmp', 'lon': f'lon{n}_norm_tmp'}), + how='left', + on=['zona', f'{i}_norm']) + etapas_agrupadas_zon.loc[etapas_agrupadas_zon[f'{poly_lst[n-1]}_norm'] == '', + f'lat{n}_norm'] = etapas_agrupadas_zon.loc[etapas_agrupadas_zon[f'{poly_lst[n-1]}_norm'] == '', f'lat{n}_norm_tmp'] + etapas_agrupadas_zon.loc[etapas_agrupadas_zon[f'{poly_lst[n-1]}_norm'] == '', + f'lon{n}_norm'] = etapas_agrupadas_zon.loc[etapas_agrupadas_zon[f'{poly_lst[n-1]}_norm'] == '', f'lon{n}_norm_tmp'] + + etapas_agrupadas_zon = etapas_agrupadas_zon.drop( + [f'lat{n}_norm_tmp', f'lon{n}_norm_tmp'], axis=1) + + if (n == 1) | (n == 4): + viajes_matrices = viajes_matrices.merge(zonificaciones[['zona', 'id', 'lat', 'lon']].rename(columns={'id': f'{i}', 'lat': f'lat{n}_tmp', 'lon': f'lon{n}_tmp'}), + how='left', + on=['zona', f'{i}']) + viajes_matrices.loc[viajes_matrices[f'{poly_lst[n-1]}'] == '', + f'lat{n}'] = viajes_matrices.loc[viajes_matrices[f'{poly_lst[n-1]}'] == '', f'lat{n}_tmp'] + viajes_matrices.loc[viajes_matrices[f'{poly_lst[n-1]}'] == '', + f'lon{n}'] = viajes_matrices.loc[viajes_matrices[f'{poly_lst[n-1]}'] == '', f'lon{n}_tmp'] + viajes_matrices = viajes_matrices.drop( + [f'lat{n}_tmp', f'lon{n}_tmp'], axis=1) + + n += 1 + + + + # # Agrupar a nivel de mes y corregir factor de expansión + sum_viajes = etapas_agrupadas_zon.groupby(['dia', + 'mes', + 'tipo_dia', + 'zona'], as_index=False).factor_expansion_linea.sum().groupby(['mes', + 'tipo_dia', + 'zona'], as_index=False).factor_expansion_linea.mean().round() + + aggregate_cols = ['mes', + 'tipo_dia', + 'id_polygon', + 'poly_inicio_norm', + 'poly_transfer1_norm', + 'poly_transfer2_norm', + 'poly_fin_norm', + 'zona', + 'inicio_norm', + 'transfer1_norm', + 'transfer2_norm', + 'fin_norm', + 'transferencia', + 'modo_agregado', + 'rango_hora', + 'genero', + 'tarifa', + 'coincidencias', + 'distancia', ] + weighted_mean_cols=['distance_osm_drive', + 'distance_osm_drive_etapas', + 'travel_time_min', + 'travel_speed', + 'lat1_norm', + 'lon1_norm', + 'lat2_norm', + 'lon2_norm', + 'lat3_norm', + 'lon3_norm', + 'lat4_norm', + 'lon4_norm'] + + etapas_agrupadas_zon = calculate_weighted_means(etapas_agrupadas_zon, + aggregate_cols=aggregate_cols, + weighted_mean_cols=weighted_mean_cols, + weight_col='factor_expansion_linea', + zero_to_nan=zero_to_nan, + var_fex_summed=False) + + + sum_viajes['factor_expansion_linea'] = 1 - (sum_viajes['factor_expansion_linea'] / etapas_agrupadas_zon.groupby(['mes', 'tipo_dia', 'zona'], as_index=False).factor_expansion_linea.sum().factor_expansion_linea ) + sum_viajes = sum_viajes.rename(columns={'factor_expansion_linea':'factor_correccion'}) + + etapas_agrupadas_zon = etapas_agrupadas_zon.merge(sum_viajes) + etapas_agrupadas_zon['factor_expansion_linea2'] = etapas_agrupadas_zon['factor_expansion_linea'] * etapas_agrupadas_zon['factor_correccion'] + etapas_agrupadas_zon['factor_expansion_linea2'] = etapas_agrupadas_zon['factor_expansion_linea'] - etapas_agrupadas_zon['factor_expansion_linea2'] + etapas_agrupadas_zon = etapas_agrupadas_zon.drop(['factor_correccion', 'factor_expansion_linea'], axis=1) + etapas_agrupadas_zon = etapas_agrupadas_zon.rename(columns={'factor_expansion_linea2':'factor_expansion_linea'}) + + # # Agrupar a nivel de mes y corregir factor de expansión + sum_viajes = viajes_matrices.groupby(['dia', 'mes', 'tipo_dia', 'zona'], as_index=False).factor_expansion_linea.sum().groupby(['mes', 'tipo_dia', 'zona'], as_index=False).factor_expansion_linea.mean() + + aggregate_cols = ['id_polygon', + 'poly_inicio', + 'poly_fin', + 'mes', + 'tipo_dia', + 'zona', + 'inicio', + 'fin', + 'transferencia', + 'modo_agregado', + 'rango_hora', + 'genero', + 'tarifa', + 'coincidencias', + 'distancia', + 'orden_origen', + 'orden_destino', + 'Origen', + 'Destino'] + weighted_mean_cols = ['lat1', + 'lon1', + 'lat4', + 'lon4', + 'distance_osm_drive', + 'travel_time_min', + 'travel_speed',] + zero_to_nan = ['lat1', + 'lon1', + 'lat4', + 'lon4'] + + viajes_matrices = calculate_weighted_means(viajes_matrices, + aggregate_cols=aggregate_cols, + weighted_mean_cols=weighted_mean_cols, + weight_col='factor_expansion_linea', + zero_to_nan=zero_to_nan, + var_fex_summed=False) + + sum_viajes['factor_expansion_linea'] = 1 - (sum_viajes['factor_expansion_linea'] / viajes_matrices.groupby(['mes', 'tipo_dia', 'zona'], as_index=False).factor_expansion_linea.sum().factor_expansion_linea ) + sum_viajes = sum_viajes.rename(columns={'factor_expansion_linea':'factor_correccion'}) + + viajes_matrices = viajes_matrices.merge(sum_viajes) + viajes_matrices['factor_expansion_linea2'] = viajes_matrices['factor_expansion_linea'] * viajes_matrices['factor_correccion'] + viajes_matrices['factor_expansion_linea2'] = viajes_matrices['factor_expansion_linea'] - viajes_matrices['factor_expansion_linea2'] + viajes_matrices = viajes_matrices.drop(['factor_correccion', 'factor_expansion_linea'], axis=1) + viajes_matrices = viajes_matrices.rename(columns={'factor_expansion_linea2':'factor_expansion_linea'}) + + if len(poligonos[poligonos.tipo=='cuenca'])>0: + + etapas_agrupadas_zon.loc[ + etapas_agrupadas_zon.poly_inicio_norm.isin( + poligonos[poligonos.tipo=='cuenca'].id.unique()), + 'inicio_norm'] = etapas_agrupadas_zon.loc[ + etapas_agrupadas_zon.poly_inicio_norm.isin( + poligonos[poligonos.tipo=='cuenca'].id.unique()), 'inicio_norm']+' (cuenca)' + etapas_agrupadas_zon.loc[ + etapas_agrupadas_zon.poly_transfer1_norm.isin( + poligonos[poligonos.tipo=='cuenca'].id.unique()), + 'transfer1_norm'] = etapas_agrupadas_zon.loc[ + etapas_agrupadas_zon.poly_transfer1_norm.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'transfer1_norm']+' (cuenca)' + etapas_agrupadas_zon.loc[ + etapas_agrupadas_zon.poly_transfer2_norm.isin( + poligonos[poligonos.tipo=='cuenca'].id.unique()), + 'transfer2_norm'] = etapas_agrupadas_zon.loc[etapas_agrupadas_zon.poly_transfer2_norm.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'transfer2_norm']+' (cuenca)' + etapas_agrupadas_zon.loc[ + etapas_agrupadas_zon.poly_fin_norm.isin( + poligonos[poligonos.tipo=='cuenca'].id.unique()), + 'fin_norm'] = etapas_agrupadas_zon.loc[etapas_agrupadas_zon.poly_fin_norm.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'fin_norm']+' (cuenca)' + viajes_matrices.loc[ + viajes_matrices.poly_inicio.isin( + poligonos[poligonos.tipo=='cuenca'].id.unique()), + 'Origen'] = viajes_matrices.loc[viajes_matrices.poly_inicio.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'Origen']+' (cuenca)' + viajes_matrices.loc[ + viajes_matrices.poly_fin.isin( + poligonos[poligonos.tipo=='cuenca'].id.unique()), + 'Destino'] = viajes_matrices.loc[viajes_matrices.poly_fin.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'Destino']+' (cuenca)' + viajes_matrices.loc[ + viajes_matrices.poly_inicio.isin( + poligonos[poligonos.tipo=='cuenca'].id.unique()), + 'inicio'] = viajes_matrices.loc[viajes_matrices.poly_inicio.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'inicio']+' (cuenca)' + viajes_matrices.loc[ + viajes_matrices.poly_fin.isin( + poligonos[poligonos.tipo== + 'cuenca'].id.unique()), 'fin'] = viajes_matrices.loc[viajes_matrices.poly_fin.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'fin']+' (cuenca)' + + etapas_agrupadas_zon = etapas_agrupadas_zon.fillna(0) - sum_viajes['factor_expansion_linea'] = 1 - (sum_viajes['factor_expansion_linea'] / etapas_agrupadas_all.groupby(['mes', 'tipo_dia', 'zona'], as_index=False).factor_expansion_linea.sum().factor_expansion_linea ) - sum_viajes = sum_viajes.rename(columns={'factor_expansion_linea':'factor_correccion'}) - - etapas_agrupadas_all = etapas_agrupadas_all.merge(sum_viajes) - etapas_agrupadas_all['factor_expansion_linea2'] = etapas_agrupadas_all['factor_expansion_linea'] * etapas_agrupadas_all['factor_correccion'] - etapas_agrupadas_all['factor_expansion_linea2'] = etapas_agrupadas_all['factor_expansion_linea'] - etapas_agrupadas_all['factor_expansion_linea2'] - etapas_agrupadas_all = etapas_agrupadas_all.drop(['factor_correccion', 'factor_expansion_linea'], axis=1) - etapas_agrupadas_all = etapas_agrupadas_all.rename(columns={'factor_expansion_linea2':'factor_expansion_linea'}) - - # # Agrupar a nivel de mes y corregir factor de expansión - sum_viajes = viajes_matrices.groupby(['dia', 'mes', 'tipo_dia', 'zona'], as_index=False).factor_expansion_linea.sum().groupby(['mes', 'tipo_dia', 'zona'], as_index=False).factor_expansion_linea.mean() - - aggregate_cols = ['id_polygon', - 'poly_inicio', - 'poly_fin', - 'mes', - 'tipo_dia', - 'zona', - 'inicio', - 'fin', - 'transferencia', - 'modo_agregado', - 'rango_hora', - 'genero', - 'tarifa', - 'coincidencias', - 'distancia', - 'orden_origen', - 'orden_destino', - 'Origen', - 'Destino'] - weighted_mean_cols = ['lat1', - 'lon1', - 'lat4', - 'lon4', - 'distance_osm_drive', - 'travel_time_min', - 'travel_speed',] - zero_to_nan = ['lat1', - 'lon1', - 'lat4', - 'lon4'] - - viajes_matrices = calculate_weighted_means(viajes_matrices, - aggregate_cols=aggregate_cols, - weighted_mean_cols=weighted_mean_cols, - weight_col='factor_expansion_linea', - zero_to_nan=zero_to_nan, - var_fex_summed=False) - - sum_viajes['factor_expansion_linea'] = 1 - (sum_viajes['factor_expansion_linea'] / viajes_matrices.groupby(['mes', 'tipo_dia', 'zona'], as_index=False).factor_expansion_linea.sum().factor_expansion_linea ) - sum_viajes = sum_viajes.rename(columns={'factor_expansion_linea':'factor_correccion'}) - - viajes_matrices = viajes_matrices.merge(sum_viajes) - viajes_matrices['factor_expansion_linea2'] = viajes_matrices['factor_expansion_linea'] * viajes_matrices['factor_correccion'] - viajes_matrices['factor_expansion_linea2'] = viajes_matrices['factor_expansion_linea'] - viajes_matrices['factor_expansion_linea2'] - viajes_matrices = viajes_matrices.drop(['factor_correccion', 'factor_expansion_linea'], axis=1) - viajes_matrices = viajes_matrices.rename(columns={'factor_expansion_linea2':'factor_expansion_linea'}) - - if id_polygon == 'NONE': - etapas_agrupadas_all = etapas_agrupadas_all.drop(['id_polygon', - 'poly_inicio_norm', - 'poly_transfer1_norm', - 'poly_transfer2_norm', - 'poly_fin_norm'], axis=1) - - viajes_matrices = viajes_matrices.drop( - ['poly_inicio', - 'poly_fin'], axis=1) + if id_polygon == 'NONE': + + etapas_agrupadas_zon = etapas_agrupadas_zon.drop(['id_polygon', + 'poly_inicio_norm', + 'poly_transfer1_norm', + 'poly_transfer2_norm', + 'poly_fin_norm'], axis=1) - if len(poligonos[poligonos.tipo=='cuenca'])>0: - - etapas_agrupadas_all.loc[etapas_agrupadas_all.poly_inicio_norm.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'inicio_norm'] = etapas_agrupadas_all.loc[etapas_agrupadas_all.poly_inicio_norm.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'inicio_norm']+' (cuenca)' - etapas_agrupadas_all.loc[etapas_agrupadas_all.poly_transfer1_norm.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'transfer1_norm'] = etapas_agrupadas_all.loc[etapas_agrupadas_all.poly_transfer1_norm.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'transfer1_norm']+' (cuenca)' - etapas_agrupadas_all.loc[etapas_agrupadas_all.poly_transfer2_norm.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'transfer2_norm'] = etapas_agrupadas_all.loc[etapas_agrupadas_all.poly_transfer2_norm.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'transfer2_norm']+' (cuenca)' - etapas_agrupadas_all.loc[etapas_agrupadas_all.poly_fin_norm.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'fin_norm'] = etapas_agrupadas_all.loc[etapas_agrupadas_all.poly_fin_norm.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'fin_norm']+' (cuenca)' - viajes_matrices.loc[viajes_matrices.poly_inicio.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'Origen'] = viajes_matrices.loc[viajes_matrices.poly_inicio.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'Origen']+' (cuenca)' - viajes_matrices.loc[viajes_matrices.poly_fin.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'Destino'] = viajes_matrices.loc[viajes_matrices.poly_fin.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'Destino']+' (cuenca)' - viajes_matrices.loc[viajes_matrices.poly_inicio.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'inicio'] = viajes_matrices.loc[viajes_matrices.poly_inicio.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'inicio']+' (cuenca)' - viajes_matrices.loc[viajes_matrices.poly_fin.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'fin'] = viajes_matrices.loc[viajes_matrices.poly_fin.isin(poligonos[poligonos.tipo=='cuenca'].id.unique()), 'fin']+' (cuenca)' - - return etapas_agrupadas_all, etapas_sin_agrupar, viajes_matrices, zonificaciones + viajes_matrices = viajes_matrices.drop( + ['poly_inicio', + 'poly_fin'], axis=1) + + guardar_tabla_sql(etapas_agrupadas_zon, + 'agg_etapas', + 'dash', + {'mes': etapas_agrupadas_zon.mes.unique().tolist(), + 'zona': etapas_agrupadas_zon.zona.unique().tolist()}) + + guardar_tabla_sql(viajes_matrices, + 'agg_matrices', + 'dash', + {'mes': viajes_matrices.mes.unique().tolist(), + 'zona': viajes_matrices.zona.unique().tolist()}) + else: + guardar_tabla_sql(etapas_agrupadas_zon, + 'poly_etapas', + 'dash', + {'mes': etapas_agrupadas_zon.mes.unique().tolist(), + 'zona': etapas_agrupadas_zon.zona.unique().tolist(), + 'id_polygon': etapas_agrupadas_zon.id_polygon.unique().tolist()}) + + guardar_tabla_sql(viajes_matrices, + 'poly_matrices', + 'dash', + {'mes': viajes_matrices.mes.unique().tolist(), + 'zona': viajes_matrices.zona.unique().tolist(), + 'id_polygon': viajes_matrices.id_polygon.unique().tolist()}) + + +### return etapas_agrupadas_zon, viajes_matrices, zonificaciones def proceso_poligonos(check_configs=True): @@ -1420,22 +1486,20 @@ def proceso_poligonos(check_configs=True): etapas_selec, viajes_selec, polygons, polygons_h3 = select_cases_from_polygons( etapas[etapas.od_validado == 1], viajes[viajes.od_validado == 1], poligonos, res=res) - etapas_agrupadas, etapas_sin_agrupar, viajes_matrices, zonificaciones = preparo_lineas_deseo( - etapas_selec, viajes_selec, polygons_h3, poligonos=poligonos, res=[6]) + preparo_lineas_deseo(etapas_selec, viajes_selec, polygons_h3, poligonos=poligonos, res=[6]) indicadores = construyo_indicadores(viajes_selec, poligonos=True) - etapas_agrupadas = etapas_agrupadas.fillna(0) - guardar_tabla_sql(etapas_agrupadas, - 'poly_etapas', - 'dash', - {'mes': etapas_agrupadas.mes.unique().tolist()}) + ## 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(viajes_matrices, + ## 'poly_matrices', + ## 'dash', + ## {'mes': viajes_matrices.mes.unique().tolist()}) guardar_tabla_sql(indicadores, 'poly_indicadores', @@ -1457,8 +1521,7 @@ def proceso_lineas_deseo(check_configs=False): etapas, viajes = load_and_process_data() - etapas_agrupadas, etapas_sin_agrupar, viajes_matrices, zonificaciones = preparo_lineas_deseo( - etapas, viajes, res=[6]) + preparo_lineas_deseo(etapas, viajes, res=[6]) indicadores = construyo_indicadores(viajes, poligonos=False) @@ -1466,16 +1529,16 @@ def proceso_lineas_deseo(check_configs=False): print('Guardo datos para dashboard') - etapas_agrupadas = etapas_agrupadas.fillna(0) - guardar_tabla_sql(etapas_agrupadas, - 'agg_etapas', - 'dash', - {'mes': etapas_agrupadas.mes.unique().tolist()}) + ## 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()}) - guardar_tabla_sql(viajes_matrices, - 'agg_matrices', - 'dash', - {'mes': viajes_matrices.mes.unique().tolist()}) guardar_tabla_sql(indicadores, 'agg_indicadores', 'dash', @@ -1486,7 +1549,7 @@ def proceso_lineas_deseo(check_configs=False): 'dash', {'mes': socio_indicadores.mes.unique().tolist()}) - e_agg, v_agg = preparo_etapas_agregadas(etapas, viajes) + e_agg, v_agg, transfers = preparo_etapas_agregadas(etapas, viajes) guardar_tabla_sql(e_agg, 'etapas_agregadas', 'dash', @@ -1497,4 +1560,9 @@ def proceso_lineas_deseo(check_configs=False): 'dash', {'mes': v_agg.mes.unique().tolist()}) + guardar_tabla_sql(transfers, + 'transferencias_agregadas', + 'dash', + {'mes': v_agg.mes.unique().tolist()}) + imprimo_matrices_od()