eMAPS is an open-source end-to-end tool for microscale assessment of pedestrian environments developed by LlactaLAB Ciudades Sustentables Research Group at University of Cuenca.
This file is a rMarkdown document to process eMAPS survey data and convert it to walkability scores. Scores are computed at three levels: item, subscale and total. The unit of analysis is the street segment, and street segment scores can be further aggregated (e.g. neighbourhoods, buffers or isochrones, around schools, etc.).
This tool is based on the original MAPS protocol (Cain KL, Millstein RA, Geremia CM (2012). Microscale Audit of Pedestrian Streetscapes (MAPS): Data Collection & Scoring Manual. University California San Diego. Available for download at: http://sallis.ucsd.edu/measures/maps)
In this document, we are scoring a pilot evaluation conducted during the REDU-EDPA project. The inputs and outputs are referred to such dataset which include data for Inter-rater reliability for ratters and methods. Results, therefore must be selected to include only real evaluation data.
Author: Daniel Orellana V. LlactaLAB - Universidad de Cuenca
The procedure requires the following files:
segmentos_eval.csv: “segmentos” table downloaded from the KoboToolbox plaform for the corresponding version with the option: “xml values”. This is a .csv file .
lotes_eval.csv: “lotes” table from the KoboToolbox plaform for the corresponding version with the option: “xml values”. This is a .csv file.
diccionario.csv: A data dictionary table which maps the question and answer labels and values. This is a .csv file.
segmentos_geom.df: A geographic dataset with the geometry of the evaluated street segments for extracting some additional data (e.g. lenght, slope, etc) and for mapping. This is a spatial dataset file (e.g. .sqlite).
The procedure produces the following tables:
segmentos_scores.csv: a table with the subscale and total scores for each segments.
zonas_scores.csv: [optional] a table with aggregated scores (mean) for groups specidied in some field on the segmentos_eval.csv table.
The following sections of this document include the required R code for converting answers from the evaluation tool into walkability scores.
First, configure R and load required packages, ipak is a custom code to facilitate loading R packages
# packloader from github
# library(devtools)
# myURL <-"https://raw.githubusercontent.com/temporalista/r-essentials/master/packloader.R"
# source_url(myURL)
#packloader local
source("/Volumes/MacData/odrive/GDrive_UC/Rspace/packloader.R")
ipak(c("car",
"ggplot2",
"dplyr",
"reshape",
"sf",
"psych"))
## car ggplot2 dplyr reshape sf psych
## TRUE TRUE TRUE TRUE TRUE TRUE
These are just convenient functions for later
myhist.f <- function(x){
ggplot2::ggplot(segsc.df, aes(x)) +
geom_histogram(aes(y=..ncount..), colour="black", fill="white") +
geom_density(aes(y=..scaled..),alpha=.1, fill="#FF6666", size = 0.1, bw=1) +
labs(title=paste("Histogram of ",deparse(substitute(x))))
}
REMEMBER: double check column separator for each table. It is assumed to be “,”. Otherwise it must be changed in the corresponding code.
REMEMBER: Always check wich version of the eMAPS form are you using.
The code for the following sections is adapted to eMAPS v4.3
setwd("/Volumes/MacData/odrive/GDrive_UC/geo/cuenca/redu_edpa/maps eval/rspace/")
#Segment evaluation data
segori.df <-
read.csv("../../maps eval/rspace/piloto/inputs/20180908_segmentos.csv",
sep = ",",
stringsAsFactors = FALSE)
#lotes evaluation data
lot.df <-
read.csv("../../maps eval/rspace/piloto/inputs/20180908_lotes.csv",
sep = ",",
stringsAsFactors = FALSE)
# #Diccionario:
# dictseg.df <-
# read.csv("./piloto/inputs/diccionario_segmento.csv",
# sep = ",",
# stringsAsFactors = FALSE)
# segments geometry
segment_geo.sf <- st_read("../../maps eval/maps_template.sqlite", "segmentos_a_evaluar")
## Reading layer `segmentos_a_evaluar' from data source `/Volumes/MacData/odrive/GDrive_UC/geo/cuenca/redu_edpa/maps eval/maps_template.sqlite' using driver `SQLite'
## Simple feature collection with 708 features and 7 fields
## geometry type: LINESTRING
## dimension: XY
## bbox: xmin: 717836.9 ymin: 9676000 xmax: 731753.4 ymax: 9684605
## epsg (SRID): 32717
## proj4string: +proj=utm +zone=17 +south +datum=WGS84 +units=m +no_defs
segment_geo.df <- segment_geo.sf %>% st_set_geometry(NULL)
Some convenience preprocessing and data manipulation before applying the scoring.
#new dataframe to store preprocess data
seg.df <- segori.df
#rename columns for convenience
colnames(seg.df)[which(names(seg.df) == "Metodo_de_levantamiento")] <- "metodo_levantamiento"
colnames(seg.df)[which(names(seg.df) == "Nombre_del_evaluador")] <- "evaluador"
# reorder
seg.df <- seg.df[order(seg.df$X_index),]
# add segment length and slope from geometry data
seg.df <- merge(seg.df,
segment_geo.df[,c("seg_id","length", "slope_pcnt")],
by.x="Q_001",
by.y="seg_id",
all.x = TRUE )
str(seg.df)
## 'data.frame': 629 obs. of 143 variables:
## $ Q_001 : int 3 3 5 5 6 6 8 8 9 9 ...
## $ start : chr "2018-07-14T13:24:50.015-10" "2018-07-09T23:06:42.518-05:00" "2018-07-17T14:01:08.715-10" "2018-07-10T00:34:51.835-05:00" ...
## $ end : chr "2018-07-14T13:35:04.412-10" "2018-07-09T23:16:34.599-05:00" "2018-07-17T14:12:02.570-10" "2018-07-10T00:54:24.375-05:00" ...
## $ today : chr "2018-07-14" "2018-07-09" "2018-07-17" "2018-07-10" ...
## $ username : chr "maps" "username not found" "maps" "username not found" ...
## $ phonenumber : chr "" "phonenumber not found" "" "phonenumber not found" ...
## $ evaluador : chr "ama" "cp" "ama" "cp" ...
## $ Seleccion_de_formulario : chr "a" "a" "a" "a" ...
## $ metodo_levantamiento : chr "b" "c" "b" "c" ...
## $ Fecha_y_Hora_Inicial : chr "" "2018-07-09T23:07:00.000-05:00" "" "2018-07-10T00:35:00.000-05:00" ...
## $ Hora_Final : chr "" "" "" "" ...
## $ Q_000 : chr "01H00413" "01H00413" "01H00413" "01H00413" ...
## $ Q_002 : int 1 1 1 1 1 1 1 1 1 0 ...
## $ Fin_del_segmento : chr "" "" "" "" ...
## $ Q_003 : chr "c" "c" "c" "c" ...
## $ Q_004 : chr "a" "a" "a" "a" ...
## $ Q_005 : chr "b" "b" "c" "c" ...
## $ Q_006 : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_007 : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_008 : chr "" "" "" "" ...
## $ Q_008.a : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_008.b : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_008.c : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_008.d : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_008.e : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_008.f : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_008.g : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_009 : chr "f" "f" "f" "f" ...
## $ Q_010 : int NA NA NA NA NA NA NA NA 1 NA ...
## $ Q_011 : chr "c" "c" "c" "c" ...
## $ Q_012 : chr "c" "c" "c" "c" ...
## $ Q_013 : chr "a" "a" "b" "a" ...
## $ Q_014 : chr "a" "a" "b" "a" ...
## $ Atencion : chr "" "" "" "" ...
## $ Q_028_r : int 1 1 1 1 0 0 1 1 NA NA ...
## $ Q_028_l : int 1 1 1 1 1 1 1 1 NA NA ...
## $ Q_029_r : int 1 1 1 1 NA NA 1 1 NA NA ...
## $ Q_029_l : int 1 1 1 1 1 1 1 1 NA NA ...
## $ Q_030_r : num 2 1.8 2 2 NA NA 3 3 NA NA ...
## $ Q_030_l : num 2 1.8 2 2 1.5 1.2 3 2.5 NA NA ...
## $ Q_031_r : int 1 1 1 1 NA NA 1 1 NA NA ...
## $ Q_031_l : int 1 1 1 1 1 1 1 1 NA NA ...
## $ Q_032_r : int 4 2 3 2 NA NA 2 1 NA NA ...
## $ Q_032_l : int 4 3 2 2 2 2 2 1 NA NA ...
## $ Q_033_r : num 0 0 0 0 NA NA 0 0 NA NA ...
## $ Q_033_l : num 0 0 0 0 0 0 2.5 2.5 NA NA ...
## $ Q_034_r : int 4 4 4 4 NA NA 4 4 NA NA ...
## $ Q_034_l : int 4 4 4 4 4 4 4 1 NA NA ...
## $ Q_035_r : int 0 0 0 0 NA NA 0 0 NA NA ...
## $ Q_035_l : int 0 0 0 0 0 0 0 0 NA NA ...
## $ Q_036_r : int 0 0 0 0 0 0 2 0 0 NA ...
## $ Q_036_l : int 1 0 1 0 2 1 0 0 2 NA ...
## $ Q_037_r : int 0 0 0 0 0 0 1 0 0 NA ...
## $ Q_037_l : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_038_r : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_038_l : int 0 0 0 0 0 0 0 0 2 NA ...
## $ Q_039_r : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_039_l : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_040_r : int 2 1 0 0 0 0 1 1 0 NA ...
## $ Q_040_l : int 0 0 1 1 1 1 1 1 2 NA ...
## $ Q_041_r : int 0 0 3 3 0 0 2 0 0 NA ...
## $ Q_041_l : int 0 1 0 1 0 0 1 3 1 NA ...
## $ Q_042_r : int NA NA 2 1 NA NA NA NA NA NA ...
## $ Q_042_l : int NA NA NA NA NA NA NA 2 NA NA ...
## $ Q_043_r : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_043_l : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_044_r : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_044_l : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_045_r : int NA 0 NA 0 NA 0 NA 0 NA NA ...
## $ Q_045_l : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_046_r : int NA 0 NA 0 NA 0 NA 0 NA NA ...
## $ Q_046_l : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_047_r : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_047_l : int 0 0 0 1 2 1 0 0 0 NA ...
## $ Q_048_r : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_048_l : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_049_r : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_049_l : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_050_r : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_050_l : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_051_r : int 1 1 0 0 0 0 2 0 0 NA ...
## $ Q_051_l : int 2 0 0 0 1 0 2 0 0 NA ...
## $ Q_052_r : int 1 0 0 1 4 0 0 0 0 NA ...
## $ Q_052_l : int 0 0 0 0 0 0 0 1 0 NA ...
## $ Q_053_r : chr "c" "c" "c" "c" ...
## $ Q_053_l : chr "c" "c" "c" "c" ...
## $ Q_054_r : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_054_l : int NA NA NA NA NA NA NA NA NA NA ...
## $ Q_055_r : num NA NA NA NA NA NA NA NA NA NA ...
## $ Q_055_l : num NA NA NA NA NA NA NA NA NA NA ...
## $ Q_056_r : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_056_l : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_057_r : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_057_l : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_058_r : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_058_l : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_059_r : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_059_l : int 0 0 0 0 0 0 0 0 0 NA ...
## $ Q_060 : num 10 8 10 8 5 5 13 20 1.5 NA ...
## [list output truncated]
#new dataset to store scores
segsc.df <- seg.df[, c("Q_000",
"Q_001",
"Q_002",
"X_index",
"evaluador",
"metodo_levantamiento",
"length",
"slope_pcnt"
)]
segsc.df <- segsc.df[order(segsc.df$X_index),]
#number of parcels and built up parcels
lot.df$construido <- car::recode(lot.df$Q_017, "0=0;1:hi=1;else=0;")
agloteseg.df <- do.call(data.frame,
(
aggregate(
construido ~ X_parent_index,
data = lot.df,
FUN = function(x)
c(numlotes = length(x), numconstr = sum(x))
)
))
colnames(agloteseg.df) <- c("X_parent_index", "numlotes", "numconstr")
segsc.df <-
merge(
segsc.df,
agloteseg.df,
by.x = "X_index",
by.y = "X_parent_index",
all.x = TRUE
)
describe(segsc.df)
## vars n mean sd median trimmed mad
## X_index 1 629 322.01 186.71 321.00 321.66 238.70
## Q_000* 2 629 NaN NA NA NaN NA
## Q_001 3 629 3611.41 39994.08 413.00 383.30 231.29
## Q_002 4 629 0.91 0.29 1.00 1.00 0.00
## evaluador* 5 629 NaN NA NA NaN NA
## metodo_levantamiento* 6 629 NaN NA NA NaN NA
## length 7 604 97.23 52.00 94.59 92.11 45.67
## slope_pcnt 8 604 0.03 0.04 0.02 0.02 0.02
## numlotes 9 560 10.59 7.01 9.00 9.93 7.41
## numconstr 10 560 9.83 6.90 8.00 9.18 7.41
## min max range skew kurtosis se
## X_index 1.00 645.00 644.00 0.02 -1.21 7.44
## Q_000* Inf -Inf -Inf NA NA NA
## Q_001 3.00 505544.00 505541.00 12.38 151.66 1594.67
## Q_002 0.00 1.00 1.00 -2.81 5.92 0.01
## evaluador* Inf -Inf -Inf NA NA NA
## metodo_levantamiento* Inf -Inf -Inf NA NA NA
## length 15.76 326.84 311.08 1.00 1.55 2.12
## slope_pcnt 0.00 0.28 0.28 3.50 14.48 0.00
## numlotes 1.00 45.00 44.00 0.78 0.20 0.30
## numconstr 0.00 40.00 40.00 0.78 -0.07 0.29
In this subsection, subscales are created for sets of items. Code is provided to facilitate understanding how the subscales are created.
For most cases, subscale creation consists of three steps:
Original codes from the KoBo Toolbox application are converted into values.
Values are then dicothomized or thricotomized.
Subscale scores are computed as summatory of individual values.
Subscales and scores are based on the original MAPS protocol and adapted for the city of Cuenca, as a case study for intermediate cities in Latin America.
Streetscape refers to the overall facilities, amenities that are present in a street segment. This include:
segsc.df$ss_basureros <-
apply(seg.df[, c("Q_037_r", "Q_037_l")], 1, sum, na.rm = T)
segsc.df$ss_p_basureros_dic <-
car::recode(segsc.df$ss_basureros, "0=0;1:hi=1;else=0;")
segsc.df$ss_bancas <-
apply(seg.df[, c("Q_038_r", "Q_038_l")], 1, sum, na.rm = T)
segsc.df$ss_p_bancas_dic <-
car::recode(segsc.df$ss_bancas, "0=0;1:hi=1;else=0;")
segsc.df$ss_parqbici <-
apply(seg.df[, c("Q_039_r", "Q_039_l")], 1, sum, na.rm = T)
segsc.df$ss_p_parqbici_dic <-
car::recode(segsc.df$ss_parqbici, "0=0;1:hi=1;else=0;")
Includes existence and characteristics: shelter, information, bench)
#Bus stops
segsc.df$ss_pbus <- apply(seg.df[, c(
"Q_043_r",
"Q_043_l",
"Q_044_r",
"Q_044_l",
"Q_045_r",
"Q_045_l",
"Q_046_r",
"Q_046_l"
)]
, 1, sum, na.rm = T)
segsc.df$ss_p_pbus_tric <-
car::recode(segsc.df$ss_pbus, "0=0;1=1;2:hi=2")
max speed regulation, bumps, bump signal
#Traffic control
segsc.df$ss_p_velmax_dic <- car::recode(seg.df$Q_066, "'1'=1;'0'=0")
segsc.df$ss_p_rompvel_dic <- car::recode(seg.df$Q_067, "'1'=1;'0'=0")
segsc.df$ss_p_senalrompvel_dic <- car::recode(seg.df$Q_068, "'1'=1;'0'=0")
segsc.df$ss_p_tcontrol <- apply(segsc.df[, c(
"ss_p_velmax_dic",
"ss_p_rompvel_dic",
"ss_p_senalrompvel_dic"
)], 1, sum, na.rm = T)
segsc.df$ss_p_tcontrol_tric <-
car::recode(segsc.df$ss_p_tcontrol, "0=0;1=1;2:hi=2")
#Lights
segsc.df$ss_luminarias <- apply(seg.df[, c("Q_040_r",
"Q_040_l")]
, 1, sum, na.rm = T)
segsc.df$ss_luminariasprop <- with(segsc.df,ss_luminarias/length*100 )
segsc.df$ss_p_luminarias_dic <-car::recode(segsc.df$ss_luminarias,
"0:1=0;1:hi=1") #al menos una lámpara cada 100m
Cebra crossing=1, raised platform=2, overpass or inexistent=0
#Mid segment crossing
segsc.df$ss_p_crucemed_tric <- as.numeric(car::recode(seg.df$Q_069,
"'a'=1;'b'=2;'c'=0;'d'=0"))
Exists=1
#parterre
segsc.df$ss_p_parter_dic <- as.numeric(car::recode(seg.df$Q_064,
"1=1;0=0;"))
on the road, segregated = 2 on the road, no segregated = 1 on the sidewalk, segregated = 1 else = 0
segsc.df$cv_ciclovia <- with(seg.df,
ifelse((Q_053_l=='b'|Q_053_r=='b')&(Q_054_l=='1'|Q_054_r=='1'),2,
ifelse((Q_053_l=='b'|Q_053_r=='b'|Q_053_r=='a'|Q_053_r=='a')&
(Q_054_l=='0'|Q_054_r=='0'),1,
0
)))
Number of trees: 0:1=0;1:10=1;10:hi=2 (For the whole segment) Spacing: Even=1, uneven=0 (for each side)
#arboles----
segsc.df$arb_num <- apply(seg.df[, c("Q_041_r",
"Q_041_l")
], 1, sum, na.rm =T)
segsc.df$arb_numarb_tric <- car::recode(segsc.df$arb_num,
"0:1=0;1:10=1;10:hi=2",
as.numeric = T)
segsc.df$arb_esparb_r <- car::recode(seg.df$Q_042_r,
"1=1;else=0",
as.numeric = T)
segsc.df$arb_esparb_l <- car::recode(seg.df$Q_042_l,
"1=1;else=0",
as.numeric = T)
segsc.df$arb_esparb_tric <- apply(segsc.df[, c("arb_esparb_r",
"arb_esparb_l")
], 1, sum, na.rm =T)
segsc.df$arb_positivo <- apply(segsc.df[, c("arb_numarb_tric",
"arb_esparb_tric")
], 1, sum, na.rm =T)
Is there a path, stairs o briddge connecting to the segment? Yes=1
#Total connectors
segsc.df$con_conectores <- apply(seg.df[, c("Q_056_r",
"Q_056_l",
"Q_057_r",
"Q_057_l",
"Q_058_r",
"Q_058_l",
"Q_059_r",
"Q_059_l")
], 1, sum, na.rm =T)
segsc.df$con_conect_dic <- car::recode(segsc.df$con_conectores,
"0=0;1:hi=1",
as.numeric = T)
#total streetscape positive
segsc.df$ss_positivo <- apply(segsc.df[, c("ss_p_basureros_dic",
"ss_p_bancas_dic",
"ss_p_parqbici_dic",
"ss_p_pbus_tric",
"ss_p_tcontrol_tric",
"ss_p_crucemed_tric",
"ss_p_luminarias_dic",
"ss_p_parter_dic",
"ss_p_plataf_dic",
"cv_ciclovia",
"arb_positivo",
"con_conect_dic"
)], 1, sum, na.rm = T)
psych::describe(segsc.df$ss_positivo)
## vars n mean sd median trimmed mad min max range skew kurtosis se
## X1 1 629 1.79 1.77 1 1.51 1.48 0 10 10 1.38 1.86 0.07
myhist.f(segsc.df$ss_positivo)
The curbs allow cars to roll-over and invade the sidewalk
#roll-over curbs
segsc.df$ss_bordred <- apply(seg.df[, c("Q_035_r", "Q_035_l")], 1, sum, na.rm = T)
segsc.df$ss_n_bordred_dic <- car::recode(segsc.df$ss_bordred, "0=0;1:hi=1")
There is no lighting
#luminarias
segsc.df$ss_n_lumin_dic <- car::recode(segsc.df$ss_luminarias, "0:1=1;1:hi=0")
There are driveways difficulting the pedestrian circulation
#accesos vehiculares
segsc.df$ss_accesvehi <- apply(seg.df[, c("Q_059_r",
"Q_059_l")]
, 1, sum, na.rm = T)
segsc.df$ss_n_accesvehi_dic <- car::recode(segsc.df$ss_accesvehi,
"0=0;1:hi=1")
1:2=0,3:4=1,>5:2
#carriles
segsc.df$ss_n_carriles_tric <- as.numeric(car::recode(seg.df$Q_062,
"'a'=0;
'b'=1;
'c'=2;
'd'=2;
else=0"))
#vehiculos estacionados
segsc.df$ss_n_vehi_dic <- as.numeric(car::recode(seg.df$Q_063,
"0=0;1:hi=1"))
What is the overall slope of the street segment (percent)? 0:0.1 = 0; >0.1=1
#Slope > 0.1
segsc.df$sl_slope_dic <- car::recode(segsc.df$slope_pcnt,
"0:0.05 = 0;
0.05:0.1=1;
0.1:0.15=2;
0.15:hi=3;
else=0",
as.numeric = T)
segsc.df$ss_negativo <- apply(segsc.df[, c("ss_n_bordred_dic",
"ss_n_lumin_dic",
"ss_n_accesvehi_dic",
"ss_n_vehi_dic",
"sl_slope_dic",
"ss_n_carriles_tric"
)], 1, sum, na.rm = T)
myhist.f(segsc.df$ss_negativo)
Streetscape positive minus streetscape negative
segsc.df$ss_streetscape_total <- segsc.df$ss_positivo - segsc.df$ss_negativo
head(segsc.df[,c("Q_001","ss_positivo", "ss_negativo", "ss_streetscape_total")], 10)
## Q_001 ss_positivo ss_negativo ss_streetscape_total
## 1 230 1 1 0
## 2 231 0 2 -2
## 3 271 1 3 -2
## 4 223 2 1 1
## 5 281 0 2 -2
## 6 588 0 1 -1
## 7 596 4 2 2
## 8 612 3 2 1
## 9 607 2 0 2
## 10 452 0 1 -1
myhist.f(segsc.df$ss_streetscape_total)
In this section, sidewalk existence and characteristics are evalauted. Both sides (left and right) are evaluated.
Exists = 1
segsc.df$ac_p_existe <- apply(seg.df[, c("Q_028_l",
"Q_028_r")], 1, sum, na.rm = T)
Sidewalk quality will be included in both Positive and Negative subscales Good or excelent = 1, else = 0
segsc.df$ac_buenestado_r <- car::recode(seg.df$Q_032_r,
"1:2=1;3:5=0;")
segsc.df$ac_buenestado_l <- car::recode(seg.df$Q_032_l,
"1:2=1;3:5=0;")
segsc.df$ac_p_buenestado <-apply(segsc.df[, c("ac_buenestado_r",
"ac_buenestado_l")
],
1, sum, na.rm =T)
width < 1.5m = 0, width >1.5m = 1
segsc.df$ac_ancho_l_dic <- car::recode(seg.df$Q_030_l,
"0:1.5=0;1.5:hi=1;else=0;",
as.numeric = T)
segsc.df$ac_ancho_r_dic <- car::recode(seg.df$Q_030_r,
"0:1.5=0;1.5:hi=1;else=0;",
as.numeric = T)
segsc.df$ac_p_ancho <- rowSums(segsc.df[,c("ac_ancho_l_dic","ac_ancho_r_dic")], na.rm=T)
If exists (width >0) = 1
segsc.df$ac_buffer_l <- car::recode(seg.df$Q_033_l,
"0=0;0:hi=1;else=0;",
as.numeric = T
)
segsc.df$ac_buffer_r <- car::recode(seg.df$Q_033_r,
"0=0;0:hi=1;else=0;",
as.numeric = T
)
segsc.df$ac_p_buffer <- apply(segsc.df[, c("ac_buffer_l",
"ac_buffer_r")
], 1, sum, na.rm =T)
If it is a pedestrian street, none of the previous will apply, and 8 points is assigned to the segment.
segsc.df$ac_p_peatonal <-as.integer(car::recode(seg.df$Q_004,
"'a'=0;'b'=8;else=0",
as.numeric = T
))
segsc.df$ac_positivo<- apply(segsc.df[, c("ac_p_existe",
"ac_p_buenestado",
"ac_p_ancho",
"ac_p_buffer",
"ac_p_peatonal")
], 1, sum, na.rm =T)
myhist.f(segsc.df$ac_positivo)
The sidewalk is continuous = 0, else = 0
segsc.df$ac_contin_r <- car::recode(seg.df$Q_029_r,
"0=1;1=0")
segsc.df$ac_contin_l <- car::recode(seg.df$Q_029_l,
"0=1;1=0")
segsc.df$ac_n_continuidad <-apply(segsc.df[, c("ac_contin_r",
"ac_contin_l")
],
1, sum, na.rm =T)
Bad or very bad = 1, else = 0
segsc.df$ac_estado_r <- car::recode(seg.df$Q_032_r,
"1:3=0;4:5=1;")
segsc.df$ac_estado_l <- car::recode(seg.df$Q_032_l,
"1:3=0;4:5=1;")
segsc.df$ac_n_estado <-apply(segsc.df[, c("ac_estado_l",
"ac_estado_r")
],
1, sum, na.rm =T)
All kind of obstacles are included: Avoidable = 0.5, Unavoidable = 1. Sums of obstacles scores are recoded: 0=0, 0:1=1, >1=2
#Obstáculos salvables.
segsc.df$ac_obssal <- apply(seg.df[, c("Q_047_r",
"Q_047_l",
"Q_049_r",
"Q_049_l")
],
1, sum, na.rm =T)
#obstáculos insalvables
segsc.df$ac_obsinsal <-apply(seg.df[, c("Q_048_r",
"Q_048_l",
"Q_050_r",
"Q_050_l")
],
1, sum, na.rm =T)
segsc.df$ac_n_obstaculos <- with(segsc.df, ac_obssal* 0.5 + ac_obsinsal)
segsc.df$ac_obs_dic <- car::recode(segsc.df$ac_n_obstaculos,
"0=0;0.1:1=1;1:hi=2;")
Vehicle ramps hinder the normal walking on the sidewalk.
# Ramps are evaluated on the "lote" table
ramp_segm <- aggregate(Q_021 ~ X_parent_index, data = lot.df, FUN = sum)
colnames(ramp_segm) <- c("X_index", "ss_rampvehi")
segsc.df <-
merge(segsc.df,
ramp_segm,
by.x = "X_index",
by.y = "X_index",
all.x = T)
segsc.df$ac_n_rampvehi_dic <- car::recode(segsc.df$ss_rampvehi, "0:1=0;1:5=1;6:hi=2;")
segsc.df$ac_negativo <- apply(segsc.df[, c("ac_n_continuidad",
"ac_n_estado",
"ac_obs_dic",
"ac_n_rampvehi_dic")
],1, sum, na.rm =T)
myhist.f(segsc.df$ac_negativo)
segsc.df$ac_aceras_total <- segsc.df$ac_positivo - segsc.df$ac_negativo
myhist.f(segsc.df$ac_aceras_total)
summary(segsc.df$ac_aceras_total)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -5.000 0.000 2.000 2.132 4.000 8.000
Facades to the street segment can contribute to walkability in several ways: Doors and windows, transparency, vegetation, and aesthetics of the buildings.
Porportion of buildings with street-level windows. 0:0.25=0;:0.25:0.75=1;0.75:hi=2;
## this comes from "lotes table"
#does the building have windows
lot.df$fa_ventanas <- car::recode(lot.df$Q_022,
"0=0;1:hi=1;else=0;",
as.numeric = T
)
#number of windows per segment
ventanas <- aggregate(fa_ventanas ~ X_parent_index,
data = lot.df,
FUN = function(x) sum(x))
segsc.df <- merge(segsc.df,
ventanas,
by.x = "X_index",
by.y = "X_parent_index",
all.x = TRUE)
#Proportion of buildings with windows
segsc.df$fa_ventanasprop <- round(segsc.df$fa_ventanas / segsc.df$numconstr, 3)
segsc.df$fa_p_ventanas_tric <- as.integer(car::recode(segsc.df$fa_ventanasprop,
"0:0.25=0;
0.25:0.75=1;
0.75:hi=2;
else=0",
as.numeric = T
))
Proportion of buildings with front doors 0:0.50=0;0.50:hi=1;else=0
##El edificio tiene puerta peatonal
lot.df$fa_puertas <- car::recode(lot.df$Q_019,
"0=0;1:hi=1;else=0;",
as.numeric = T
)
#puertas peatonales por segmento
puertas <- aggregate(fa_puertas ~ X_parent_index,
data = lot.df,
FUN = function(x) sum(x))
segsc.df <- merge(segsc.df,
puertas,
by.x = "X_index",
by.y = "X_parent_index",
all.x = TRUE)
#Proporcion de edificaciones con puertas peatonales
segsc.df$fa_puertasprop <- round(segsc.df$fa_puertas / segsc.df$numconstr, 3)
segsc.df$fa_p_puertas_dic <- as.integer(car::recode(segsc.df$fa_puertasprop,
"0:0.50=0;0.50:hi=1;else=0",
as.numeric = T
))
Proportion of buildings with transparent or semi-transparent enclosure 0:0.25=0;0.25:0.75=1;0.75:hi=2;else=0
##El edificio tiene cerramiento transparente o semi transparente
lot.df$fa_transparente <- car::recode(lot.df$Q_024,
"'a'=1;'b'=1;'c'=0;else=0;",
as.numeric = T
)
#transparentes por segmento
transparentes <- aggregate(fa_transparente ~ X_parent_index,
data = lot.df,
FUN = function(x) sum(x))
segsc.df <- merge(segsc.df,
transparentes,
by.x = "X_index",
by.y = "X_parent_index",
all.x = TRUE)
#Proporcion de edificaciones con cerramiento transparente
segsc.df$fa_transparenteprop <- round(segsc.df$fa_transparente / segsc.df$numconstr, 3)
segsc.df$fa_p_transparente_tric <- as.integer(car::recode(segsc.df$fa_transparenteprop,
"0:0.25=0;0.25:0.75=1;0.75:hi=2;else=0",
as.numeric = T
))
Proportion of buildings with vegetation on the enclosure or seatback 0:0.25=0;0.25:0.75=1;0.75:hi=2;else=0
##El edificio tiene cerramiento con vegetacion
lot.df$fa_vegetal <- car::recode(lot.df$Q_025,
"'c'=1;'d'=1;else=0;",
as.numeric = T
)
#cerramientos con vegetacion por segmento
vegetal <- aggregate(fa_vegetal ~ X_parent_index,
data = lot.df,
FUN = function(x) sum(x))
segsc.df <- merge(segsc.df,
vegetal,
by.x = "X_index",
by.y = "X_parent_index",
all.x = TRUE)
#Proporcion de edificaciones con cerramiento con vegetacion
segsc.df$fa_vegetalprop <- round(segsc.df$fa_vegetal / segsc.df$numlotes, 3)
segsc.df$fa_p_vegetalprop_dic <- as.integer(car::recode(segsc.df$fa_vegetalprop,
"0:0.75=0;0.75:hi=1;else=0",
as.numeric = T
))
If more than 90% of buildings are well maintained = 1
# ths is an aggregated measure from the "lotes" table
lot.df$fa_mantedif <- car::recode(lot.df$Q_023,
"'a'=1;'b'=0;'c'=0;'d'=0;'e'=0;"
)
mant_edif <- do.call(data.frame,
(aggregate(fa_mantedif ~ X_parent_index,
data = lot.df,
FUN = function(x) c(bien = sum(x), n=length(x))
)))
colnames(mant_edif) <- c("X_parent_index","fa_mantedif_bien","fa_mantedif_n")
segsc.df <- merge(segsc.df,
mant_edif,
by.x = "X_index",
by.y = "X_parent_index",
all.x = TRUE)
segsc.df$fa_mantedifprop <- round(segsc.df$fa_mantedif_bien / segsc.df$fa_mantedif_n, 3)
segsc.df$fa_p_mantedifprop_dic <- as.integer(car::recode(segsc.df$fa_mantedifprop,
"0:0.9=0;0.9:hi=1;else=0",
as.numeric = T
))
segsc.df$fa_fachadas_pos <- apply(segsc.df[, c("fa_p_ventanas_tric",
"fa_p_puertas_dic",
"fa_p_transparente_tric",
"fa_p_vegetalprop_dic",
"fa_p_mantedifprop_dic")
], 1, sum, na.rm =T)
myhist.f(segsc.df$fa_fachadas_pos)
summary(segsc.df$fa_fachadas_pos)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 2.00 3.00 2.56 4.00 7.00
Facades to the street segment can hinder walkability if buildings are poorly maintained or there are no windows or transparency (blind walls)
Blind walls are segments of the street where less than 10% of buldings have windows at the street level
#proportion of windows was already computed on "Windows" section
segsc.df$fa_n_murociego <- as.integer(car::recode(segsc.df$fa_ventanasprop,
"0:0.1=1;
0.1:hi=0;
else=0",
as.numeric = T
))
If more than 50% of buildings are poorly or very poorly mainateined
# ths is an aggregated measure from the "lotes" table
lot.df$fa_mantedifmal <- car::recode(lot.df$Q_023,
"'a'=0;'b'=0;'c'=1;'d'=1;'e'=0;"
)
mant_edif_mal <- do.call(data.frame,
(aggregate(fa_mantedifmal ~ X_parent_index,
data = lot.df,
FUN = function(x) c(mal = sum(x), n=length(x))
)))
colnames(mant_edif_mal) <- c("X_parent_index","fa_mantedif_mal","fa_mantedifmal_n")
segsc.df <- merge(segsc.df,
mant_edif_mal,
by.x = "X_index",
by.y = "X_parent_index",
all.x = TRUE)
segsc.df$fa_mantedifmalprop <- round(segsc.df$fa_mantedif_mal / segsc.df$fa_mantedifmal_n, 3)
segsc.df$fa_n_mantedifmalprop_dic <- as.integer(car::recode(segsc.df$fa_mantedifmalprop,
"0:0.49=0;0.49:hi=1;else=0",
as.numeric = T))
More than 25% of the segment lots are empty = 1
# ths is an aggregated measure from the "lotes" table
lotes_vacios <- do.call(data.frame,
(aggregate(Q_018_o1 ~ X_parent_index,
data = lot.df,
FUN = function(x) c(vacios = sum(x), n=length(x))
)))
colnames(lotes_vacios) <- c("X_parent_index","vacios","n")
lotes_vacios$prop_vacios <- with(lotes_vacios, vacios/n)
segsc.df <- merge(segsc.df,
lotes_vacios[,c("X_parent_index","prop_vacios")],
by.x = "X_index",
by.y = "X_parent_index",
all.x = TRUE)
segsc.df$fa_n_prop_vacios_dic <- as.integer(car::recode(segsc.df$prop_vacios,
"0.25:hi=1;else=0",
as.numeric = T))
segsc.df$fa_fachadas_neg <- apply(segsc.df[, c("fa_n_murociego",
"fa_n_mantedifmalprop_dic",
"fa_n_prop_vacios_dic")
], 1, sum, na.rm =T)
myhist.f(segsc.df$fa_fachadas_neg)
summary(segsc.df$fa_fachadas_neg)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0000 0.0000 0.0000 0.1383 0.0000 2.0000
segsc.df$fa_fachadas_total <- segsc.df$fa_fachadas_pos - segsc.df$fa_fachadas_neg
myhist.f(segsc.df$fa_fachadas_total)
summary(segsc.df$fa_fachadas_total)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -2.000 2.000 3.000 2.421 3.000 7.000
Presence and characteristics of the traffic lights and signage at the intersection (start and end intersections). A complete intersection must have all signals.
Complete signaled intersection = 2 Partially signaled intersection = 1 No signaled intersection = 0
#Signals at initial intersection
segsc.df$in_signals_i <- apply(seg.df[,c("Q_008.a",
"Q_008.b",
"Q_008.c",
"Q_008.d",
"Q_008.e",
"Q_008.f",
"Q_008.g")
],1,sum, na.rm=T)
segsc.df$in_signals_i_tric <- as.integer(car::recode(segsc.df$in_signals_i,
"1:6=1;7=2;else=0",
as.numeric = T))
#Signals at end intersection
segsc.df$in_signals_f <- apply(seg.df[,c("Q_077.a",
"Q_077.b",
"Q_077.c",
"Q_077.d",
"Q_077.e",
"Q_077.f",
"Q_077.g")
],1,sum, na.rm=T)
segsc.df$in_signals_f_tric <- as.integer(car::recode(segsc.df$in_signals_f,
"1:6=1;7=2;else=0",
as.numeric = T))
# signals total
segsc.df$in_p_signals <- with(segsc.df, in_signals_i_tric+in_signals_f_tric)
Curbs must have ramps aligned with the crossing at both sides
segsc.df$in_ramps_i <-
as.integer(car::recode(seg.df$Q_011,"'a'=1;else=0", as.numeric = T)) +
as.integer(car::recode(seg.df$Q_012,"'a'=1;else=0",as.numeric = T))
segsc.df$in_ramps_f <-
as.integer(car::recode(seg.df$Q_080,"'a'=1;else=0", as.numeric = T)) +
as.integer(car::recode(seg.df$Q_081,"'a'=1;else=0",as.numeric = T))
segsc.df$in_p_ramps <- with(segsc.df, in_ramps_i+in_ramps_f)
Crrossing type: Raised crossing = 2, other =1, none = 0
Curb extension: exists = 1
#crossing type
segsc.df$in_crossing_i <-
as.integer(car::recode(seg.df$Q_009,"'a'=1;'b'=1;'c'=1;'d'=2;else=0", as.numeric = T))
segsc.df$in_crossing_f <-
as.integer(car::recode(seg.df$Q_078,"'a'=1;'b'=1;'c'=1;'d'=2;else=0", as.numeric = T))
# curb extension
segsc.df$in_curbext_i <- as.integer(car::recode(seg.df$Q_007,"1=1;else=0", as.numeric = T))
segsc.df$in_curbext_f <- as.integer(car::recode(seg.df$Q_076,"1=1;else=0", as.numeric = T))
segsc.df$in_p_crossdesign <- apply(segsc.df[,c("in_crossing_i",
"in_crossing_f",
"in_curbext_i",
"in_curbext_f")
],1,sum, na.rm=T)
segsc.df$in_intersections_pos <- apply(segsc.df[, c("in_p_signals",
"in_p_ramps",
"in_p_crossdesign")
], 1, sum, na.rm =T)
myhist.f(segsc.df$in_intersections_pos)
summary(segsc.df$in_intersections_pos)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 1.000 1.838 3.000 10.000
segsc.df$in_discont_i <- as.integer(car::recode(seg.df$Q_010,"1=1;else=0", as.numeric = T))
segsc.df$in_discont_f <- as.integer(car::recode(seg.df$Q_079,"1=1;else=0", as.numeric = T))
segsc.df$in_n_discont <- apply(segsc.df[, c("in_discont_i",
"in_discont_f")
], 1, sum, na.rm =T)
Roundabouts and intersections with 4 or more legs have negative impact.
Roundabouts = 1
’# of legs: <3 = 0, 4:1, 5+=2
segsc.df$in_legs_i <- as.integer(car::recode(seg.df$Q_005,
"'a'=0;'b'=0;'c'=1;'d'=2;else=0",
as.numeric = T))
segsc.df$in_legs_f <- as.integer(car::recode(seg.df$Q_074,
"'a'=0;'b'=0;'c'=1;'d'=2;else=0",
as.numeric = T))
segsc.df$in_roundabout_i <- as.integer(car::recode(seg.df$Q_006,"1=1;else=0", as.numeric = T))
segsc.df$in_roundabout_f <- as.integer(car::recode(seg.df$Q_075,"1=1;else=0", as.numeric = T))
segsc.df$in_n_intconfig <- apply(segsc.df[, c("in_legs_i",
"in_legs_i",
"in_roundabout_i",
"in_roundabout_f")
], 1, sum, na.rm =T)
Curbs height in each side > 40cm = 1
segsc.df$in_curbh_i <- as.integer(car::recode(seg.df$Q_013,
"'a'=0;'b'=0;'c'=1;'d'=0;else=0",
as.numeric = T)) +
as.integer(car::recode(seg.df$Q_014,
"'a'=0;'b'=0;'c'=1;'d'=0;else=0",
as.numeric = T))
segsc.df$in_curbh_f <- as.integer(car::recode(seg.df$Q_082,
"'a'=0;'b'=0;'c'=1;'d'=0;else=0",
as.numeric = T)) +
as.integer(car::recode(seg.df$Q_083,
"'a'=0;'b'=0;'c'=1;'d'=0;else=0",
as.numeric = T))
segsc.df$in_n_curbheight <- apply(segsc.df[, c("in_curbh_i",
"in_curbh_f")
], 1, sum, na.rm =T)
segsc.df$in_intersections_neg <- apply(segsc.df[, c("in_n_discont",
"in_n_intconfig",
"in_n_curbheight")
], 1, sum, na.rm =T)
myhist.f(segsc.df$in_intersections_neg)
summary(segsc.df$in_intersections_neg)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 1.000 1.463 2.000 6.000
segsc.df$in_intersections_total <- with(segsc.df, in_intersections_pos - in_intersections_neg)
myhist.f(segsc.df$in_intersections_total)
summary(segsc.df$in_intersections_total)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -6.0000 -1.0000 0.0000 0.3752 1.0000 6.0000
total so far.
segsc.df$partial_score <- apply(segsc.df[, c("ss_streetscape_total",
"ac_aceras_total",
"fa_fachadas_total",
"in_intersections_total")
], 1, sum, na.rm =T)
myhist.f(segsc.df$partial_score)
summary(segsc.df$partial_score)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -7.000 2.000 5.000 5.275 9.000 23.000