Análisis de senderos escolares en la Ciudad

En este trabajo nos proponemos analizar la ubicación y distribución de senderos escolares en la Ciudad Autónoma de Buenos Aires en relación a la cantidad de población en edad escolar y cantidad de delitos por Comuna.

Los Senderos Escolares fueron desarrollados por el Ministerio de Justicia y Seguridad del Gobierno de la Ciudad de Buenos Aires. Un Sendero Escolar es un camino protegido por Agentes de Prevención de la Ciudad, el Cuerpo de Agentes de Control de Tránsito y Transporte y efectivos de la Policía de la Ciudad. Su objetivo es brindar seguridad a los estudiantes en los horarios de entrada y salida del colegio.

La Ciudad Autónoma de Buenos Aires tiene 207 Senderos Escolares. Los Agentes de Prevención de la Ciudad tienen dos turnos de 6:30 a 13:30 y de 12 a 19 horas. Los Agentes van a pie, uniformados y con teléfonos reglamentarios con el propósito de preservar la seguridad de los alumnos en los trayectos hacia la escuela dese sus casas y viceversa.

La ubicación y longitud de los senderos escolares actualmente está determinada por la concentración de escuelas por radio. Creemos que sería de utilidad sumar a este análisis las variables de “Población en edad escolar” y “Cantidad de delitos” por Comuna.

A continuación presentamos el análisis que realizamos, junto con el código correspondiente. Antes de empezar importamos las librerías necesarias.

# Librerías
library(tidyverse)
library(sf)
library(wesanderson)
library(RColorBrewer)
library(leaflet)
library(readxl)
library(dplyr)
library(viridis)

1. Barrios, senderos escolares y escuelas

La primera sección consiste en un estudio descriptivo de los senderos escolares de la Ciudad Autónoma de Buenos Aires en relación a las comunas, barrios y escuelas cercanas.

En primer lugar, importamos los archivos .shp de comunas (polígonos), barrios (polígonos), senderos escolares (líneas) y establecimientos educativos (puntos) de CABA.

# Comunas. Fuente: BA Data
shape_comunas <- st_read("http://cdn.buenosaires.gob.ar/datosabiertos/datasets/comunas/CABA_comunas.geojson")
shape_comunas <- shape_comunas %>% 
  select(COMUNAS,
         BARRIOS,
         AREA, 
         geometry)
# Barrios. Fuente: BA Data
shape_barrios <- st_read("barrios/barrios_badata.shp")
shape_barrios <- shape_barrios %>% 
  select(BARRIO, 
         COMUNA, 
         AREA, 
         geometry) %>% 
  arrange(COMUNA)
# Senderos escolares. Fuente: BA Data
shape_senderos <- st_read("shf senderos seguros/senderos-escolares.shp")
shape_senderos <- shape_senderos %>% 
  select(ID, 
         Nombre, 
         Longitud, 
         geometry)
# Establecimientos educativos. Fuente: BA Data 
shape_establecimientos <- st_read("shp establecimientos educativos/establecimientos-educativos.shp")
shape_establecimientos <- shape_establecimientos %>% 
  select(OBJECTID, 
         CUE, 
         CUEANEXO, 
         DOM_ESTABL, 
         NOMBRE_EST, 
         NIVEL, 
         NIVELMODAL, 
         COMUNA, 
         BARRIO, 
         geometry)

