Análisis geográfico de líneas de autobús en Barcelona (1/2)

Objetivo: Determinar solapamientos de líneas de autobús con códigos postales en la ciudad de Barcelona (España)

Desde hace tiempo tengo la curiosidad sobre cómo se distribuyen las líneas de transporte público (autobús, tranvía y metro) en la ciudad de Barcelona. Al mismo tiempo que empiezo a practicar con objectos espaciales (Spatial Polygons y Lines principalmente), he decidio hacerlo con alguna línea de autobús y los códigos postales de la ciudad de Barcelona. Los códigos postales son de gran relevancia para el análisis de mercado al ser un estándar de agrupación de datos sociales, administrativos, poblacionales, etc. tanto a nivel de las administraciones públicas como de empresas que venden dicha información. En un futuro se puede trabajar en la casuística en la que los barrios y los códigos postales no concuerdan geométricamente.

Este ejercicio puede ser la parte inicial de adecuación de datos para la conformación de un modelo de predicción que tenga gran correlación con la información de líneas de autobús y la tipología de las zonas por las que transita tales como ocupación de autobuses, impacto del turismo, idoneïdad de nuevas rutas o cambios en las actuales, impacto laboral y económico de dichas ruta, etc.

Dos son los tipos de datos que se deben conseguir: líneas de autobús y códigos postales.

Los códigos postales en España constan de cinco dígitos habiendo casos en que los dos primeros, que definen la provincia, puedan contener un cero como dígito inicial (Barcelona con el 08).

Códigos postales en España (Fuente Wikipedia)

Códigos Postales

Los códigos postales pueden bajarse en formato KML de la web codigospostales.com. La URL es del estilo http://www.codigospostales.com/kml/08/08033.kml por lo que debemos componerla de forma dinámica.

Para reducir el ámbito de los códigos postales con los que se trabajará, se define un valor mínimo y máximo de códigos postales a bajar y cargar que en este caso se centrará en el rango 080 (ciudad de Barcelona).

Con un bucle for se descargan los archivos KML, se almacenan y cargan. La razón por la cual se almacenan los archivos es para disponer de los mismos en el futuro sin tener que bajarlos de nuevo.

Los archivos KML de los códigos postales sólo contienen geometrías y no disponen de metadatos de interés. Están basados en el estándar Open GIS.

La presentación de Francisco Barreras da una buena base sobre los Spatial Polygons así como de proyecciones UTM.

Un resúmen de algunas de las funciones básicas están compartidas por Barry Rowlingson. Igualmente, los cursos de Claudia Engel cuentan con ejercicios prácticos para desarrollar los conocimientos.

En este caso utilizaremos los polígonos y líneas. Dichos objetos contienen información sobre las coordenadas de los objetos y su proyección (que se comenta más adelante). Se pueden asignar valores a los objetos poligonales para dotarlos de contexto tales como identificativos de nombre o variables. En este caso, se pueden asignar nombres a los cógidos postales y las líneas de autobús para su correcta y fácil identificación. Igualmente se pueden asignar valores de número de habitantes por cada código postal o el número de paradas de autobús en cada código postal. Esos datos se almacenan en @data en formato data.frame y permiten complementar la información meramente geográfica. La única restricción en @data es que debe haber el mismo número de filas que elementos poligonales contenidos (tantos valores de cada metadato como códigos postales o líneas de autobús en este caso). Aquellos objetos poligonales usados en este ejemplo que únicamente contienen datos de coordenadas y proyecciones se llaman Spatial Polygons (SP, polígonos) y Spatial Lines (SL, líneas). En el caso de contener metadatos de dichos objetos se convierten en Spatial Polygons Data Frame (SPDF) y Spatial Lines Data Frame (SLDF). La terminología de las variables en este ejercicio contienen una coda con el identificativo del tipo de objeto que se trata para ayudar en su compresnsión.

Los objetos poligonales que hacen referencia a cartografía conllevan una proyección además del conjunto de objetos que se definen. Como describe Francisco Barreras, las proyecciones “permiten transformar las coordenadas sobre la superficie curva de la Tierra en coordenadas sobre una superficie plana. Esto es necesario para poder representarlas en un soporte plano tal como puede ser un mapa o la pantalla del ordenador, así como para poder analizarlas de forma más simple”. Como somera referencia, los análisis cartográficos en este ejemplo se basan en proyecciones sobre un plano de un objeto esférico o elipsoidal (elipsoide).

Para poder realizar análisis de solapamiento, los objetos espaciales deben tener la misma proyección. Una buena introducción al tema se puede encontrar en el capítulo tercero de Sistemas de Información Geográfica de Victor Olaya.

En vez de crear un objeto por cada código postal, usamos las características del Spatial Polygon para definir diferentes capas. Cada capa se corresponde un código postal.

library(sp)
library(rgdal)
library(RCurl)
library(ggplot2)
library(rgeos)
library(ggmap)
library(jpeg)
library(plyr)
library(htmlwidgets)
library(highcharter)
library(httr)
library(rjson)
library(xtable)
library(stringr)

