├── .gitattributes ├── data ├── tarifas.csv ├── indices_h3.csv ├── paradas.csv ├── lineas_ramales.csv └── transacciones.csv ├── resultados ├── etapas.csv ├── tarjetas.csv └── viajes.csv ├── informe └── Matriz OD de Transporte Publico en base a datos SUBE.pdf ├── queries ├── 1_crear_tablas_principales.sql ├── 4_construir_tablas_viajes_tarjetas.sql ├── 3_imputar_destinos.sql └── 2_construir_etapas.sql ├── README.md ├── CODE_OF_CONDUCT.md └── LICENSE.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.csv filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /data/tarifas.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d4f84708b4e28f5e9a49e92552ff844b8bde8e0a2fba9bac51c61e21e129aa15 3 | size 463 4 | -------------------------------------------------------------------------------- /data/indices_h3.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:87e2db03ab42ba22f746cb319183911f2a812b34207bb764f92f73871a196155 3 | size 2912797 4 | -------------------------------------------------------------------------------- /data/paradas.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:65b50b46df4d0a3d6db61baf7f7e5c116677148e980c39c9ecb975a1f95ae4cf 3 | size 8938696 4 | -------------------------------------------------------------------------------- /data/lineas_ramales.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a76dcf8ed607e799544a91801d3a3ac918d7edbb8b6b158b1b9cab7f4853aad3 3 | size 151686 4 | -------------------------------------------------------------------------------- /data/transacciones.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:04b7063e257dc019f77c3300d1770734b48bf52938507c60b809de07f1509baf 3 | size 852638550 4 | -------------------------------------------------------------------------------- /resultados/etapas.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:13fde654afa6e4754801c0f7df3a0f4d1b2ce7d0c8f86353b465b93e3ba09491 3 | size 505183745 4 | -------------------------------------------------------------------------------- /resultados/tarjetas.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:06fb387d85cfc2e5cbfd2d0e6396cb56ef2adc0720fa798b64366291f31e9b37 3 | size 74438481 4 | -------------------------------------------------------------------------------- /resultados/viajes.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a0425491473ddeb095791b5a58604cf50a7a0502560e42d825a1e6255fda4899 3 | size 270429803 4 | -------------------------------------------------------------------------------- /informe/Matriz OD de Transporte Publico en base a datos SUBE.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EL-BID/Matriz-Origen-Destino-Transporte-Publico/HEAD/informe/Matriz OD de Transporte Publico en base a datos SUBE.pdf -------------------------------------------------------------------------------- /queries/1_crear_tablas_principales.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Este script crea las tablas e insumos fundamentales para el proceso de imputacion de destinos 3 | Para continuar deberá reemplazar PATH en todas las sentencias COPY 4 | */ 5 | 6 | -- Axtivar extensiones para postgis y los bindings de h3 7 | CREATE EXTENSION if not EXISTS postgis; 8 | CREATE EXTENSION if not exists h3; 9 | 10 | -- Tablas de paradas de transporte publico de AMBA 11 | CREATE TABLE paradas ( 12 | id serial PRIMARY KEY, 13 | id_linea numeric, 14 | id_ramal numeric , 15 | longitud numeric, 16 | latitud numeric, 17 | nombre_estacion text, 18 | h3 h3index 19 | ); 20 | 21 | COPY paradas(id,id_linea,id_ramal,nombre_estacion,longitud,latitud,h3) 22 | FROM '[PATH]/Matriz-Origen-Destino-Transporte-Publico/data/paradas.csv' 23 | CSV HEADER; 24 | 25 | -- Crear punto de parada, buffer e index espacial 26 | SELECT AddGeometryColumn ('public','paradas','geom',4326,'POLYGON',2); 27 | 28 | update paradas 29 | set geom = ST_Buffer(ST_SetSRID(ST_MakePoint(longitud, latitud),4326),0.03); 30 | 31 | CREATE INDEX paradas_geom_idx 32 | ON paradas 33 | USING GIST (geom); 34 | 35 | 36 | CREATE INDEX idx_paradas_linea 37 | ON paradas(id_linea); 38 | 39 | CREATE INDEX idx_paradas_ramal 40 | ON paradas(id_ramal); 41 | 42 | -- Tabla de lineas y ramales de transporte publico de AMBA 43 | CREATE TABLE lineas_ramales ( 44 | id_linea numeric, 45 | linea text, 46 | modo text, 47 | id_ramal numeric, 48 | ramal_corto text, 49 | ramal text, 50 | provincia text, 51 | municipio text 52 | ); 53 | 54 | COPY lineas_ramales(id_linea,linea,modo,id_ramal,ramal_corto,ramal,provincia,municipio) 55 | FROM '[PATH]/Matriz-Origen-Destino-Transporte-Publico/data/lineas_ramales.csv' 56 | CSV HEADER; 57 | 58 | 59 | -- Tabla con transacciones sube en formato original 60 | CREATE TABLE trx ( 61 | id serial PRIMARY KEY, 62 | id_tarjeta bigint, 63 | modo text, 64 | lat numeric, 65 | lon numeric, 66 | sexo text, 67 | interno_bus numeric, 68 | tipo_trx_tren text, 69 | etapa_red_sube numeric, 70 | id_linea numeric, 71 | id_ramal numeric, 72 | id_tarifa numeric, 73 | hora numeric 74 | ); 75 | 76 | COPY trx(id,id_tarjeta, modo, lat, lon, sexo, interno_bus, 77 | tipo_trx_tren, etapa_red_sube,id_linea, id_ramal, id_tarifa, hora) 78 | FROM '[PATH]/Matriz-Origen-Destino-Transporte-Publico/data/transacciones.csv' 79 | CSV HEADER; 80 | 81 | 82 | 83 | CREATE TABLE indices_h3 ( 84 | h3 h3index PRIMARY KEY, 85 | radio_2010 char(9), 86 | depto_2010 char(5), 87 | departamento text, 88 | provincia text 89 | ); 90 | 91 | 92 | COPY indices_h3(h3,radio_2010,depto_2010,departamento,provincia) 93 | FROM '[PATH]/Matriz-Origen-Destino-Transporte-Publico/data/indices_h3.csv' 94 | CSV HEADER; 95 | -------------------------------------------------------------------------------- /queries/4_construir_tablas_viajes_tarjetas.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Este script crea la tabla de viajes y de tarjetas a partir de las etapas 3 | */ 4 | 5 | -- Crear tabla viajes 6 | create table viajes as ( 7 | with primer_y_ultima_etapa as ( 8 | select e.id_tarjeta, e.id_viaje, e.id_etapa, e.hora, e.modo, 9 | FIRST_VALUE(parada_id_o) over (partition by id_tarjeta, id_viaje order by id_etapa, hora asc 10 | RANGE BETWEEN 11 | UNBOUNDED PRECEDING AND 12 | UNBOUNDED FOLLOWING) as parada_id_o, 13 | LAST_VALUE(parada_id_d) over (partition by id_tarjeta, id_viaje order by id_etapa, hora asc 14 | RANGE BETWEEN 15 | UNBOUNDED PRECEDING AND 16 | UNBOUNDED FOLLOWING) as parada_id_d, 17 | FIRST_VALUE(e.hora) over (partition by id_tarjeta, id_viaje order by id_etapa, hora asc 18 | RANGE BETWEEN 19 | UNBOUNDED PRECEDING AND 20 | UNBOUNDED FOLLOWING) as hora_o 21 | from etapas e 22 | ) 23 | select id_tarjeta, id_viaje, count(distinct id_etapa) cantidad_etapas, 24 | sum(CASE when modo = 'SUB' THEN 1 else 0 end) etapas_subte, 25 | sum(CASE when modo = 'TRE' THEN 1 else 0 end) etapas_tren, 26 | sum(CASE when modo = 'COL' THEN 1 else 0 end) etapas_colectivo, 27 | (array_agg(parada_id_o))[1] as parada_id_o, 28 | (array_agg(parada_id_d))[1] as parada_id_d, 29 | (array_agg(pu.hora_o))[1] as hora 30 | from primer_y_ultima_etapa as pu 31 | group by id_tarjeta, id_viaje 32 | ); 33 | 34 | -- clasificar viajes con etapas sin imputar destino correctamente 35 | alter table viajes 36 | add column etapas_incompletas bool; 37 | 38 | 39 | UPDATE viajes v 40 | SET etapas_incompletas = true 41 | FROM ( 42 | select distinct id_tarjeta, id_viaje 43 | from etapas 44 | where parada_id_d is null) p 45 | WHERE v.id_tarjeta = p.id_tarjeta 46 | and v.id_viaje = p.id_viaje; 47 | 48 | 49 | UPDATE viajes v 50 | SET etapas_incompletas = false 51 | where etapas_incompletas is not true; 52 | 53 | 54 | -- Crear tabla tarjetas 55 | create table tarjetas as ( 56 | select distinct id_tarjeta, FIRST_VALUE(parada_id_o) over (partition by id_tarjeta order by id_viaje asc 57 | RANGE BETWEEN 58 | UNBOUNDED PRECEDING AND 59 | UNBOUNDED FOLLOWING) as parada_hogar 60 | from viajes); 61 | 62 | create table tabla_sexo_tarjeta as 63 | with sexo_tarjetas as ( 64 | select distinct id_tarjeta,sexo 65 | from etapas 66 | where sexo <> '' 67 | ) 68 | select * 69 | from sexo_tarjetas 70 | where id_tarjeta not in ( 71 | -- tarjetas con mas de un sexo 72 | select id_tarjeta 73 | from sexo_tarjetas 74 | group by id_tarjeta 75 | having count(*) > 1 76 | ); 77 | 78 | alter table tarjetas 79 | add column sexo text; 80 | 81 | UPDATE tarjetas t 82 | SET sexo = st.sexo 83 | FROM tabla_sexo_tarjeta st 84 | WHERE t.id_tarjeta = st.id_tarjeta; 85 | 86 | drop table tabla_sexo_tarjeta; 87 | 88 | alter table tarjetas 89 | add column viajes_con_etapas_incompletas bool; 90 | 91 | 92 | UPDATE tarjetas t 93 | SET viajes_con_etapas_incompletas = true 94 | FROM ( 95 | select distinct id_tarjeta 96 | from viajes 97 | where etapas_incompletas = true) v 98 | WHERE t.id_tarjeta = v.id_tarjeta; 99 | 100 | UPDATE tarjetas t 101 | SET viajes_con_etapas_incompletas = false 102 | where viajes_con_etapas_incompletas is not true; 103 | 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Matriz-Origen-Destino-Transporte-Publico 3 | 4 | En este repositorio se encuentran los resultados de la matriz OD en base a datos SUBE para la Región Metropolitana de Buenos Aires (RMBA) para un día miércoles de noviembre representativo del año 2019, como así también el dataset de transacciones SUBE y los procedimientos para obtenerla mediante scripts de PostgresSQL + PostGIS. En el [informe](https://github.com/EL-BID/Matriz-Origen-Destino-Transporte-Publico/blob/main/informe/Matriz%20OD%20de%20Transporte%20Publico%20en%20base%20a%20datos%20SUBE.pdf) encontrarán un resumen de los principales resultados como así también una descripción detallada de la metodología. En el directorio `resultados/` encontrarán todos los resultados finales, con las tablas correspondientes a las **etapas**, **viajes** y **tarjetas**. Finalmente, en el directorio `queries/` encontrarán los scripts para obtener estos resultados a partir de los datos. 5 | 6 | Los datos SUBE fueron obtenidos mediante un pedido de acceso a la información pública (expediente *EX - 2020 - 32945006 - DNAIP#AAIP*). A criterio del área de incumbencia técnica, para preservar la privacidad de los usuarios se omitió la identificación de la tarjeta SUBE, enmascarando esa información (junto a los números de interno de los colectivos). Asimismo, para mayor resguardo de información personal se procedió a agregar espacial y temporalmente la información. No se ofrecen datos de los minutos en los que ocurrió la transacción (sólo la hora) y las coordenadas han sido truncadas a tres decimales (esto ofrece un margen de error de aproximadamente 100m). La información en el archivo transacciones intenta presentar el dataset original tal cual fue provisto, haciendo solo modificaciones al esquema de datos para ofrecerlo de la manera mas eficiente posible. Esta información, como otras tablas insumo necesarias para el proceso, se encuentran en el directorio `data/` del repositorio, siendo `transacciones.csv` el insumo principal con las transacciones SUBE otorgadas en el pedido de información pública. 7 | 8 | El procesamiento está hecho en PostgresSQL + PostGIS junto a la infraestructura de celdas hexagonales jerarquicas [H3 de Uber](https://eng.uber.com/h3/), para los que se utilizaron los bindings para Postgres desarrollados por [bytesandbrains](https://github.com/bytesandbrains) por [aqui](https://github.com/bytesandbrains/h3-pg). Las queries toman como principal insumo los archivos `transacciones.csv`, `paradas.csv` y `lineas_ramales.csv`, procesan esa información y elaboran las correspondientes matrices y tablas conexas. Para más detalles sobre la metodología pueden leer el informe final presente en este repositorio. 9 | 10 | 11 | ## Guía de usuario 12 | 13 | Para quienes quieran utilizar los microdatos de la matriz OD pueden simplemente utilizar los datos presentes en `resultados/`. La información relativa a las paradas, indices h3, lineas y ramales pueden encontrarla en `data/`, para hacer los joins mediante los ids. Por ejemplo, para georeferenciar cada origen y destino deberan unir con la tabla paradas mediante el `id`. A su vez, para obtener información contextual sobre cada indice `h3`, se debera unir el indice `h3` de la tabla `paradas` con el de la tabla `indices_h3`. 14 | 15 | Para quienes quieran reproducir y/o modificar algunos de los proedimientos del trabajo realizado deberán: 16 | 17 | 1. Instalar [Postgres](https://www.postgresql.org/) + [Postgis](https://postgis.net/) + [h3-pg](https://github.com/bytesandbrains/h3-pg). 18 | 19 | 2. Crear una base de datos. 20 | 21 | 3. Abrir el script `1_crear_tablas_principales.sql`, modificar `[PATH]` por la ruta donde se haya clonado el repositorio y ejecutarlo. 22 | 23 | 4. Correr los scripts en el siguiente orden: `2_construir_etapas.sql`, `3_imputar_destinos.sql` y `4_construir_tablas_viajes_tarjetas.sql`. 24 | 25 | 26 | ## Licencia 27 | 28 | Copyright© 2022. Banco Interamericano de Desarrollo ("BID"). Uso autorizado. [AM-331-A3](/LICENSE.md) 29 | 30 | 31 | ## Autores 32 | 33 | Felipe González ([@alephcero](https://github.com/alephcero/)) 34 | Sebastián Anaposlky([@sanapolsky](https://github.com/sanapolsky/)) 35 | 36 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /queries/3_imputar_destinos.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Este script imputa a cada etapa una parada de origen y de destino a las etapas. 3 | 4 | Cuando se calculan distancias se usan las de h3 que calcula el camino mas corto siguiendo celdas adyacentes. 5 | Las celdas utilizadas en este proceso tienen resolucion 10, es decir que el largo del hexagono tiene 66 m. 6 | Entre los centros de dos hexagonos adyacentes hay 132 m de distancia. 7 | 8 | Distancias de 15 hex significa ~ 2000 metros 9 | Distancias de 16 hex significa ~ 2100 metros 10 | Distancias de 17 hex significa ~ 2200 metros 11 | 12 | Selecciona para cada etapa una estacion de origen tomando aquella con la distancia minima 13 | siempre dentro de un area de influencia minima (buffer) de la estacion 14 | Se usa ramal para FFCC y Subte, linea para buses. Porque, por ej., si la etapa dice usar la linea C (considerada como ramal), 15 | hay que comparar la distancia contra ese ramal, y no todas las estaciones del subte (considerado como linea) 16 | */ 17 | 18 | create table distancia_minima_parada_o as ( 19 | with buses as ( 20 | select distinct on (e_id) * 21 | from ( 22 | -- selecciona la estaciones cercanas 23 | select 24 | e.id e_id, 25 | e.id_linea e_linea, 26 | e.id_ramal e_ramal, 27 | e.modo e_modo, 28 | e.h3 h3_etapas, 29 | p.id p_id, 30 | p.h3 h3_paradas, 31 | p.id_linea p_linea, 32 | p.id_ramal p_ramal, 33 | h3_distance(e.h3,p.h3) distancia 34 | from (select * from etapas where modo = 'COL') as e 35 | inner join paradas as p 36 | on e.id_linea = p.id_linea 37 | and ST_Intersects(e.geom, p.geom) 38 | ) d 39 | order by e_id, distancia), 40 | trenes as ( 41 | select distinct on (e_id) * 42 | from ( 43 | -- selecciona la estaciones cercanas 44 | select 45 | e.id e_id, 46 | e.id_linea e_linea, 47 | e.id_ramal e_ramal, 48 | e.modo e_modo, 49 | e.h3 h3_etapas, 50 | p.id p_id, 51 | p.h3 h3_paradas, 52 | p.id_linea p_linea, 53 | p.id_ramal p_ramal, 54 | h3_distance(e.h3,p.h3) distancia 55 | from (select * from etapas where modo = 'TRE') as e 56 | inner join paradas as p 57 | on e.id_ramal = p.id_ramal 58 | and ST_Intersects(e.geom, p.geom) 59 | ) d 60 | order by e_id, distancia), 61 | subtes as ( 62 | select distinct on (e_id) * 63 | from ( 64 | -- selecciona la estaciones cercanas 65 | select 66 | e.id e_id, 67 | e.id_linea e_linea, 68 | e.id_ramal e_ramal, 69 | e.modo e_modo, 70 | e.h3 h3_etapas, 71 | p.id p_id, 72 | p.h3 h3_paradas, 73 | p.id_linea p_linea, 74 | p.id_ramal p_ramal, 75 | h3_distance(e.h3,p.h3) distancia 76 | from (select * from etapas where modo = 'SUB') as e 77 | inner join paradas as p 78 | on e.id_ramal = p.id_ramal 79 | and ST_Intersects(e.geom, p.geom) 80 | ) d 81 | order by e_id, distancia) 82 | select * from subtes 83 | union 84 | select * from trenes 85 | union 86 | select * from buses 87 | ); 88 | 89 | 90 | --Agregar a la tabla etapas una columna para el id de parada de origen 91 | alter table etapas 92 | ADD COLUMN parada_id_o numeric; 93 | 94 | /*Imputar la parada de origen a la tabla etapa , siempre que la distancia a la parada de origen 95 | no sea mayor que a 800 metros (6 hexagonos h3 a resolucion 10) 96 | */ 97 | delete from distancia_minima_parada_o where distancia > 6; 98 | 99 | CREATE INDEX etapas_ids_distancia_minima_parada_o_e_id 100 | ON distancia_minima_parada_o(e_id); 101 | 102 | update etapas e 103 | set parada_id_o = d.p_id 104 | from distancia_minima_parada_o d 105 | where e.id = d.e_id; 106 | 107 | 108 | -- Elminar tabla insumo 109 | drop table distancia_minima_parada_o; 110 | 111 | -- Borrar transacciones con distancias muy largas a su parada de origen 112 | DELETE FROM etapas e where parada_id_o is null; 113 | 114 | -- Borrar tarjetas simple transaccion 115 | DELETE FROM etapas e 116 | USING ( select id_tarjeta, count(*) 117 | from etapas 118 | group by id_tarjeta 119 | having count(*) = 1) as u 120 | WHERE e.id_tarjeta = u.id_tarjeta; 121 | 122 | 123 | -------------------------------------------------------------------------------------------------------------------- 124 | -- IMPUTAR DESTINOS 125 | -------------------------------------------------------------------------------------------------------------------- 126 | /* 127 | Crear una tabla con los posibles destinos de cada etapa, empezando por asignar como pontencial destino 128 | la siguiente transaccion de esa misma tarjeta. Al ordenar por tipo de trx tren, el checkout queda 129 | como la siguiente transaccion y por ende, el destino potencial 130 | */ 131 | 132 | -- Se crea una tabla de potenciales destinos, con la siguiente transaccion como destino propuesto 133 | create table destinos as ( 134 | select id, id_tarjeta, id_etapa, id_viaje,id_linea,hora, tipo_trx_tren, 135 | LEAD(id,1) OVER ( 136 | PARTITION BY id_tarjeta 137 | ORDER BY id_viaje,id_etapa,tipo_trx_tren 138 | ) id_lead, 139 | LEAD(geom,1) OVER ( 140 | PARTITION BY id_tarjeta 141 | ORDER BY id_viaje,id_etapa,tipo_trx_tren 142 | ) geom, 143 | LEAD(h3,1) OVER ( 144 | PARTITION BY id_tarjeta 145 | ORDER BY id_viaje,id_etapa,tipo_trx_tren 146 | ) h3_lead, 147 | row_number () over ( 148 | PARTITION BY id_tarjeta 149 | ORDER BY id_viaje,id_etapa,tipo_trx_tren 150 | ) fila 151 | from etapas e 152 | ORDER BY id_viaje,id_etapa,tipo_trx_tren); 153 | 154 | 155 | CREATE INDEX idx_destinos_id_lead 156 | ON destinos(id_lead); 157 | 158 | CREATE INDEX idx_destinos_id 159 | ON destinos(id); 160 | 161 | CREATE INDEX idx_destinos_id_tarjeta 162 | ON destinos(id_tarjeta); 163 | 164 | -- La última transaccion del dia no tiene siguiente transaccion, por lo que se usa la primera del dia 165 | update destinos d 166 | set id_lead = p.primera 167 | from ( 168 | select distinct on (id_tarjeta) id_tarjeta, id as primera 169 | from destinos 170 | order by id_tarjeta, fila 171 | ) p 172 | where id_lead is null 173 | and d.id_tarjeta = p.id_tarjeta; 174 | 175 | 176 | -- Eliminar check outs a los que no nos interesa imputar destinos 177 | delete from destinos where tipo_trx_tren = 'CHECK OUT'; 178 | 179 | /* 180 | Agregar a la tabla de potenciales destinos los atributos geograficos del destino 181 | **/ 182 | update destinos d 183 | set 184 | geom = e.geom, 185 | h3_lead = e.h3 186 | from etapas e 187 | where d.id_lead = e.id 188 | and d.geom is null 189 | and d.h3_lead is null 190 | ; 191 | 192 | /* 193 | Se crea una tabla con la parada mas cercana al potencial destino 194 | */ 195 | 196 | CREATE INDEX destinos_geom_idx 197 | ON destinos 198 | USING GIST (geom); 199 | 200 | -- Para todas las paradas posibles del destino, elegir la que minimice la distancia 201 | create table distancia_minima_parada_d as ( 202 | select distinct on (id_tarjeta,id_viaje,id_etapa) * 203 | from ( 204 | select d.*,p.id as p_id, p.h3 as h3_parada, h3_distance(d.h3_lead,p.h3) distancia 205 | from destinos d 206 | inner join paradas as p 207 | on d.id_linea = p.id_linea 208 | and ST_Intersects(d.geom, p.geom) 209 | ) t 210 | order by id_tarjeta,id_viaje,id_etapa,tipo_trx_tren,distancia 211 | ); 212 | 213 | -- Elminar como pontenciales paradas de destino aquellas con mas de 2200 metros con respecto a la siguiente transaccion 214 | delete from distancia_minima_parada_d where distancia > 17; 215 | 216 | CREATE INDEX idx_distancia_minima_parada_d_id 217 | ON distancia_minima_parada_d(id); 218 | 219 | alter table etapas 220 | ADD COLUMN parada_id_d numeric; 221 | 222 | vacuum full etapas; 223 | 224 | -- Agregar parada destino a la tabla etapas 225 | update etapas e 226 | set parada_id_d = d.p_id 227 | from distancia_minima_parada_d d 228 | where e.id = d.id; 229 | 230 | -- Se eliminan checkouts que no son etapas propiamente dichas, sino destinos de etapas 231 | delete from etapas where tipo_trx_tren = 'CHECK OUT'; 232 | 233 | 234 | select count(*) from etapas where parada_id_d is not null; 235 | 236 | -- eliminar tablas insumo 237 | DROP TABLE destinos; 238 | DROP TABLE distancia_minima_parada_d; 239 | 240 | 241 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## AM-331-A3 Licencia de Software 2 | Effective: April 2018 3 | Contenido de la página 4 | 5 | El Software, con excepción de los Documentos de Soporte y Uso, deberá estar sujetos a los siguientes términos y condiciones, los cuales se empaquetarán como parte de cada Software bajo un archivo que llevará el nombre de "LICENCIA" : 6 | "Copyright © [2022]. Banco Interamericano de Desarrollo ("BID"). Uso autorizado." 7 | 8 | ### 1. Licencia 9 | Por medio de la presente licencia ("Licencia") no exclusiva, revocable, global y libre de regalías el BID otorga permiso al usuario ("Usuario") para reproducir, distribuir, ejecutar públicamente, prestar y poner a disposición del público, y modificar el software y sus modificaciones, por sí o como parte de una colección, siempre que sea para fines no comerciales, sujeto a los términos y condiciones aquí señalados. 10 | Salvo indicación en contrario, la Documentación de Soporte y Uso del software se licenciará bajo Creative Commons IGO 3.0 Atribución-NoComercial-SinObraDerivada (CC-IGO 3.0 BY-NC-ND). 11 | 12 | #### 2. Definiciones 13 | 2.1 Software: conjunto de programas, instrucciones y reglas informáticas que permiten ejecutar tareas en una computadora a fin de gestionar un determinado proceso u obtener un determinado resultado. El Software incluye (i) código fuente, (ii) código objeto y (iii) Documentación de Soporte y Uso. 14 | El Software puede ser del tipo, pero sin estar limitado a (i) programa ejecutable desde el computador, (ii) aplicación móvil y de escritorio, (iii) algoritmo y (iv) hoja de cálculo que contienen macros, así como otras instrucciones para simular, proyectar o realizar otros cálculos. 15 | 2.2 Código Fuente: conjunto de líneas de texto con los pasos que debe seguir la computadora para ejecutar el Software. Puede estar compuesto por un número indeterminado de documentos, con distintas extensiones y organizados en carpetas. 16 | 2.3 Código Objeto: código que resulta de la compilación del Código Fuente. La compilación es un proceso informático que traduce el Código Fuente en lenguaje máquina o bytecode. 17 | 2.4 Documentación de Soporte y Uso (la "Documentación"): se refiere a la información de acompañamiento al código fuente y objeto que permite a un humano comprender los objetivos, arquitectura y lenguaje de programación de Software. 18 | 2.5 Software Derivado: obras derivadas del Software, tales como modificaciones, actualizaciones y mejoras de la misma. 19 | 2.6 Usuario: cualquier persona, natural o jurídica, que obtenga una copia del Software. 20 | 21 | ### 3. Derechos del BID 22 | 3.1 El BID se reserva todos los derechos de propiedad intelectual, incluyendo sin limitación derechos de autor, relacionados con o asociados al Software. 23 | 3.2 El BID se reserva expresamente los derechos de ceder, transferir y/o sub-licenciar el Software y/o cualquiera de sus componentes a terceros sin previo aviso. 24 | 25 | ### 4. Derechos del Usuario sobre Software Derivado 26 | El Usuario que desarrolle Software Derivado retendrá todos los derechos de propiedad intelectual, incluyendo sin limitación derechos de autor, relacionados con o asociados al Software Derivado, en el entendido que dicho Software Derivado y cualquier otra edición futura estén sujetas a los mismos términos y condiciones de esta Licencia. 27 | 28 | ### 5. Restricciones 29 | 5.1 El Usuario sólo está autorizado a hacer uso del Software conforme se describe en esta Licencia. 30 | 5.2 Con excepción de esta Licencia, el BID no otorga ninguna otra licencia al Usuario con respecto a cualquier otra información u obra propiedad del BID o de cualquier derecho de autor, marcas o cualquier otro derecho de propiedad intelectual del BID. Cualquier licencia adicional deberá ser por escrito y firmada por un representante del BID debidamente autorizado para tales fines. 31 | 5.3 La Licencia no constituye una venta del Software ni de cualquier parte o copia de la misma. 32 | 5.4 El Usuario no podrá usar ni permitir que otros usen el Software para fines comerciales. 33 | 5.5 El Usuario sólo podrá autorizar el uso del Software a terceros de conformidad con lo establecido en esta Licencia, sin que en ningún caso los terceros puedan adquirir más derechos sobre el Software que los expresamente otorgados por el BID mediante esta Licencia. 34 | 35 | ### 6. Reconocimiento 36 | 6.1 El Usuario deberá mantener los siguientes enunciados y exenciones en el archivo principal de la Documentación del Software: 37 | "Copyright © [año]. Banco Interamericano de Desarrollo ("BID"). Uso autorizado. 38 | Los procedimientos y resultados obtenidos en base a la ejecución de este software son los programados por los desarrolladores y no necesariamente reflejan el punto de vista del BID, de su Directorio Ejecutivo ni de los países que representa." 39 | 6.1.1 En el caso de Software del Fondo Multilateral de Inversiones ("FOMIN"), la exención de responsabilidad deberá ser: "Las opiniones expresadas en esta obra son de los autores y no necesariamente reflejan el punto de vista del BID, de su Directorio Ejecutivo ni de los países que representa, así como tampoco del Comité de Donantes del FOMIN ni de los países que representa." 40 | 6.2 El Usuario podrá incluir en el Software Derivado una referencia al Software como obra original, siempre y cuando dicho aviso no genere confusión alguna respecto a la titularidad de los derechos del BID sobre el Software. 41 | 42 | ### 7. Nombre y Logo del BID 43 | El Usuario no podrá hacer uso del nombre y/o logo del BID para fines diferentes a los aquí estipulados, ni podrá hacer promesas, ni adquirir compromisos u obligaciones, ni otorgar garantías de ninguna clase en nombre del BID. 44 | 45 | ### 8. Declaraciones y Garantías 46 | 8.1 El BID otorga esta Licencia sin garantía explícita o implícita de ningún género, objetiva o subjetiva, por responsabilidad contractual o extracontractual, lo que comprende, sin consistir en una enumeración taxativa, garantías de comerciabilidad, adecuación, cumplimiento de normas o requisitos o aplicabilidad para un fin determinado. 47 | 8.2 El BID no garantiza que el funcionamiento del Software será ininterrumpido o libre de errores y no asume obligación alguna de actualizar, corregir ni introducir mejoras en el Software. 48 | 8.3 El Usuario asume exclusivamente el riesgo por su utilización, y así deberá informarlo a terceros cuando utilice, distribuya o ponga el Software a disposición de terceros. 49 | 50 | ### 9. Limitación de Responsabilidad 51 | 9.1 El BID no será responsable, bajo circunstancia alguna, de daño ni indemnización, moral o patrimonial; directo o indirecto; accesorio o especial; o por vía de consecuencia, previsto o imprevisto, que pudiese surgir: 52 | 9.1.1 Bajo cualquier teoría de responsabilidad, ya sea por contrato, infracción de derechos de propiedad intelectual, negligencia o bajo cualquier otra teoría; y/o 53 | 9.1.2 A raíz del uso del Software, incluyendo, pero sin limitación de potenciales defectos en el Software, o la pérdida o inexactitud de los datos de cualquier tipo. Lo anterior incluye los gastos o daños asociados a fallas de comunicación y/o fallas de funcionamiento de computadoras, vinculados con la utilización del Software. 54 | 55 | ### 10. Indemnización 56 | 10.1 El Usuario se obliga a liberar, defender e indemnizar al BID, su personal y consultores, conforme sea aplicable, de cualquier reclamo, queja, acción, pérdida, demanda, responsabilidad, obligación, daño, costo, incluyendo sin limitación, honorarios de abogados, que pudiesen emprender contra el BID, su personal y/o consultores en virtud de: 57 | 10.1.1 El ejercicio de los derechos otorgados por el BID bajo esta Licencia. 58 | 10.1.2 Incumplimiento de los términos y condiciones de esta Licencia por parte del Usuario. 59 | 10.1.3 Infracción de derechos de autor de terceros por parte del Usuario con relación al uso del Software y el desarrollo de Software Derivado. 60 | 61 | ### 11. Terminación de la Licencia 62 | El BID podrá terminar de manera inmediata esta Licencia, con causa o sin causa, sin dar aviso previo al Usuario. La terminación con causa aplica en caso de que el BID determine, a su entera discreción, que el uso del Software es inconsistente con los términos y condiciones de esta Licencia. 63 | 64 | ### 12. Devolución del Sistema Informático 65 | En caso de terminación de esta Licencia, indistintamente de la causa de terminación y conforme decida el BID, el Usuario deberá inmediatamente cesar el uso del Software y deberá destruir y/o devolver al BID cualesquiera programas, códigos, accesos, archivos o información, impresa y digital, que sean necesarios para que el BID tenga control sobre el Software, sin incluir medida de protección tecnológica alguna. En caso de que el Usuario haya desarrollado Software Derivado y el BID termine la Licencia, el Usuario deberá obtener autorización del BID, por escrito, para poder seguir usando el Software. 66 | 67 | ### 13. Ley Aplicable 68 | Esta Licencia estará sujeta a y será interpretada de conformidad con las leyes del Distrito de Columbia de los Estados Unidos de América, con excepción de sus disposiciones respecto a conflicto de leyes. 69 | 70 | ### 14. Privilegios e Inmunidades 71 | Ninguna cláusula de esta Licencia podrá ser interpretada como un acto de renuncia por parte del BID o de sus funcionarios y empleados a los privilegios e inmunidades que le han sido concedidos como organización internacional pública por su Convenio Constitutivo, por el derecho internacional o por las leyes de cualquiera de sus países miembros. 72 | 73 | ### 15. Resolución de Disputas 74 | Las Partes se comprometen a resolver cualquier diferencia o disputa relacionada con esta Licencia de buena fe y mediante un arreglo amigable. Si al cabo de treinta (30) días calendario de la fecha en que una Parte le comunique a la otra Parte su disconformidad con una diferencia o disputa las Partes no han llegado a un acuerdo satisfactorio para ambas Partes, dicha diferencia o disputa será sometida a arbitraje de conformidad con las reglas de la American Arbitration Association. La determinación final le corresponderá a un único árbitro. El lugar del arbitraje será Washington, Distrito de Columbia, Estados Unidos de América. El idioma que se usará en el proceso de arbitraje será el inglés con traducción simultánea en cualquiera de los idiomas oficiales del BID, si el BID lo solicitara. Los gastos del arbitraje serán cubiertos por ambas Partes en igual proporción. 75 | 76 | ### 16. Relación entre las Partes 77 | Nada de lo contenido en esta Licencia se interpretará como el establecimiento o creación de una asociación ni relación empleador-empleado entre las Partes, las cuales en todo momento permanecerán como contratistas independientes. 78 | 79 | ### 17. Divisibilidad 80 | Si cualquier cláusula de esta Licencia es considerada inválida o inexigible, dicha invalidez o inexigibilidad no afectará a la validez ni la exigibilidad de las demás cláusulas, y dicha cláusula inválida o inexigible se considerará eliminada de esta Licencia. 81 | 82 | ### 18. Validez de Obligaciones 83 | En caso de terminación de esta Licencia sobrevivirán los derechos y las obligaciones previstas en las cláusulas Nos. 3, 7, 8, 9, 10, 13, 14, 15 y 19. 84 | 85 | ### 19. Notificaciones 86 | Cualquier notificación que se requiera en el marco de esta Licencia se hará por escrito al BID a la siguiente cuenta de correo electrónico: code@iadb.org. El BID podrá modificar esta cláusula sin dar previo aviso al Usuario. 87 | 88 | ### 20. Enmienda 89 | Esta Licencia sólo podrá ser modificada mediante autorización previa, expresa y por escrita del BID. 90 | 91 | ### 21. Acuerdo Final 92 | Esta Licencia constituye el acuerdo final entre las Partes y reemplaza todas las comunicaciones, entendimientos o acuerdos, escritos o verbales, de carácter previo entre las Partes con relación al objeto de esta Licencia. 93 | 94 | -------------------------------------------------------------------------------- /queries/2_construir_etapas.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Este script crea la tabla de etapas, reconstruyendo la cadena de viejas y etapas con sus 3 | correspondientes ids. 4 | */ 5 | 6 | -- Crear tabla etapas con transacciones con id tarjeta y eliminar checkouts sin checkin 7 | create table etapas as ( 8 | select * 9 | from trx t 10 | where t.id_tarjeta is not null 11 | and ( 12 | tipo_trx_tren <> 'CHECK OUT SIN CHECKIN' or tipo_trx_tren is null 13 | ) 14 | ); 15 | 16 | 17 | CREATE INDEX idx_etapas 18 | ON etapas(id); 19 | 20 | CREATE INDEX idx_etapas_tarjeta 21 | ON etapas(id_tarjeta); 22 | 23 | 24 | -------------------------------------------------------------------------------------------------------------------------------- 25 | -- CREAR ID ETAPA Y ID VIAJE 26 | -------------------------------------------------------------------------------------------------------------------------------- 27 | 28 | /* 29 | Crear tabla insumo de ids etapas viajes para poder crear los ids 30 | Para cada tarjeta, ordena por hora, etapa red sube y tipo de transaccion 31 | crea un id_etapa con un incremental para las transacciones de usos (no checkouts) 32 | */ 33 | create table ids_etapas_viajes as ( 34 | select id, id_tarjeta, hora, tipo_trx_tren, etapa_red_sube, 35 | sum( 36 | CASE WHEN tipo_trx_tren <> 'CHECK OUT' or tipo_trx_tren is null THEN 1 ELSE 0 END) 37 | OVER (PARTITION BY id_tarjeta ORDER BY hora, etapa_red_sube, tipo_trx_tren) AS id_etapa 38 | FROM etapas 39 | order by id_tarjeta, hora, etapa_red_sube, tipo_trx_tren 40 | ); 41 | 42 | 43 | -- Agregar un id viaje temporal 44 | alter table ids_etapas_viajes 45 | add column id_viaje_temp int8; 46 | 47 | -- Crear un id de viaje temporal que no es secuencial 48 | update ids_etapas_viajes e 49 | set id_viaje_temp = id_etapa - etapa_red_sube; 50 | 51 | /* 52 | Al no contar con un timestamp que permita ordenar en el tiempo las transacciones y solo tener hora y etapa red sube 53 | hay un problema para ordenar en el tiempo y con los ids cuando a un Check Out le sigue un uso dentro de la misma hora. 54 | Algunas transacciones checkout quedan identificadas con un id_etapa correspondiente a la siguiente etapa y con un id_viaje 55 | propio, sin que ninguno de los dos coincida con la etapa y viaje correspondiente. 56 | 57 | Un ejemplo es el id_tarjeta = 37035823 en las dos transacciones de las 17hs, donde el check out deberia coincidir 58 | con el id de la etapa y el viaje del checkin. Tambien la tarjeta 5539503909, con dos suceso de este tipo. Las queries siguientes procuran solucionarlo 59 | 60 | 61 | Sin embrago para subte, cuando una misma tarjeta hace dos transacciones en el mismo ramal del subte (por ej linea H) a la misma hora, al no haber integracion 62 | tarifaria marcada en etapa_red_sube no hay forma de ordenar en el tiempo las transacciones dentro de esa hora. Por ej tarjeta 7239578027. 63 | Se podría buscar un criterio de minimizacion de distancias con respecto a las transacciones anteriores o posteriores para ordenar, cambiar 64 | para cada hora de las transacciones en subte en la misma hora por la hora de la transaccion mas cercana en el espacio y reasignar el id etapa. 65 | La tarjeta 7239578027 es un caso donde no hay transaccion posterior y deberia usarse solo la anterior. 66 | */ 67 | 68 | ----------------------------------------------------------------------------------------------------- 69 | -- Solucion checkout seguido de transaccion en la misma hora 70 | ----------------------------------------------------------------------------------------------------- 71 | 72 | -- Crear una tabla con los id viaje 73 | create table viajes_solo_checkout as ( 74 | select id_tarjeta, id_viaje_temp 75 | from ( 76 | select id_tarjeta, id_viaje_temp, count(*) as trxs, sum(case when tipo_trx_tren = 'CHECK OUT' then 1 else 0 end) as checksouts 77 | from ids_etapas_viajes 78 | group by id_tarjeta, id_viaje_temp) tabla 79 | where checksouts = trxs 80 | ); 81 | 82 | alter table viajes_solo_checkout 83 | add column viaje_target numeric, 84 | add column etapa_target numeric; 85 | 86 | 87 | 88 | --Para todos los id viajes que sean solo checkout, se reemplaza su id por el id del viaje anterior (el del checkin) 89 | with viajes_anteriores_al_checkout as ( 90 | select distinct on (iev.id_tarjeta,vsc.id_viaje_temp) iev.id_tarjeta, vsc.id_viaje_temp, iev.id_viaje_temp as viaje_target 91 | from ids_etapas_viajes iev, viajes_solo_checkout vsc 92 | where iev.id_tarjeta = vsc.id_tarjeta 93 | and vsc.id_viaje_temp > iev.id_viaje_temp 94 | order by id_tarjeta,id_viaje_temp desc,viaje_target desc 95 | ) 96 | update viajes_solo_checkout vsc 97 | set viaje_target = vt.viaje_target 98 | from viajes_anteriores_al_checkout vt 99 | where vsc.id_tarjeta = vt.id_tarjeta 100 | and vsc.id_viaje_temp = vt.id_viaje_temp; 101 | 102 | -- Dentro de cada tarjeta y viaje, se reemplaza el id_etapa de las transacciones solo con checkout por el id de la etapa del checkin 103 | with etapas_anteriores_al_checkout as ( 104 | select distinct iev.id_tarjeta, vsc.id_viaje_temp, id_etapa as etapa_target 105 | from ids_etapas_viajes iev, viajes_solo_checkout vsc 106 | where iev.id_tarjeta = vsc.id_tarjeta 107 | and vsc.id_viaje_temp > iev.id_viaje_temp 108 | and tipo_trx_tren = 'CHECK IN'), 109 | etapas_target as ( 110 | select id_tarjeta, id_viaje_temp, max(etapa_target) as etapa_target 111 | from etapas_anteriores_al_checkout 112 | group by id_tarjeta, id_viaje_temp 113 | order by id_tarjeta,id_viaje_temp 114 | ) 115 | update viajes_solo_checkout vsc 116 | set etapa_target = et.etapa_target 117 | from etapas_target et 118 | where vsc.id_tarjeta = et.id_tarjeta 119 | and vsc.id_viaje_temp = et.id_viaje_temp; 120 | 121 | 122 | -- Actualizar la tabla de ids con los nuevos correspondientes a los checkouts mal asignados 123 | update ids_etapas_viajes iev 124 | set 125 | id_viaje_temp = vsc.viaje_target , 126 | id_etapa = vsc.etapa_target 127 | from viajes_solo_checkout vsc 128 | where iev.id_tarjeta = vsc.id_tarjeta 129 | and iev.id_viaje_temp = vsc.id_viaje_temp; 130 | 131 | 132 | -- Eliminar tabla insumo 133 | drop table viajes_solo_checkout; 134 | 135 | /* 136 | El haber elminado ids de viajes que eran solo checkout, deja un id viaje con hiatos en la secuencia 137 | Se reemplazan por una secuencia para cada tarjeta 138 | */ 139 | 140 | alter table ids_etapas_viajes 141 | add column id_viaje numeric; 142 | 143 | 144 | -- Sumar nuevos ids a la tabla ids 145 | update ids_etapas_viajes ev 146 | set id_viaje = v.id_viaje 147 | from ( 148 | select *, row_number () over (partition by id_tarjeta order by id_tarjeta, id_viaje_temp) id_viaje 149 | from ( 150 | select distinct id_tarjeta, id_viaje_temp 151 | from ids_etapas_viajes 152 | order by id_tarjeta, id_viaje_temp 153 | ) viajes_temp 154 | ) v 155 | where ev.id_tarjeta = v.id_tarjeta 156 | and ev.id_viaje_temp = v.id_viaje_temp; 157 | 158 | 159 | -- Agregar columnas de ids etapas y viejas a tabla etapas 160 | alter table etapas 161 | add column id_etapa numeric, 162 | add column id_viaje numeric; 163 | 164 | CREATE INDEX idx_ids_etapas_viajes 165 | ON ids_etapas_viajes(id); 166 | 167 | -- agregar id_etapa e id_viaje a tabla de etapas 168 | update etapas e 169 | set id_etapa = t.id_etapa, 170 | id_viaje = t.id_viaje 171 | from ids_etapas_viajes t 172 | where e.id = t.id; 173 | 174 | drop table ids_etapas_viajes; 175 | 176 | /* 177 | Eliminar etapas con problemas de geolocalizacion 178 | */ 179 | -- asignar h3 180 | alter table etapas 181 | add column h3 h3index; 182 | 183 | update etapas 184 | set h3 = h3_geo_to_h3(POINT(lon,lat), 10); 185 | 186 | 187 | 188 | -- Borrar toda las etapas con transacciones fuera de un rango logico de latong o sin latlong 189 | delete from etapas 190 | where lat < -36 191 | or lat > -33 192 | or lon <-61 193 | or lon > -57 194 | or h3 is null; 195 | 196 | -- Borrar tarjetas simple transaccion. 197 | DELETE FROM etapas e 198 | USING ( select id_tarjeta, count(*) 199 | from etapas 200 | group by id_tarjeta 201 | having count(*) = 1) as u 202 | WHERE e.id_tarjeta = u.id_tarjeta; 203 | 204 | 205 | 206 | /* 207 | Asignar el ide linea en base al id ramal de acuerdo a la tabla linea ramales 208 | El id linea que viene en las transacciones sube no coincide con nuestra definicion de linea. 209 | Por ejemplo, el subte no es una unica linea. 210 | */ 211 | UPDATE etapas 212 | SET id_linea = lineas_ramales.id_linea 213 | FROM lineas_ramales 214 | WHERE etapas.id_ramal = lineas_ramales.id_ramal; 215 | 216 | 217 | /* 218 | Una misma tarjeta puede usarse dos veces en el mismo colectivo o molinete, ya sea porque viajan dos personas 219 | o por error. Decidimos eliminar uno de esos registros. Cada criterio de duplicado varia segun modo 220 | */ 221 | 222 | -- COLECTIVOS 223 | -- borrar casos que repiten tarjeta, hora, etapa e interno en bus 224 | with dups as ( 225 | select e.id, e.id_tarjeta,e.id_linea, e.interno_bus, e.hora, e.etapa_red_sube 226 | from etapas e, 227 | ( 228 | select id_tarjeta,id_linea, interno_bus, hora, etapa_red_sube, count(*) 229 | from etapas 230 | where modo = 'COL' 231 | group by id_tarjeta,id_linea, interno_bus, hora, etapa_red_sube 232 | having count(*) > 1 233 | ) d 234 | where e.id_tarjeta = d.id_tarjeta 235 | and e.id_linea = d.id_linea 236 | and e.interno_bus = d.interno_bus 237 | and e.hora = d.hora 238 | and e.etapa_red_sube = d.etapa_red_sube 239 | ) 240 | delete from etapas e 241 | using dups d 242 | where e.id < d.id 243 | and e.id_tarjeta = d.id_tarjeta 244 | and e.id_linea = d.id_linea 245 | and e.interno_bus = d.interno_bus 246 | and e.hora = d.hora 247 | and e.etapa_red_sube = d.etapa_red_sube ; 248 | 249 | 250 | 251 | -- SUBTE 252 | -- borrar casos que repiten tarjeta, hora, etapa en SUBTE 253 | with dups as ( 254 | select e.id, e.id_tarjeta,e.id_ramal,e.lat,e.lon, e.hora, e.etapa_red_sube 255 | from etapas e, 256 | ( 257 | select id_tarjeta,id_ramal,lat,lon,hora, etapa_red_sube, count(*) 258 | from etapas 259 | where modo = 'SUB' 260 | group by id_tarjeta,hora,id_ramal,lat,lon,etapa_red_sube 261 | having count(*) > 1 262 | ) d 263 | where e.id_tarjeta = d.id_tarjeta 264 | and e.id_ramal = d.id_ramal 265 | and e.hora = d.hora 266 | and e.lat = d.lat 267 | and e.lon = d.lon 268 | and e.etapa_red_sube = d.etapa_red_sube 269 | ) 270 | delete from etapas e 271 | using dups d 272 | where e.id < d.id 273 | and e.id_tarjeta = d.id_tarjeta 274 | and e.id_ramal = d.id_ramal 275 | and e.hora = d.hora 276 | and e.etapa_red_sube = d.etapa_red_sube ; 277 | 278 | 279 | 280 | -- BORRAR DUPS TREN 281 | with dups as ( 282 | select e.id, e.id_tarjeta,e.id_linea, e.lat,e.lon,e.tipo_trx_tren, e.hora, e.etapa_red_sube 283 | from etapas e, 284 | ( 285 | select id_tarjeta,id_linea,lat,lon,tipo_trx_tren, hora, etapa_red_sube, count(*) 286 | from etapas 287 | where modo = 'TRE' 288 | group by id_tarjeta,id_linea,lat,lon,tipo_trx_tren, hora, etapa_red_sube 289 | having count(*) > 1 290 | ) d 291 | where e.id_tarjeta = d.id_tarjeta 292 | and e.id_linea = d.id_linea 293 | and e.hora = d.hora 294 | and e.etapa_red_sube = d.etapa_red_sube 295 | and e.lat = d.lat 296 | and e.lon = d.lon 297 | and e.tipo_trx_tren = d.tipo_trx_tren 298 | ) 299 | delete from etapas e 300 | using dups d 301 | where e.id < d.id 302 | and e.id_tarjeta = d.id_tarjeta 303 | and e.id_linea = d.id_linea 304 | and e.hora = d.hora 305 | and e.etapa_red_sube = d.etapa_red_sube 306 | and e.lat = d.lat 307 | and e.lon = d.lon 308 | and e.tipo_trx_tren = d.tipo_trx_tren; 309 | 310 | 311 | -- Al eliminar estas transacciones pueden quedar tarjeta con una unica transaccion. 312 | DELETE FROM etapas e 313 | USING ( select id_tarjeta, count(*) 314 | from etapas 315 | group by id_tarjeta 316 | having count(*) = 1) as u 317 | WHERE e.id_tarjeta = u.id_tarjeta; 318 | 319 | 320 | -------------------------------------------------------------------------------------------------------------- 321 | -- Solucion para doble transaccion misma linea misma hora, sin integracion y sin etapa red sube que ordene secuencialmente 322 | ------------------------------------------------------------------------------------------------------ 323 | 324 | drop table if exists nuevos_ids_con_etapa_posterior; 325 | 326 | -- Crear una tabla para asignar un id nuevo minimizando la distancia con la trx posterior 327 | create table nuevos_ids_con_etapa_posterior as ( 328 | -- Detectar tarjetas misma hora y linea y etapa red sube 329 | with etapas_duplicadas as ( 330 | select id_tarjeta, id_etapa 331 | from etapas 332 | where modo in ('SUB', 'COL') 333 | group by id_tarjeta, id_etapa 334 | having count(*) >1 335 | ), 336 | -- Detectar la transaccion posterior a las transacciones duplicadas 337 | etapas_posteriores as ( 338 | select distinct on (ed.id_tarjeta, ed.id_etapa) e.id_etapa as id_etapa_posterior, ed.id_tarjeta , ed.id_etapa 339 | from etapas_duplicadas ed, etapas e 340 | where ed.id_tarjeta = e.id_tarjeta 341 | and ed.id_etapa < e.id_etapa 342 | ORDER BY ed.id_tarjeta, ed.id_etapa, e.id_etapa 343 | ), 344 | -- De las transacciones posteriores, usar los checking 345 | etapas_sin_chkout as ( 346 | select * from etapas where tipo_trx_tren <> 'CHECK OUT' or tipo_trx_tren is null 347 | ), 348 | -- Calcular distancias 349 | distancias_entre_etapas as( 350 | select ep.*, e1.id as id_trx_etapa, e1.h3 as h3_etapa, e2.id as id_trx_etapa_post, e2.h3 as h3_posterior, h3_distance(e1.h3, e2.h3) as distancia_etapas 351 | from etapas_posteriores ep 352 | --inner join etapas e1 353 | inner join etapas_sin_chkout e1 354 | on ep.id_tarjeta = e1.id_tarjeta 355 | and ep.id_etapa = e1.id_etapa 356 | inner join etapas_sin_chkout e2 357 | on ep.id_tarjeta = e2.id_tarjeta 358 | and ep.id_etapa_posterior = e2.id_etapa 359 | order by id_tarjeta, id_etapa, id_etapa_posterior 360 | ), 361 | -- Calcular nuevo id de etapa 362 | nuevo_id_etapa as ( 363 | select id_tarjeta, id_etapa, id_etapa_posterior, distancia_etapas,id_trx_etapa,id_trx_etapa_post, 364 | row_number () over ( 365 | PARTITION BY id_tarjeta,id_etapa 366 | ORDER BY id_etapa, id_etapa_posterior,distancia_etapas asc 367 | ) - 1 as n_fila 368 | from distancias_entre_etapas 369 | ), 370 | -- Puede haber una etapa posterior donde hay doble transaccion 371 | chequeo_doble_posterior as ( -- casos como id tarjeta 39005685 que tienen una doble transaccion por delante 372 | select distinct on (id_tarjeta, id_etapa, id_etapa_posterior,id_trx_etapa) * 373 | from nuevo_id_etapa 374 | order by id_tarjeta, id_etapa, id_etapa_posterior,id_trx_etapa,n_fila 375 | ) 376 | -- Minimizar distancia 377 | select id_tarjeta, id_etapa, id_etapa_posterior, distancia_etapas, id_trx_etapa, id_trx_etapa_post, 378 | id_etapa - (row_number () over ( 379 | PARTITION BY id_tarjeta,id_etapa 380 | ORDER BY n_fila asc 381 | ) - 1) as nuevo_id_etapa 382 | from chequeo_doble_posterior 383 | order by id_tarjeta, id_etapa, nuevo_id_etapa 384 | ); 385 | 386 | delete from nuevos_ids_con_etapa_posterior 387 | where id_etapa = nuevo_id_etapa; 388 | 389 | CREATE INDEX idx_nuevos_ids_con_etapa_posterior 390 | ON nuevos_ids_con_etapa_posterior(id_trx_etapa); 391 | 392 | -- Actualizar tabla etapas con los nuevos id posterior 393 | update etapas e 394 | set id_etapa = np.nuevo_id_etapa 395 | from nuevos_ids_con_etapa_posterior np 396 | where e.id = np.id_trx_etapa; 397 | 398 | drop table if exists nuevos_ids_con_etapa_posterior; 399 | 400 | 401 | -- Crear una tabla para asignar un id nuevo minimizando la distancia con la trx posterior 402 | drop table if exists nuevos_ids_con_etapa_anterior; 403 | 404 | create table nuevos_ids_con_etapa_anterior as ( 405 | with etapas_duplicadas as ( 406 | select id_tarjeta, id_etapa 407 | from etapas 408 | where modo in ('SUB', 'COL') 409 | group by id_tarjeta, id_etapa 410 | having count(*) >1 411 | ), 412 | etapas_anteriores as ( 413 | select distinct on (ed.id_tarjeta, ed.id_etapa) e.id_etapa as id_etapa_anterior, ed.id_tarjeta , ed.id_etapa, 414 | e.id as id_trx_etapa_pre, e.h3 as h3_anterior 415 | from etapas_duplicadas ed, etapas e 416 | where ed.id_tarjeta = e.id_tarjeta 417 | and ed.id_etapa > e.id_etapa 418 | ORDER BY ed.id_tarjeta, ed.id_etapa, e.id_etapa desc, e.tipo_trx_tren desc -- prioriza el check out en etapa anterior 419 | ), 420 | distancias_entre_etapas as( 421 | select ep.*, e1.id as id_trx_etapa, e1.h3 as h3_etapa, 422 | h3_distance(e1.h3, ep.h3_anterior) as distancia_etapas 423 | from etapas_anteriores ep 424 | inner join etapas e1 425 | on ep.id_tarjeta = e1.id_tarjeta 426 | and ep.id_etapa = e1.id_etapa 427 | order by id_tarjeta, id_etapa, id_etapa_anterior 428 | ), 429 | nuevo_id_etapa as ( 430 | select id_tarjeta, id_etapa, id_etapa_anterior, distancia_etapas,id_trx_etapa,id_trx_etapa_pre, 431 | id_etapa - (row_number () over ( 432 | PARTITION BY id_tarjeta,id_etapa 433 | ORDER BY id_etapa, id_etapa_anterior,distancia_etapas desc 434 | ) - 1) as nuevo_id_etapa_pre 435 | from distancias_entre_etapas 436 | ) 437 | select * 438 | from nuevo_id_etapa 439 | order by id_tarjeta, id_etapa, id_etapa_anterior 440 | ); 441 | 442 | delete from nuevos_ids_con_etapa_anterior 443 | where id_etapa = nuevo_id_etapa_pre; 444 | 445 | CREATE INDEX idx_nuevos_ids_con_etapa_anterior 446 | ON nuevos_ids_con_etapa_anterior(id_trx_etapa); 447 | 448 | -- Actualizar etapas con los nuevos id anterior 449 | update etapas e 450 | set id_etapa = np.nuevo_id_etapa_pre 451 | from nuevos_ids_con_etapa_anterior np 452 | where e.id = np.id_trx_etapa; 453 | 454 | drop table if exists nuevos_ids_con_etapa_anterior; 455 | 456 | -- Las que no tienen anterior ni posterior cambiar al azar 457 | drop table if exists nuevos_ids_azar; 458 | 459 | create table nuevos_ids_azar as ( 460 | with etapas_duplicadas as ( 461 | select id_tarjeta, id_etapa 462 | from etapas 463 | where modo in ('SUB', 'COL') 464 | group by id_tarjeta, id_etapa 465 | having count(*) >1 466 | ) 467 | select id, e.id_etapa, 468 | e.id_etapa - (row_number () over ( 469 | PARTITION BY e.id_tarjeta,e.id_etapa 470 | ORDER BY id 471 | ) - 1) as nuevo_id_etapa 472 | from etapas_duplicadas ed, etapas e 473 | where ed.id_tarjeta = e.id_tarjeta 474 | and ed.id_etapa = e.id_etapa 475 | ORDER BY ed.id_tarjeta, ed.id_etapa 476 | ); 477 | 478 | delete from nuevos_ids_azar 479 | where id_etapa = nuevo_id_etapa; 480 | 481 | CREATE INDEX idx_nuevos_ids_azar 482 | ON nuevos_ids_azar(id); 483 | 484 | -- Actualizar etapas con los nuevos id anterior 485 | update etapas e 486 | set id_etapa = np.nuevo_id_etapa 487 | from nuevos_ids_azar np 488 | where e.id = np.id; 489 | 490 | drop table if exists nuevos_ids_azar; 491 | 492 | ------------------------------------------------------------------------------------------------------ 493 | -- Agregar atributos geograficos a etapas 494 | ------------------------------------------------------------------------------------------------------ 495 | SELECT AddGeometryColumn ('public','etapas','geom',4326,'POINT',2); 496 | 497 | update etapas e 498 | SET geom = ST_SetSRID(ST_MakePoint(e.lon, e.lat),4326); 499 | 500 | CREATE INDEX etapas_geom_idx 501 | ON etapas 502 | USING GIST (geom); 503 | 504 | CREATE INDEX etapas_modo 505 | ON etapas(modo); 506 | 507 | CREATE INDEX etapas_linea 508 | ON etapas(id_linea); 509 | 510 | CREATE INDEX etapas_ramal 511 | ON etapas(id_ramal); 512 | 513 | vacuum full etapas; --------------------------------------------------------------------------------