# Filtramos solo escuelas con nivel inicial, primario y secundario modalidad común y especial 
# (no adultos, no nocturno, etc)
nivelmodal_senderos <- c("Nivel Secundario Común", "Nivel Inicial Común", "Nivel Primario Común",
                         "Nivel Inicial, Primario y Secundario Común", "Nivel Inicial y Primario Común",
                         "Nivel Superior No Universitario Común", "Nivel Inicial y Primario Especial",
                         "Nivel Inicial, Primario, Secundario y Terciario No Universitario Común",
                         " Nivel Inicial y Secundario Común", "Nivel Inicial, Primario, Secundario 
                         y Superior No Universitario Común", "Nivel Primario Especial", "Nivel Inicial,
                         Primario, Secundario  y Superior No Universitario Común - Nivel Primario y
                         Secundario Especial", "Nivel Secundario Común -Nivel Secundario de Jóvenes y
                         Adultos", "Nivel Inicial Especial", "Nivel Secundario y Superior No
                         Universitario Común - Nivel Secundario de Jóvenes y Adultos", "Nivel Inicial",
                         "Nivel Primario y Secundario Común", "Nivel Inicial, Primario y Secundario
                         Común - Nivel Primario de Jóvenes y Adultos", "Nivel Inicial y Primario
                         Especial - Nivel Secundario Común", "Nivel Inicial y Superior No Universitario
                         Común", "Nivel Secundario y Superior No Universitario Común", "Nivel Inicial,
                         Primario, Secundario y Superior No Universitario Común - Nivel Secundario de
                         Jóvenes y Adultos", "Nivel Inicial, Primario y Secundario Común - Nivel
                         Primario y Secundario de Jóvenes y Adultos", "Nivel Primario y Secundario
                         Especial")
shape_establecimientos <- shape_establecimientos %>% 
  filter(NIVELMODAL %in% nivelmodal_senderos) %>% 
  arrange(COMUNA)

A continuación, graficamos todos los elementos por separado.

1.1 Comunas

# Descriptivo
cant_comunas <- nrow(shape_comunas)
# Corregimos el sistema de coordenadas del shape de comunas
shape_comunas <- st_transform(shape_comunas, crs=st_crs(shape_senderos))

# Pre-pro
colourCount_comunas <- length(unique(shape_comunas$COMUNAS))
shape_comunas$COMUNAS <- as.factor(shape_comunas$COMUNAS) 

# Figura/mapa
grafico_comunas <- 
ggplot() +
  geom_sf(data = shape_comunas, aes(fill = COMUNAS), colour = 'beige') +
  theme_minimal() +
  theme(legend.position = "none") +
  scale_fill_manual(values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_comunas)) +
  labs(title = "Comunas",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2019") +
  geom_sf_label(data = shape_comunas, aes(label = COMUNAS), size = 2, alpha = 0.5)

grafico_comunas

# Cantidad de comunas en la ciudad:
cant_comunas
## [1] 15

Con el código anterior podemos ver que hay 48 barrios en la ciudad. La figura representa su localización geográfica en el sistema de coordenadas universal transversal de Mercator.

1.2 Barrios

# Descriptivo
cant_barrios <- nrow(shape_barrios)

# Pre-pro
colourCount <- length(unique(shape_barrios$BARRIO))
shape_barrios$COMUNA <- as.factor(shape_barrios$COMUNA)

# Figura/mapa
grafico_barrios <- 
ggplot() +
  geom_sf(data = shape_barrios, aes(fill = shape_barrios$COMUNA), colour = 'beige') +
  theme_minimal() +
  theme(legend.position = "none") +
  scale_fill_manual(values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_comunas)) +
  labs(title = "Barrios",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2019")
  #geom_sf_label(data = shape_barrios, aes(label = BARRIO), size = 1, alpha = 0.5)

grafico_barrios

# Cantidad de barrios en la ciudad:
cant_barrios
## [1] 48

Con el código anterior podemos ver que hay 48 barrios en la ciudad. La figura representa su localización geográfica en el sistema de coordenadas universal transversal de Mercator.

1.3 Senderos escolares

# Descriptivo
cant_senderos <- nrow(shape_senderos)
long_senderos <- sum(shape_senderos$Longitud)
long_prom_senderos <- mean(shape_senderos$Longitud)

# Pre-pro
colourCount_senderos <- length(unique(shape_senderos$ID))

# Figura/mapa
grafico_senderos <- 
ggplot() +
  geom_sf(data = shape_barrios, fill = 'beige', colour = 'cornsilk3') +
  geom_sf(data = shape_senderos, aes(color = ID)) + #'brown3'
  theme_minimal() +
  theme(legend.position = "none") +
  scale_colour_manual(values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_senderos)) +
  labs(title = "Senderos escolares",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2019")

grafico_senderos

# Cantidad de senderos en la ciudad:
cant_senderos
## [1] 207
long_senderos
## [1] 415.57
round(long_prom_senderos, 2)
## [1] 2.01

El mapa anterior muestra la localización de todos los senderos escolares de la Ciudad; en total suman 207 senderos con una longitud promedio de 2 km y total de más de 415 km. Cabe destacar que muchos de ellos atraviesan más de un barrio.

1.4 Escuelas

# Descriptivo
cant_establecimientos <- nrow(shape_establecimientos)

# Pre-pro
shape_establecimientos$COMUNA <- as.factor(shape_establecimientos$COMUNA)

grafico_escuelas <- 
ggplot() +
  geom_sf(data = shape_barrios, fill = 'beige', color = 'cornsilk3') +
  geom_sf(data = shape_establecimientos, aes(color = shape_establecimientos$COMUNA) , size = 1) + #color = 'cadetblue4', size = 1) + 
  theme_minimal() +
  theme(legend.position = "none") +
  scale_colour_manual(values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_comunas)) +
  labs(title = "Establecimientos educativos",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2019")

grafico_escuelas

# Cantidad de establecimientos en la ciudad:
cant_establecimientos
## [1] 1717

Por último, la figura representa la ubicación de 1717 establecimientos educativos de la Ciudad, correspondientes al nivel inicial, primario, secundario y/o terciario no universitario de modalidad común o especial.

2. Distribución de establecimientos educativos y senderos escolares por comuna

2.1 Cantidad de establecimientos educativos por comuna

Estudiemos cuántos establecimientos educativos hay en cada comuna de la Ciudad. Recordemos que estamos analizando únicamente escuelas de nivel inicial, primario y secundario de modalidad común y especial. No tomamos en cuenta establecimientos con modalidades para jóvenes y adultos.

# Agrupamos escuelas por comuna
escuelas_por_comuna <- shape_establecimientos %>% 
  select(CUEANEXO, COMUNA) %>% 
  group_by(COMUNA) %>% 
  summarise(n_escuelas = n())

summary(escuelas_por_comuna$n_escuelas)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    75.0   108.5   113.0   114.5   126.0   146.0

Lo anterior muestra que en la ciudad hay un promedio de 114.5 escuelas por comuna, con un máximo de 146 y un mínimo de 82 en las comunas 4 y 6, respectivamente. Analicemos esta información gráficamente mediante un mapa de calor.

# Pre-pro
escuelas_por_comuna <- escuelas_por_comuna %>% 
  rename(COMUNAS = COMUNA)
# Añadimos al shapefile de comunas la columna n_escuelas del dataframe escuelas_por_comuna
escuelas_por_comuna <- data.frame(escuelas_por_comuna)
escuelas_por_comuna$COMUNAS <- as.factor(escuelas_por_comuna$COMUNAS) 

shape_comunas <- shape_comunas %>% 
  left_join(escuelas_por_comuna, by = "COMUNAS")

shape_comunas <- shape_comunas %>% 
  mutate(geometry = geometry.x) %>% 
  select(COMUNAS, BARRIOS, AREA, n_escuelas, geometry)
# Mapa
ggplot() +
  geom_sf(data = shape_comunas, aes(fill = n_escuelas), colour = 'beige') +
  theme_minimal() +
  scale_fill_distiller(palette = "Spectral", name = "Cant. est. esc.") +
  labs(title = "Cantidad de establecimientos educativos por comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2019")

Esta visualización permite concluir que las comunas 1 y 4 son las que mayor cantidad de establecimientos educativos nuclean, con más de 140 cada una. Por su parte, la comunas del Norte de la Ciudad (13 y 12) tienen más de 120 escuelas cada una y las del Sur, poco más de 100. La comunas con menor cantidad de escuelas son la 6 y la 2. En este punto tiene sentido analizar la cantidad de establecimientos en función de la superficie de la comuna, para obtener una medida objetiva al respecto.

# Mapa
ggplot() +
  geom_sf(data = shape_comunas, aes(fill = n_escuelas/AREA*100000/2), colour = 'beige') +
  theme_minimal() +
  theme(axis.title = element_text(size = 9),
        title = element_text(size = 12)) +
  scale_fill_distiller(palette = "Spectral", name = "Cant. est. ed./área") +
  labs(title = "Cantidad de est. educ. por unidad de área por Comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2018",
       Fuente = "Mapa del Delito - CABA")

Al aplicar este ajuste podemos notar que la comuna con mayor densidad de establecimientos educativos es la 3 con una diferencia significativa respecto de las demás; que las comunas 2, 5 y 6 tienen una concentración relativamente alta; que las comunas del Norte y Oeste se encuentran por debajo de la media de la distribución; y que las del Sur (8, 9, 4) están en el primer cuartil y presentan un claro déficit de escuelas por unidad de área respecto del resto de la Ciudad.

2.2 Longitud de senderos escolares por comuna

En este apartado intentamos calcular cuántos kilómetros de sendero escolares hay en cada comuna. Para hacerlo, utilizamos el siguiente código.

# Asignamos cada linea de sendero a todas las comunas que toca
senderos_por_comuna <- st_join(shape_senderos, shape_comunas)

# Contamos cuantos barrios toca cada sendero 
repeticiones <- data.frame(table(senderos_por_comuna$Nombre))
# Cambiamos nombre de las columnas para facilitar el join
colnames(repeticiones) <- c('Nombre', 'f_rep')
# Añadimos cantidad de  repeticiones a la lista de senderos por barrios
shape_senderos <- shape_senderos %>% 
  left_join(repeticiones, by = 'Nombre')

# Aproximamos distribucion de senderos en más de un barrio mediante la división de 
# la longitud del sendero entre la cantidad de barrios que toca
shape_senderos <- shape_senderos %>% 
  mutate(Long_ajustada = Longitud/f_rep)

# Asignamos longitud de senderos por comuna
repeticiones <- repeticiones %>% 
  left_join(shape_senderos, by = "Nombre") %>% 
  select(Nombre, Longitud, Long_ajustada)
senderos_por_comuna <- senderos_por_comuna %>% 
  left_join(repeticiones, by = "Nombre")
senderos_por_comuna <- senderos_por_comuna %>% 
  group_by(COMUNAS) %>% 
  summarise(long_senderos = sum(Long_ajustada))
summary(senderos_por_comuna$long_senderos)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   11.55   19.98   29.86   27.70   35.24   38.20

Entonces tenemos un dataframe con un resumen (una aproximación) de la cantidad de km de sendero escolar por comuna. Veamos en un mapa de calor los resultados.

# Pre-pro
# Añadimos al shapefile de comunas la columna long_senderos del dataframe senderos_por_comuna
senderos_por_comuna <- data.frame(senderos_por_comuna)
shape_comunas <- shape_comunas %>% 
  left_join(senderos_por_comuna, by = "COMUNAS")

shape_comunas <- shape_comunas %>% 
  select(COMUNAS, BARRIOS, AREA, n_escuelas, long_senderos, geometry.x) %>% 
  mutate(geometry = geometry.x) %>% 
  select(COMUNAS, BARRIOS, AREA, n_escuelas, long_senderos, geometry)
# Mapa
ggplot() +
  geom_sf(data = shape_comunas, aes(fill = long_senderos), colour = 'beige') +
  theme_minimal() +
  scale_fill_distiller(palette = "Spectral", name = "Longitud (km)") +
  labs(title = "Longitud de senderos escolares por comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2019")

Podemos ver que la media de la longitud de senderos escolares por comuna es de aproximadamente 30 km. Además, que las comunas del Oeste y Noroeste de la Ciudad (especialmente la 12 y la 15) tienen una longitud de senderos escolares de entre 30 y 40 km, mientras que las del centro y Sur promedian 20 km o menos. La comuna 1 es la que más senderos tiene y representa una excepción a la distribución anterior, porque tiene más de 38 km.

Calculemos ahora la cantidad de senderos escolares en función de la cantidad de establecimientos educativos por comuna.

# Mapa
ggplot() +
  geom_sf(data = shape_comunas, aes(fill = long_senderos/n_escuelas*10/4), colour = 'beige') +
  theme_minimal() +
  theme(axis.title = element_text(size = 9),
        title = element_text(size = 10)) +
  scale_fill_distiller(palette = "Spectral", name = "SE/EE") +
  labs(title = "Longitud de senderos escolares por cantidad de est. educ. por Comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2018",
       Fuente = "Mapa del Delito - CABA")

Este mapa repite las tendencias del anterior, pero las desacentúa para las comunas del Norte y Oeste y las acentúa en el Sur. Así es que las comunas 9, 10, 11 y 12 se localizan más cerca de la media que en el caso anterior (sin normalizar por cantidad de establecimientos). Por el contrario, las comunas 8 y 4 tienen aún menos cantidad de senderos escolares al normalizar por cantidad de establecimientos.

3. Análisis de población en edad escolar

3.1 Población en edad escolar por comuna

A continuación analizamos la población en edad escolar por comuna en la Ciudad.

# Población según comuna y edad
Poblacion_por_comuna_y_edad <- read_excel("Poblacion por comuna y edad.xlsx")

# Columnas del rango de edades en edad escolar
min_edad_escolar <- 3
max_edad_escolar <- 17
Pobl_edad_escolar <- select(Poblacion_por_comuna_y_edad, Comuna, min_edad_escolar:max_edad_escolar)

# Total de la población de 3 a 17
Pobl_edad_escolar$Total_3_a_17 <- 
  (Poblacion_por_comuna_y_edad$'3'
  + Poblacion_por_comuna_y_edad$'4'
  + Poblacion_por_comuna_y_edad$'5'
  + Poblacion_por_comuna_y_edad$'6'
  + Poblacion_por_comuna_y_edad$'7'
  + Poblacion_por_comuna_y_edad$'8'
  + Poblacion_por_comuna_y_edad$'9'
  + Poblacion_por_comuna_y_edad$'10'
  + Poblacion_por_comuna_y_edad$'11'
  + Poblacion_por_comuna_y_edad$'12'
  + Poblacion_por_comuna_y_edad$'13'
  + Poblacion_por_comuna_y_edad$'14'
  + Poblacion_por_comuna_y_edad$'15'
  + Poblacion_por_comuna_y_edad$'16'
  + Poblacion_por_comuna_y_edad$'17')

Pobl_edad_escolar <- Pobl_edad_escolar %>% 
  select(Comuna, Total_3_a_17)  

# Gráfico de barras de población de 3 a 17 años por comuna
# Pre-pro
colourCount_barras_comunas <- length(unique(Pobl_edad_escolar$Comuna)) 
Pobl_edad_escolar$Comuna <- factor(Pobl_edad_escolar$Comuna, levels = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
                                                                        11, 12, 13, 14, 15))