La librería sp es la encargada de la gestión de los objetos poligonales (Spatial Polygons). La libreria rgdal nos permite hacer la carga de datos y transformaciones de proyecciones de objetos geográficos. Con rgeos se realizan las transformaciones de los objetos y cálculos de características de los mismos así como relaciones entre ellos. rjson permite la lectura y conversión de ficheros JSON a objetos R.

#Cambio del directorio de trabajo
#setwd("~/Desktop/TMB/data")

#Definiendo el rango de códigos postales
postal_code_min="08000"
postal_code_max="08099"
#Añadimos el cero precedente que desaparece al generar el vector
postal_codes_range<-str_trunc(paste0("0",as.character(c(postal_code_min:postal_code_max))), width=5, side="left", ellipsis='') #Añadimos un cero y recortamos el valor a cinco dígitos

#Definimos la proyección
projection_value<-CRS("+init=epsg:2062")

#Iniciando variables para el bucle
loaded_postal_codes<-c()
list_polygons<-list() #Inicializamos para asegurarnos de que está vacío
par(mfrow=c(2,3)) #Disposición de gráficos en tres columnas y dos filas
for(i in postal_codes_range){ 
  url=paste("http://www.codigospostales.com/kml/",substring(i,1,2),'/',i,'.kml',sep='')
  destfile=paste('data/',i,'.kml',sep='')
  if(url.exists(url)){
    #En caso de que existe el código postal en KML, se descarga, guarda y procesa
    #download.file(url, destfile, mode="wb") #Guardando los archivos para futuros análisis. Se puede añadir una comprobación de existencia de fichero
    the_polygon<-readOGR(destfile, "Area Features")
    print(proj4string(the_polygon))
    if(length(the_polygon)>1){ row.names(the_polygon)<-paste(sprintf("%s-",i),row.names(the_polygon),sep='')} #En caso de que haya más de un polígono
    else row.names(the_polygon)<-sprintf("%s",i) #Creando un identificador único al no provenir de los metadatos
    the_polygon <- spTransform(the_polygon,projection_value) #Asignando la proyección mediante transformación
    if(length(list_polygons)<5) plot(main=paste('Código postal',i),the_polygon) #Mostrando los cinco primeros
    if(i=='08017') plot(main=paste('Código postal',i),the_polygon) #Mostrando 08017 con dos polígonos
      list_polygons<-c(list_polygons,slot(the_polygon,"polygons"))
  }
}

Algunos códigos postales de Barcelona

par(mfrow=c(1,1)) 

    grouped_pc_polygons.sp<-SpatialPolygons(lapply(list_polygons,function(x){x})) #Recogemos todos los polígonos
    plot(grouped_pc_polygons.sp)

Ciudad de Barcelona con sus códigos postales

Los códigos postales exitentes en España tienen un rango que va del 01000 al 52080. Algunos de los códigos postales no existen y otros no tienen traslación geográfica al ser Apartados de correos. Es neceario gestionar los ceros iniciales de dichos códigos postales para mantener siempre un valor de cinco dígitos. Para comprobar que funciona la gestión de códigos postales, el rango se establece desde 08000 (inexistente) y 08099 (inexistente). Una vez descargados inicialmente puede desctivarse el código de descarga de ficheros. Con este método, fácilmente se puede adecuar la descarga y carga de otras regiones españolas.

Al cargar los datos de los KML, se define como proyección LAT-LON (“+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs”). Así pues, en vez de utilizar la proyección estándar en el Ecuador (WGS84), se puede optar por la 2062 al estar más circunscrita a España. Otra alternativa sería la 32631. Se debe tener en cuenta que las distancias resultantes de los cálculos en diferentes referencias son distintas al tener diferentes proyecciones. Tanto la proyección 2062 como la 32631 tienen las unidades de medida en metros.

La proyección asignada resulta “+init=epsg:2062 +proj=lcc +lat_1=40 +lat_0=40 +lon_0=0 +k_0=0.9988085293 +x_0=600000 +y_0=600000 +a=6378298.3 +b=6356657.142669561 +pm=madrid +units=m +no_defs”

Una vez se ha creado un único objecto SP (Spatial Polygon), asignamos la misma proyección que se ha utilizado anteriormente, esta vez sin transformación.

El código 08017 tiene la particularidad de contener una isla. Al utilizar un código que no se centra en captar el primer elemento de polygons, permite recuperar todos los polígonos cada código postal. Dos códigos postales tienen islas: 08017 y 08075.