ggplot(Pobl_edad_escolar) +
  geom_bar(aes(x = reorder(Comuna, -Total_3_a_17), weight = Total_3_a_17, fill = Comuna))+
  labs(title = "Población en edad escolar por Comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires, 2018",
       caption = "Fuente: EAH 2018",
       x = "Comuna",
       y = "Población en edad escolar") +
  #geom_text(aes(x = "", y = "", label = Pobl_edad_escolar$Total_3_a_17)) +
  theme_minimal() +
  scale_fill_manual(values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_barras_comunas),
                    guide = FALSE)

El gráfico de barras deja en evidencia que las comunas 1, 4 y 8 presentan la mayor cantidad de niños/as y adolesentes en edad escolar; por el contrario, las comunas 2 y 3 son las que registran la menor poblacion en edad escolar en CABA.

3.2 Población en edad escolar según población total por comuna

Ahora analizamos la relación entre la población de 3 a 17 y la población total por comuna:

# Añadimos una columna con el total de la población (todas las edades) al dataframe de edad escolar
Pobl_edad_escolar$Total_Poblacion <- Poblacion_por_comuna_y_edad$Total


# Representamos lo anterior en un gráfico de dispersión
ggplot(Pobl_edad_escolar) +
  geom_point(aes(x = Total_Poblacion, 
                 y = Total_3_a_17, 
                 color = Comuna), 
                 size = 2.5) +
  labs(title = "Población en edad escolar según Población Total, por Comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires, 2018",
       caption = "Fuente: EAH 2018",
       x = "Población Total",
       y = "Población de 3 a 17 años") + #,
       #label = Pobl_edad_escolar$Total_3_a_17) +
  theme_minimal() +
  scale_color_manual(values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_barras_comunas))

3.3 Incidencia de población en edad escolar por comuna

A continuación calculamos la incidencia por comuna y la graficamos:

Pobl_edad_escolar <- Pobl_edad_escolar %>% 
  mutate(incidencia = Total_3_a_17/Total_Poblacion*100)

#Graficamos la incidencia
ggplot(Pobl_edad_escolar) +
  geom_bar(aes(x = reorder(Comuna, -incidencia), weight = incidencia, fill = Comuna, show.legend = FALSE)) +
  labs(title = "Incidencia de Población en edad escolar por Comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires, 2018",
       caption = "Fuente: EAH 2018",
       x = "Comuna",
       y = "Incidencia de Población en edad escolar") +
  theme_minimal() +
  scale_fill_manual(
    values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_barras_comunas), guide = FALSE)
## Warning: Ignoring unknown aesthetics: show.legend

Observamos que las comunas 4 y 8, que son las que más poblacion en edad escolar tienen, también son las que presentan la mayor incidencia. Las comunas 2 y 3, que son aquellas con menor poblacion en edad escolar, son tambien las que menor incidencia tienen. Sin embargo, el resto de las comunas no mantienen una relación lineal entre cantidad de poblacion en edad escolar y la incidencia de ésta sobre el total de la poblacion.

Representamos la información sobre incidencia por comuna a nivel geográfico en un mapa de calor.

# Pre-pro
# Añadimos al shapefile de comunas las columnas "total población", "Total_3_a_17" e "incidencia" mediante un join
# Adaptamos los nombres de las columnas en común para el join
Pobl_edad_escolar <- Pobl_edad_escolar %>% 
  rename(COMUNAS= Comuna)
# Join
shape_comunas <- left_join(shape_comunas, 
                           Pobl_edad_escolar)
# Mapa
ggplot() +
  geom_sf(data = shape_comunas, aes(fill = incidencia), colour = 'beige') +
  theme_minimal() +
  scale_fill_distiller(palette = "Spectral", name = "Incidencia") +
  labs(title = "Incidencia de población en edad escolar por comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2019") #+

  #geom_sf_label(aes(label = COMUNAS), size = 2, alpha = 0.5)

3.4 Condición de asistencia a un establecimiento educativo de población en edad escolar

En primer lugar importamos el archivo de Condicion de asistencia. Este data frame contiene la condicion de asistencia a un establecimiento educativo por edad y comuna. Como lo que interesa para este trabajo es la población de 3 a 17 años que asiste a un establecimiento educativo, extraemos solamente parte de la información.