proj4string(grouped_pc_polygons.sp) <- projection_value #Reasignando la proyección sin necesidad de transformación
head(readLines(file('data/08075.kml',open="r")), n=30) #Mostrando las primeras 30 líneas del 08075
##  [1] "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>"                                              
##  [2] "<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\">"
##  [3] "<Document>"                                                                                   
##  [4] "  <!-- Begin Style Definitions -->"                                                           
##  [5] "  <Style id=\"area1\">"                                                                       
##  [6] "    <LineStyle>"                                                                              
##  [7] "      <color>FFFF0000</color>"                                                                
##  [8] "      <width>1</width>"                                                                       
##  [9] "    </LineStyle>"                                                                             
## [10] "    <PolyStyle>"                                                                              
## [11] "      <color>640080FF</color>"                                                                
## [12] "      <fill>1</fill>"                                                                         
## [13] "      <outline>1</outline>"                                                                   
## [14] "    </PolyStyle>"                                                                             
## [15] "  </Style>"                                                                                   
## [16] "  <Folder>"                                                                                   
## [17] "    <name>Area Features</name>"                                                               
## [18] "    <description>Area Features</description>"                                                 
## [19] "    <Placemark>"                                                                              
## [20] "      <description>Unknown Area Type</description>"                                           
## [21] "      <styleUrl>#area1</styleUrl>"                                                            
## [22] "      <Polygon>"                                                                              
## [23] "        <outerBoundaryIs>"                                                                    
## [24] "          <LinearRing>"                                                                       
## [25] "            <coordinates>"                                                                    
## [26] "              2.1325446450,41.3653568252,0"                                                   
## [27] "              2.1309770341,41.3649458413,0"                                                   
## [28] "              2.1320498830,41.3633610749,0"                                                   
## [29] "              2.1310967239,41.3629201454,0"                                                   
## [30] "              2.1314457661,41.3624416827,0"
#Al añadirlos al SP, se pierden los datos (@data) que igualmente no eran relevantes
head(the_polygon@data)
##         Name       description timestamp begin  end altitudeMode
## 08075-1 <NA> Unknown Area Type      <NA>  <NA> <NA>         <NA>
## 08075-2 <NA> Unknown Area Type      <NA>  <NA> <NA>         <NA>
##         tessellate extrude visibility drawOrder icon
## 08075-1         -1      -1         -1        NA <NA>
## 08075-2         -1      -1         -1        NA <NA>
print(proj4string(the_polygon))
## [1] "+init=epsg:2062 +proj=lcc +lat_1=40 +lat_0=40 +lon_0=0 +k_0=0.9988085293 +x_0=600000 +y_0=600000 +a=6378298.3 +b=6356657.142669561 +pm=madrid +units=m +no_defs"
remove(the_polygon)

plot(grouped_pc_polygons.sp)
plot(grouped_pc_polygons.sp[c("08017-1","08017-2"),], col="green", add=T)
plot(grouped_pc_polygons.sp[c("08075-1","08075-2"),], col="red", add=T)

En verde 08017 y en rojo 08075

length(grouped_pc_polygons.sp) #Cantidad de objetos de códigos postales
## [1] 45
laply(grouped_pc_polygons.sp@polygons, slot, "ID") #Obteniendo los nombres de los códigos postales
##  [1] "08001"   "08002"   "08003"   "08004"   "08005"   "08006"   "08007"  
##  [8] "08008"   "08009"   "08010"   "08011"   "08012"   "08013"   "08014"  
## [15] "08015"   "08016"   "08017-1" "08017-2" "08018"   "08019"   "08020"  
## [22] "08021"   "08022"   "08023"   "08024"   "08025"   "08026"   "08027"  
## [29] "08028"   "08029"   "08030"   "08031"   "08032"   "08033"   "08034"  
## [36] "08035"   "08036"   "08037"   "08038"   "08039"   "08040"   "08041"  
## [43] "08042"   "08075-1" "08075-2"
names(grouped_pc_polygons.sp) #Alternativa para obtener los nombres de los códigos postales
##  [1] "08001"   "08002"   "08003"   "08004"   "08005"   "08006"   "08007"  
##  [8] "08008"   "08009"   "08010"   "08011"   "08012"   "08013"   "08014"  
## [15] "08015"   "08016"   "08017-1" "08017-2" "08018"   "08019"   "08020"  
## [22] "08021"   "08022"   "08023"   "08024"   "08025"   "08026"   "08027"  
## [29] "08028"   "08029"   "08030"   "08031"   "08032"   "08033"   "08034"  
## [36] "08035"   "08036"   "08037"   "08038"   "08039"   "08040"   "08041"  
## [43] "08042"   "08075-1" "08075-2"

La variable grouped_pc_polygons.sp contiene 43 códigos postales (con dos códigos postales desdoblados).

Sorprende ver el código postal 08075, que contiene dos polígonos. Se trata de la Ciutat de la Justícia, que debió dejar de pertencer únicamente a l’Hospitalet de Llobregat para incorporarse a la ciudad de Barcelona.

[Continuación en Análisis geográfico de líneas de autobús en Barcelona (2/2)]

One thought on “Análisis geográfico de líneas de autobús en Barcelona (1/2)

Comentarios Cerrados