Condicion_de_asistencia <- read_excel("Condicion de asistencia.xlsx")
Asiste_pobl_edad_escolar <- Condicion_de_asistencia[,c("Condición_asistencia", "Comuna", "3":"17")]
names(Asiste_pobl_edad_escolar)[1] <- "condicion_asistencia"
Asiste_pobl_edad_escolar <- Asiste_pobl_edad_escolar %>% 
  filter(condicion_asistencia == "Asiste")

Luego calculamos y representamos gráficamente el total de la población de 3 a 17 años que asiste a un establecimiento educativo.

Asiste_pobl_edad_escolar$Total_asiste <- 
  (Asiste_pobl_edad_escolar$"3" +
  Asiste_pobl_edad_escolar$"4" +
  Asiste_pobl_edad_escolar$"5" +
  Asiste_pobl_edad_escolar$"6" +
  Asiste_pobl_edad_escolar$"7" +
  Asiste_pobl_edad_escolar$"8" +
  Asiste_pobl_edad_escolar$"9" +
  Asiste_pobl_edad_escolar$"10" +
  Asiste_pobl_edad_escolar$"11" +
  Asiste_pobl_edad_escolar$"12" +
  Asiste_pobl_edad_escolar$"13" +
  Asiste_pobl_edad_escolar$"14" +
  Asiste_pobl_edad_escolar$"15" +
  Asiste_pobl_edad_escolar$"16" +
  Asiste_pobl_edad_escolar$"17")
# Gráfico de barras de población de 3 a 17 años que asiste a un establecimiento educativo por comuna
# Pre-pro
Asiste_pobl_edad_escolar$Comuna <- factor(Asiste_pobl_edad_escolar$Comuna, 
                                          levels = c(1, 2, 3, 4, 5, 6, 7, 8,
                                                     9, 10, 11, 12, 13, 14, 15))

# Gráfica
ggplot(data = Asiste_pobl_edad_escolar) +
  geom_bar(aes(x = reorder(Comuna, -Total_asiste), weight = Total_asiste, fill = Comuna))+
  labs(title = "Población en edad escolar que asiste a un establecimiento educativo por Comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires, 2018",
       caption = "Fuente: EAH 2018",
       x = "Comuna",
       y = "Población en edad escolar que asiste a un establecimiento educativo") +
  theme_minimal() +
  theme(axis.title = element_text(size = 9),
        title = element_text(size = 10)) +
  scale_fill_manual(
    values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_barras_comunas), 
    guide = FALSE)

3.5 Incidencia de población en edad escolar que asiste a un establecimiento educativo por comuna

Para calcular la incidencia de la población en edad escolar que asiste a un establecimiento educativo sobre la población en edad escolar, traemos los datos del total de poblacion de 3 a 17 años de la tabla Pobl_edad_escolar.

# Left join entre los datos de asistencia y el total de poblacion en edad escolar
Pobl_edad_escolar <- Pobl_edad_escolar %>% 
  rename(Comuna = COMUNAS)

Asiste_pobl_edad_escolar <- Asiste_pobl_edad_escolar %>% 
  left_join(select(Pobl_edad_escolar, -incidencia), by = "Comuna")

# Calculamos incidencia
Asiste_pobl_edad_escolar <- mutate(Asiste_pobl_edad_escolar, 
                                   incidencia_asiste = Total_asiste/Pobl_edad_escolar$Total_3_a_17*100)

Ahora graficamos estos datos, pero en lugar de graficar la incidencia de asistencia, elegimos la de no asistencia, que son complementarias, porque consideramos que la visualización aportará más información de este modo.

#Graficamos la incidencia
ggplot(Asiste_pobl_edad_escolar) +
  geom_bar(aes(x = reorder(Comuna, -incidencia_asiste), weight = 100-incidencia_asiste, fill = Comuna, show.legend = FALSE)) +
  labs(title = "Incidencia de Población en edad escolar que no asiste a establecimientos educativos por Comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires, 2018",
       caption = "Fuente: EAH 2018",
       x = "Comuna",
       y = "Incidencia de Población en edad escolar que no asiste a un Est. Ed.") +
  theme_minimal() +
  theme(axis.title = element_text(size = 9),
        title = element_text(size = 9)) +
  scale_fill_manual(
    values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_barras_comunas), guide = FALSE)
## Warning: Ignoring unknown aesthetics: show.legend

Como era de esperar dada la alta tasa de escolarización en la Ciudad, la incidencia de no asistencia es baja en todas las comunas. Sin embargo, existen diferencias relativamente importantes entre la comuna 2, que presenta la menor incidencia (de hecho, es 0 porque el 100% de las personas en edad escolar asiste a algún establecimiento), y la 9, que presenta la más alta (casi 5% de no asistencia). Para profundizar en estas diferencias recurrimos a los valores numéricos de asistencia.

summary(Asiste_pobl_edad_escolar$incidencia_asiste)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   95.20   96.75   97.60   97.61   98.52  100.00
cols_of_interest <- c("Comuna", "incidencia_asiste")
resumen_asistencia <- Asiste_pobl_edad_escolar %>% 
  select(cols_of_interest, Total_3_a_17) %>%
  mutate(total_no_asiste = (100-incidencia_asiste) * Total_3_a_17 / 100) %>% 
  arrange(desc(incidencia_asiste))
resumen_asistencia
## # A tibble: 15 x 4
##    Comuna incidencia_asiste Total_3_a_17 total_no_asiste
##    <fct>              <dbl>        <dbl>           <dbl>
##  1 2                  100          12891              0 
##  2 6                  100          30192              0 
##  3 12                 100          44267              0 
##  4 10                  99.0        34470            339.
##  5 15                  98.0        35187            692 
##  6 13                  98.0        37005            748.
##  7 4                   97.6        57333           1349.
##  8 7                   97.6        51290           1231.
##  9 14                  97.5        30985            769.
## 10 11                  96.9        36493           1116.
## 11 5                   96.9        31447            977.
## 12 1                   96.6        45667           1552.
## 13 3                   95.4        32271           1472.
## 14 8                   95.3        67650           3176.
## 15 9                   95.2        38945           1870.
sum(resumen_asistencia$total_no_asiste)
## [1] 15291

De este modo podemos concluir que:

  • la comuna 2 tiene asistencia del 100% de la población en edad escolar
  • la media de la incidencia de población en edad escolar que efectivamente asiste a la escuela es de 97,6%
  • la distribución es simétrica ya que la media y la mediana son similares
  • la diferencia entre el máximo y el mínimo de incidencia es de aproximente 5 puntos
  • la comuna 9 tiene la menor incidencia de población en edad escolar escolarizada, con un 95,2%. Esto es, 1870 personas en la comuna 9 no asisten a la escuela aunque estén en edad de hacerlo.
  • la comuna 8 presenta la mayor cantidad de personas en edad escolar que no asiste a un establecimiento educativo: 3176
  • El total de la población de la Ciudad en edad escolar que no asiste a ningún establecimiento educativo es de 15291 personas

Por último, graficamos lo anterior en un mapa para complementar el análisis.

# Pre-pro
# Añadimos al shapefile de comunas la columna "incidencia_asiste" mediante un join
# Adaptamos los nombres de las columnas en común para el join
Asiste_pobl_edad_escolar <- Asiste_pobl_edad_escolar %>% 
  rename(COMUNAS= Comuna)
# Join
shape_comunas <- left_join(shape_comunas, 
                           Asiste_pobl_edad_escolar[,c("COMUNAS","Total_asiste","incidencia_asiste")],
                           by = "COMUNAS")
# Mapa
ggplot() +
  geom_sf(data = shape_comunas, aes(fill = incidencia_asiste), colour = 'beige') +
  theme_minimal() +
  theme(axis.title = element_text(size = 9),
        title = element_text(size = 8)) +
  scale_fill_distiller(palette = "Spectral", name = "Incidencia Asistencia") +
  labs(title = "Incidencia de población en edad escolar que asiste a establecimientos educativos por comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2019")

4. Análisis de delitos por comuna

La tercera parte del trabajo consiste en estudiar los delitos registrados en las comunas, particularmente en los horarios en que los Agentes de Prevención recorren los senderos (6:30-19 horas). El objetivo es cuantificar los delitos y asignar a cada comuna una incidencia.

Para ello importamos un conjunto de datos de delitos violentos obtenido a partir de una API del Mapa del Delito del Ministerio de Justicia y Seguridad de la Ciudad (https://mapa.seguridadciudad.gob.ar/). Utilizamos los datos del año 2018 por ser los más actualizados disponibles.

delitos_2018 <- read_csv("delitos-RV-2018-CABA.csv")

# Corroboramos que son todos delitos violentos
unique(delitos_2018$tipo_delito)
## [1] "Robo (Con violencia)"
# Contamos cantidad de delitos
nrow(delitos_2018)
## [1] 67867

Este conjunto de datos contiene 67867 delitos violentos ocurridos en 2018. Además, para cada uno informa la fecha, hora y comuna donde ocurrió. Seleccionamos estos campos para los próximos pasos. A continuación descartamos los delitos que ocurren fuera de las franjas horarias de los senderos escolares, que asumimos son los horarios en que los estudiantes realizan el trayecto desde o hacia la escuela. Por último, agrupamos por día y por comuna para contabilizar el total.

sum_delitos_2018 <- delitos_2018 %>% 
  select(comunaId, fecha, hora) %>% 
  filter(hora < 68400 & hora > 23400) %>% 
  group_by(comunaId, fecha) %>% 
  summarise(n_delitos = n())

nrow(sum_delitos_2018)
## [1] 5588

Observamos que hay 5588 registros en el agrupado de delitos cuando debería haber como máximo 365 días * 15 comunas = 5475 entradas, cada una correspondiente a un día en una comuna. Adjudicamos la diferencia a delitos sin comuna definida y descartamos estos registros.

sum_delitos_2018 <- sum_delitos_2018 %>% 
  filter(!is.na(comunaId))

nrow(sum_delitos_2018)
## [1] 5324

Finalmente pasamos la columna n_delitos al shapefile de comunas

# agrupamos solo por comuna
delitos_por_comuna <- delitos_2018 %>%
  select(comunaId, fecha, hora) %>% 
  filter(hora < 68400 & hora > 23400) %>%
  group_by(comunaId) %>% 
  summarise(n_delitos = n()) %>% 
  filter(!is.na(comunaId))

# cambiamos nombre para join
delitos_por_comuna <- delitos_por_comuna %>% 
  rename(COMUNAS= comunaId)
# factorizo comunas en delitos por comuna
delitos_por_comuna$COMUNAS <- as.factor(delitos_por_comuna$COMUNAS)
# Join
shape_comunas <- left_join(shape_comunas, 
                           delitos_por_comuna,
                           by = "COMUNAS")

Ahora sí, podemos representar esta información por comuna de tres modos distintos.

Gráfico de barras

#Graficamos los delitos por comuna
ggplot(shape_comunas) +
  geom_bar(aes(x = reorder(COMUNAS, -n_delitos), weight = n_delitos, fill = COMUNAS, show.legend = FALSE)) +
  labs(title = "Delitos violentos por Comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2018",
       caption = "Fuente: Mapa del Delito - CABA",
       x = "Comuna",
       y = "Delitos violentos") +
  theme_minimal() +
  scale_fill_manual(
    values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_barras_comunas), guide = FALSE)
## Warning: Ignoring unknown aesthetics: show.legend

A simple vista podemos ver que la comuna 1 presenta una diferencia muy importante en la cantidad de delitos violentos ocurridos durante el año 2018. Veamos estos resultados en un mapa.

Mapas de calor

# Mapa
ggplot() +
  geom_sf(data = shape_comunas, aes(fill = n_delitos), colour = 'beige') +
  theme_minimal() +
  theme(axis.title = element_text(size = 9),
        title = element_text(size = 12)) +
  scale_fill_distiller(palette = "Spectral", name = "Delitos violentos") +
  labs(title = "Delitos violentos por Comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2018",
       Fuente = "Mapa del Delito - CABA")

Nuevamente observamos que la comuna 1 tiene mayor cantidad de delitos violentos registrados. Del mimso modo que en la sección 2 (donde calculamos la cantidad de alumnos que asisten a establecimientos educativos sobre el total de la población en edad escolar) podemos preguntarnos cuál es el efecto del área de cada comuna sobre la cantidad de delitos cometidos. Por eso normalizamos la cantidad de delitos por el área de la comuna y reptimos la visualización.

# Mapa
ggplot() +
  geom_sf(data = shape_comunas, aes(fill = n_delitos/AREA*1000/0.6), colour = 'beige') +
  theme_minimal() +
  theme(axis.title = element_text(size = 9),
        title = element_text(size = 12)) +
  scale_fill_distiller(palette = "Spectral", name = "Delitos violentos/área") +
  labs(title = "Densidad de delitos violentos por unidad de área por Comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2018",
       Fuente = "Mapa del Delito - CABA")

Así, hemos creado un índice de cantidad de delitos violentos por unidad de área para cada comuna (escaldo por un factor de 1000 para facilitar su interpretación). Esto nos permite prestar atención a hechos que antes pasaban desapercibidos. Podemos ver que las comunas del Suroeste, Oeste y Norte mantienen un comportamiento similar al del mapa anterior. Sin embargo, las comunas del centro y Sur presentan diferencias:

  • La comuna 3 tiene la tasa de delitos por área más alta de la Ciudad, con una gran diferencia respecto de las demás.
  • La comuna 5, que tenía una cantidad de delitos moderada en el primer mapa, ahora presenta una tasa relativamente alta, debido a su pequeña superficie.
  • A diferencia del mapa anterior, ahora la comuna 1 tiene un índice moderado porque, si bien presenta más delitos que la comuna 3 y 5, su superficie es significativamente mayor. Sucede algo similar con la comuna 4.

Como conclusión, las comunas que requieren mayor análisis con respecto a senderos escolares son las comunas 1, 4 (por cantidad de delitos), 3 y 5 (por densidad de delitos por unidad de área).

Gráfico de dispersión

# Representamos lo anterior en un gráfico de dispersión
ggplot(shape_comunas) +
  geom_point(aes(x = AREA, 
                 y = n_delitos, 
                 color = COMUNAS), 
                 size = 2.5) +
  labs(title = "Delitos violentos según área, por Comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2018",
       caption = "Fuente: Mapa del Delito - CABA",
       x = "Área",
       y = "Delitos violentos 2018") + #,
       #label = Pobl_edad_escolar$Total_3_a_17) +
  theme_minimal() +
  scale_color_manual(values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_barras_comunas))

Aquí confirmamos las conclusiones anteriores, y vemos que la comuna 8 tiene la menor proporción de delitos por área.

5. Regresión lineal

A continuación llevamos a cabo un análisis de regresión lineal con las siguientes variables:

  • Factores predictores: ⋅⋅⋅1. Densidad de senderos escolares por comuna ⋅⋅⋅2. Cantidad de establecimientos educativos por comuna ⋅⋅⋅3. Incidencia de población en edad escolar que asiste a establecimientos educativos por comuna

  • Factores de respuesta: ⋅⋅⋅1. Densidad de delitos violentos en horarios escolares por comuna

Buscamos entender si existe una asociación entre los delitos violentos que ocurren en las comunas y la cantidad de escuelas, senderos escolares, y habitantes que asisten a la escuela. Construimos todos los modelos usando el conjunto de datos ‘shape_columnas’ que recopilamos y procesamos a lo largo del trabajo. En todos los casos primero graficamos las dos variables (de respuesta vs. predictora) y luego evaluamos el modelo lineal.

# Calculamos los índices normalizando los campos correspondientes (que llamamos "densidades") y los escalamos entre 1 y 0. 
# senderos
shape_comunas$densidad_senderos <- (shape_comunas$long_senderos/shape_comunas$n_escuelas)*10/4
# delitos
shape_comunas$densidad_delitos <- (shape_comunas$n_delitos/shape_comunas$AREA)*1000/0.6
# escuelas
shape_comunas$densidad_escuelas <- (shape_comunas$n_escuelas/shape_comunas$AREA)*100000/2

5.1 Delitos vs. Senderos escolares

ggplot() +
  geom_point(data = shape_comunas,
               aes(x = densidad_senderos, y = densidad_delitos, color = COMUNAS)) +
  theme_minimal() +
  scale_color_manual(values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_barras_comunas)) +
  labs(title = "Densidad de delitos vs. densidad de senderos escolares por comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2018",
       x = "Senderos escolares por escuela",
       y = "Delitos violentos por unidad de área - 2018") 

A simple vista, deducimos del gráfico de dispersión que no existe una asociación fuerte entre los dos factores. Construimos el modelo para corroborarlo.

# Regresión lineal
modelo_senderos <- lm(data = shape_comunas, densidad_delitos ~ densidad_senderos)
summary(modelo_senderos)
## 
## Call:
## lm(formula = densidad_delitos ~ densidad_senderos, data = shape_comunas)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.31544 -0.09644 -0.06135  0.08446  0.48989 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)  
## (Intercept)         0.5836     0.2001   2.917    0.012 *
## densidad_senderos  -0.3816     0.3207  -1.190    0.255  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.1952 on 13 degrees of freedom
## Multiple R-squared:  0.09822,    Adjusted R-squared:  0.02885 
## F-statistic: 1.416 on 1 and 13 DF,  p-value: 0.2554

Efectivamente vemos que el valor p de la curva de ajuste lineal propuesta por el modelo es de 0.255, por lo que no es un resultado estadísticamente significativo.

5.2 Delitos vs. cantidad de establecimientos educativos

ggplot() +
  geom_point(data = shape_comunas,
               aes(x = densidad_escuelas, y = densidad_delitos, color = COMUNAS)) +
  theme_minimal() +
  scale_color_manual(values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_barras_comunas)) +
  labs(title = "Densidad de delitos vs. densidad de est. ed. por comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2018",
       x = "Establecimientos educativos por unidad de área",
       y = "Delitos violentos por unidad de área - 2018") 

Este gráfico es más alentador que el anterior, ya que podría admitir una recta para ajustar los puntos. Nuevamente, corroboremos esta hipótesis con el modelo lineal.

# Regresión lineal
modelo_escuelas <- lm(data = shape_comunas, densidad_delitos ~ densidad_escuelas)
summary(modelo_escuelas)
## 
## Call:
## lm(formula = densidad_delitos ~ densidad_escuelas, data = shape_comunas)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.118481 -0.061982 -0.001016  0.040521  0.226332 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)        -0.1319     0.0683  -1.931   0.0756 .  
## densidad_escuelas   1.0222     0.1356   7.539 4.26e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.08869 on 13 degrees of freedom
## Multiple R-squared:  0.8139, Adjusted R-squared:  0.7995 
## F-statistic: 56.84 on 1 and 13 DF,  p-value: 4.256e-06

Como predijimos, el modelo propone una recta que ajusta los puntos y ésta tiene un valor p asociado de 4.26 e-06 (menor a 0.05), ¡el modelo es estadísticamente significativo! Es decir que existe una relación lineal entre la cantidad de establecimientos educativos y delitos ocurridos en 2018 por unidad de área por comuna. En otras palabras, la cantidad de establecimientos educativos podría predecir la cantidad de delitos en horario escolar.

5.3 Delitos vs. incidencia de población que asiste a un establecimiento educativo

ggplot() +
  geom_point(data = shape_comunas,
               aes(x = incidencia_asiste, y = densidad_delitos, color = COMUNAS)) +
  theme_minimal() +
  scale_color_manual(values = colorRampPalette(wes_palette("Darjeeling1"))(colourCount_barras_comunas)) +
  labs(title = "Densidad de delitos vs. incidencia de asistencia por comuna",
       subtitle = "Ciudad Autónoma de Buenos Aires - 2018",
       x = "Incidencia de población en edad escolar que asiste a est. ed.",
       y = "Delitos violentos por unidad de área - 2018") 

Por último, aquí vemos mucha aleatoreidad en los puntos. No esperamos una relación lineal significativa entre las variables.

# Regresión lineal
modelo_escuelas <- lm(data = shape_comunas, densidad_delitos ~ incidencia_asiste)
summary(modelo_escuelas)
## 
## Call:
## lm(formula = densidad_delitos ~ incidencia_asiste, data = shape_comunas)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.2466 -0.1168 -0.0780  0.1256  0.5044 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)
## (Intercept)        1.79528    3.26331   0.550    0.592
## incidencia_asiste -0.01477    0.03343  -0.442    0.666
## 
## Residual standard error: 0.204 on 13 degrees of freedom
## Multiple R-squared:  0.0148, Adjusted R-squared:  -0.06098 
## F-statistic: 0.1953 on 1 and 13 DF,  p-value: 0.6658

El valor p del modelo (0.666) es demasiado alto para asumir la asociación entre variables con los datos disponibles.

5.4 Modelo multivariado

Finalmente probamos todos los factores predictores juntos.

Modelo multivariado

modelo_multivariado <- lm(data = shape_comunas,
                         densidad_delitos ~ densidad_senderos + densidad_escuelas + incidencia_asiste)

summary(modelo_multivariado)
## 
## Call:
## lm(formula = densidad_delitos ~ densidad_senderos + densidad_escuelas + 
##     incidencia_asiste, data = shape_comunas)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.106011 -0.049231 -0.003475  0.037081  0.216265 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)        1.57355    1.38967   1.132    0.282    
## densidad_senderos -0.14100    0.14698  -0.959    0.358    
## densidad_escuelas  1.00094    0.13550   7.387 1.38e-05 ***
## incidencia_asiste -0.01650    0.01436  -1.149    0.275    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.08663 on 11 degrees of freedom
## Multiple R-squared:  0.8497, Adjusted R-squared:  0.8088 
## F-statistic: 20.74 on 3 and 11 DF,  p-value: 7.826e-05

El modelo multivariado llega a las mismas conclusiones que los modelos univariados de las secciones anteriores.

6. Mejoras al trabajo

Proponemos a continuación puntos débiles del trabajo que podríamos mejorar en futuras iteraciones:

  • Considerar migraciones entre comunas de la población en edad escolar que asiste a establecimientos educativos. En este trabajo asumimos que la incidencia de asistencia de una comuna se compone exclusiva y totalmente por la población en edad escolar de la comuna. Esto en muchas oportunidades no ocurre porque la población viaja para ir a la escuela.

  • Utilizar buffers para hacer más específica la comparación entre senderos escolares y escuelas. Es decir, desagregar más la información geográfica para obtener datos más fidedignos.

  • Mejorar la asignación de longitudes de senderos escolares a las comunas. En este trabajo lo aporximamos dividiendo la longitud total del sendero entre la cantidad de comunas que atraviesa, pero esto podría mejorarse.

  • Añadir un mapa interactivo con Leaflet para la primera sección del trabajo