A velocidade caracteriza-se como um relevante indicador da qualidade de serviço das vias. Enquanto característica de tráfego ela assume diversas formas de obtenção de acordo com a base espaço/temporal utilizada.
Afim de validar os dados do waze foram utilizados dados de filas do waze bem como registros de velocidades veículares capturadas pelos controladores de velocidade do município de Porto Alegre. Os dados utilizados consistem de dados de velocidade pontual {velocidade instantânea de um veículo quando passa por um ponto ou seção da via} correspondentes aos dados coletados pelos controladores eletrônicos; bem como de dados de velocidade média de viagem ou velocidade média no espaço {dada pela razão do comprimento do trecho pelo tempo gasto no percurso} correspondendo aos dados coletados pelo WAZE.
Conforme os métodos de amostragem utilizados as velocidades calculadas costumam apresentar características específicas. Em pontos de coleta como controladores eletrônicos de velocidade a amostragem costuma apresentar uma distribuição normal ,uma vez que estes ficam localizados em pontos que apresentam características de fluxo inisnterrupto; onde a velocidade é dada pelo deslocamento no tempo (deslocamento/tempo)[grandeza vetorial]. Já a distribuição de velocidades médias no espaço originadas de filas apresentam inclinação à direita, uma vez que concentram informações de velocidades significativamente baixas e algumas amostras de velocidade relativamente baixas, dadas pela razão distancia percorrida/tempo gasto [grandeza escalar].
Como as velocidades dadas pelo waze correspondem a um dado período de tempo de percurso, afim de comparar tais velocidades com aquelas obtidas pelo controlador eletrônico as velocidades do controlador foram tratadas para gerar o valor de velocidade média no tempo, correspondendo à média aritimética das velocidades pontuais de todos veículos durante o intervalo que equivale a 5 antes do alerta de fila e a 5 após o alerta de fila. Dessa forma buscou-se verificar o quanto a velocidade média no espaço obtida do WAZE se aproxima da velocidade média no tempo dada pelo conrolador e a que taxa.
Inicialmente realizou-se a instanciação das bibliotecas necessárias para tratamento, análise e apresentação de dados.
library(jsonlite)
library(dplyr)
library(tidyr)
library(sp)
library(mapview)
library(stringr)
library(raster)
library(leaflet.extras)
library(geosphere)
library(rgeos)
O passo seguinte foi carregar os dados persistidos de filas do waze
#setwd("C:/Users/fsmoura/OneDrive/r-files/CIET/waze_download/")
dados = load("waze.Rda")
Após foram obtidos os dados de filas referentes ao mês de outubro de 2019.
waze$hora = substring(waze$pubMillis, 12,17)
waze = waze[waze$pubMillis >= "2019-10-01", ]
waze = waze[waze$pubMillis < "2019-11-01", ]
waze$fx_hora = substring(waze$pubMillis, 12,13)
Aplicou-se uma restrição para vias com controlador eletrônico de velocidade, tomando cuidado de manter apenas vias pouca ou nenhuma alternativa em situações de congestionamento. Dessa forma buscou-se considerar apenas vias em que os usuários do Waze não possam utilizar rotas alternativas, de outra forma, vias muito capilarizadas fazem com que o algorítimo de rotas do app direcione o fluxo de usuários para outras vias acabando por reduzir a amostragem na via de interesse.
vias_de_interesse = c('R. Voluntários da Pátria', 'Av. Juca Batista', 'Av. Prof. Oscar Pereira', 'Av. Icaraí',
'Av. Plínio Brasil Milano', 'Av. Baltazar de Oliveira Garcia', 'Av. Antônio de Carvalho')
waze = subset(waze,city %in% c('Porto Alegre'))
waze = subset(waze,street %in% vias_de_interesse)
O próximo tratamento aplicado foi a restrição de período de análise. Nessa etapa foram descartados eventos de finais de semana e aqueles entre as 20 e 6 horas.
waze = waze %>%
filter(str_detect(dia, "feira"))
filas_fx_hora = as.data.frame(table(waze$fx_hora))
totalAlertas = sum(filas_fx_hora$Freq)
waze = waze[waze$hora > "06:00", ]
waze = waze[waze$hora < "20:00", ]
percentualFora = round((totalAlertas - length(waze$country))/totalAlertas, 2)*100
A titulo de exploração de dados, é possível perceber que entre as 20 e as 6 horas o número de ocorrencias de filas é muito pequeno, correspondendo a 2% do total de filas, como pode visto na tabela abaixo:
names(filas_fx_hora) = c("Faixa Horária", "N° de Filas registradas")
filas_fx_hora
Afim de identificar o sentido das vias utilizou-se a mesma nomenclatura dos controladores “cb” (Centro -> Bairro) e “bc” (Bairro -> Centro). Para tanto procedeu-se com a criação da variável “sentido” inicialmente defida como “cb” para todos os exemplares.
congestionamentos = waze
congestionamentos$sentido = "cb"
Afim de classificar as vias nos sentidos “cb” e “bc” o ponto de referência escolhido foi a Praça da Alfândega, caracterizada como o centro radial do bairro Centro Histórico. Dessa forma a cada fila de congestionamento foram tomadas as coordenadas inicial e final correspondentes para obtenção da distância euclidiana de ambas em relação ao ponto de referência no centro histórico. Uma vez obtidas as duas métricas aquelas filas onde a coordenada final estava mais próxima do ponto de referência foram classificadas como “bc”, uma vez que a direção do vetor entre origem e destino da fila aponta para o bairro Centro Histórico. Este procedimento de classificação de orientação da fila foi implementado de forma aninhada ao processo iterativo em que as filas do waze são transformadas em objetos espaciais a serem armazenados um array de filas.
pracaAlfandega = as.data.frame(cbind(c(-51.23105), c(-30.02961)))
antonioCarvalho = as.data.frame(cbind(c(-51.15170), c(-30.07058)))
lista = list()
nomes_linhas = list()
for (i in 1:length(congestionamentos$country)) {
nomes_linhas[i] = i
teste = congestionamentos$line[i]
teste = as.data.frame(teste)
inicioLinha = head(teste,1)
fimLinha = tail(teste,1)
ACinicioLinha = pointDistance(antonioCarvalho, inicioLinha, lonlat=TRUE)
ACfimLinha = pointDistance(antonioCarvalho, fimLinha, lonlat=TRUE)
inicioLinha = pointDistance(pracaAlfandega, inicioLinha, lonlat=TRUE)
fimLinha = pointDistance(pracaAlfandega, fimLinha, lonlat=TRUE)
if (fimLinha < inicioLinha) {
congestionamentos$sentido[i] = "bc"
}
if (congestionamentos$street[i] == "Av. Antônio de Carvalho") {
if (ACfimLinha < ACinicioLinha) {
congestionamentos$sentido[i] = "ns"
}else{
congestionamentos$sentido[i] = "sn"
}
}
l1 = cbind(c(teste$x),c(teste$y))
Sl1 = Line(l1)
S1 = Lines(list(Sl1), ID=i)
lista[i] = S1
}
O passo seguinte foi criar uma base unica de geometrias das filas do tipo SpatialLines.
Sl = SpatialLines(lista)
Então procedeu-se com a projeção espacial dos dados, de forma a torná-los compátiveis com arquiteturas de GIS.
proj4string(Sl) <- CRS("+init=epsg:4326")
Uma fez que os dados de fila do Waze apresentam uma série de atributos como velocidade, atraso, extensão da fila, etc. foi criado um objeto do tipo “SpatialLinesDataFrame”. Um SpatialLinesDataFrame se configura de um banco de dados geoespacial que reune a geometria das filas associando às mesmas os atributos correspondentes em forma de banco de dados.
row.names(congestionamentos) = row.names(Sl)
SlDF <- SpatialLinesDataFrame(Sl, data = congestionamentos[,c(1:3, 5:22)])
#dim(congestionamentos)
#paste("Atraso médio: ", mean(congestionamentos$delay), "s", sep = "")
#paste("Fila média: ", mean(congestionamentos$length), "m", sep = "")
#paste("Velocidade média: ", mean(congestionamentos$speedKMH), "km/h", sep = "")
Uma vez tratados os dados e conformados em um banco de dados espacial, os tados foram plotados em mapa interativo para uma primeira exploração.
paletta = colorRampPalette(c("#ff0000","#cc0099", "orange", "yellow", "green", "blue"), space="Lab" )
mapview(SlDF, zcol= 'speedKMH', color = paletta, layer.name = 'Velocidade Média', lwd=4,
legend = TRUE, map.types=c("CartoDB.DarkMatter", "OpenStreetMap", "Esri.WorldImagery", "Esri.WorldStreetMap"))
Após todos os tratamentos, a base de dados consolidada pode ser visualizada na seguinte tabela:
head(congestionamentos, 10)
Como o mapa acima apresenta filas ao longo de toda extensão das vias sob análise e o objetivo foi comparar velocidades das filas do Waze próximas aos controladores de tráfego com os registros do próprio controlador; procedeu-se com a eliminação de registros de filas a uma distância superior a 30 metros do controlador de referência e com extensão inferior à 1000.
Afim de poder gerar tal segregação, foi gerado um objeto representando um raio de 30 metros ao redor do controlador correspondendo à área a ser considerada para análise das filas.
source("../../funcoes/makeDotBuffer.R")
# CB
pts <- data.frame(lon = c(-51.213555),
lat = c(-30.018315))
pts_buf_100km <- make_GeodesicBuffer(as.matrix(pts), width = raio)
Uma vez criado o objeto, o mesmo foi reprojetado para o mesmo sistema de projeção geográfica utilizado nos objetos de análise.
source("../../funcoes/makeDotBuffer.R")
projection(pts_buf_100km)=projection(SlDF)
O objeto que representa a área de interesse pode ser visualizado no mapa abaixo:
map =leaflet() %>%
addTiles() %>%
addProviderTiles("CartoDB.Positron", options= providerTileOptions(opacity = 0.99)) %>%
addPolygons(data = pts_buf_100km,
stroke = FALSE, fillOpacity = 0.5, smoothFactor = 0.5
)
map
Havendo criado o objeto que representa a área de análise, foi realizada a interseção entre o objeto e as filas do Waze, onde apenas as filas inserias no interior do mesmo foram mantidas para comparação das velocidades das filas e velocidades registradas no controlador.
eth.clip <- raster::intersect(SlDF, pts_buf_100km)
eth.clip = eth.clip[eth.clip$sentido == "cb", ]
#eth.clip
A título de ilustração, o mapa abaixo apresenta o trecho avisinhado a um controlador, onde são exibidas apenas aquelas filas inseridas na área de abranhgência de 30 metros do controlador.
mapview(eth.clip, zcol= 'speedKMH', color = paletta, layer.name = 'Velocidade Média', lwd=4,
legend = TRUE, map.types=c("CartoDB.DarkMatter", "OpenStreetMap", "Esri.WorldImagery", "Esri.WorldStreetMap"))
dftab = as.data.frame(eth.clip)
dftab = dftab[dftab$sentido == "cb",]
dftab$fx_hora = as.numeric(dftab$fx_hora)
# dftab = dftab[dftab$fx_hora > 16, ]
# dftab = dftab[dftab$fx_hora < 20, ]
dftab = dftab[dftab$length < fila, ]
voluntarios = read.csv("../data/voluntarios.csv", header = T, sep = ";", check.names = FALSE)
voluntarios = voluntarios[grepl("C/B",voluntarios$LOCAL,fixed=T),]
voluntarios$DATA = paste(substring(voluntarios$DATA, 7, 10), substring(voluntarios$DATA, 4, 5), substring(voluntarios$DATA, 1, 2),sep = "-")
voluntarios$DATA = paste(voluntarios$DATA, voluntarios$HORçRIO, sep = " ")
voluntarios$DATA = as.POSIXct(voluntarios$DATA)
operacao = dftab[1, ]
library(lubridate)
##
## Attaching package: 'lubridate'
## The following object is masked from 'package:base':
##
## date
intervalo_inferior = operacao$pubMillis - minutes(min)
intervalo_superior = operacao$pubMillis + minutes(max)
control = voluntarios[voluntarios$DATA >= intervalo_inferior & voluntarios$DATA <= intervalo_superior,]
paste("Hora:", operacao$hora,"Waze:", operacao$speedKMH,"Controlador:" , mean(control$VELOCIDADE), sep = " ")
## [1] "Hora: 16:40: Waze: 10.64 Controlador: 25.0681818181818"
#mean(control$VELOCIDADE)
#operacao$speedKMH
df = waze = data.frame(matrix(, nrow = 0, ncol = 2))
for (variable in 1:length(dftab$country)) {
#print(variable)
operacao = dftab[variable, ]
library(lubridate)
intervalo_inferior = operacao$pubMillis - minutes(min)
intervalo_superior = operacao$pubMillis + minutes(max)
control = voluntarios[voluntarios$DATA >= intervalo_inferior & voluntarios$DATA <= intervalo_superior,]
print(paste("Hora:", operacao$hora, "Waze:", operacao$speedKMH,"Controlador:" , mean(control$VELOCIDADE), sep = " "))
res = c(operacao$speedKMH, mean(control$VELOCIDADE))
df = rbind(df, res)
}
## [1] "Hora: 16:40: Waze: 10.64 Controlador: 25.0681818181818"
## [1] "Hora: 14:48: Waze: 13.73 Controlador: 24.6734693877551"
## [1] "Hora: 14:58: Waze: 15.58 Controlador: 23.032967032967"
## [1] "Hora: 17:50: Waze: 14.05 Controlador: 22.5633802816901"
## [1] "Hora: 17:40: Waze: 8.84 Controlador: 26.25"
names(df) = c("waze", "control")
scatter.smooth(x=df$waze, y=df$control, main="Vel ~ Waze")
#
#par(mfrow=c(1, 2))
#boxplot(df$waze, main="Waze", sub=paste("Média: ", mean(df$waze)), col=c("gold"))
#points(mean(df$waze),col="red",pch=4,lwd = 4)
#lines(c(0.8, 1.2), rep(mean(df$waze), 2), col="red", lwd = 2)
#legend("bottomright", legend=c("Média", "Mediana"),
# col=c("red", "black"), lty=1, cex=0.8, bty = "n")
#boxplot(df$control, main="Control", sub=paste("Média: ", mean(df$control)), col=c("darkgreen"))
#points(mean(df$control),col="red",pch=4,lwd = 4)
#lines(c(0.8, 1.2), rep(mean(df$control), 2), col="red", lwd = 2)
#legend("bottomright", legend=c("Média", "Mediana"),
# col=c("red", "black"), lty=1, cex=0.8, bty = "n")
df2 = as.data.frame(cbind(df$waze, "Waze"))
df1 = as.data.frame(cbind(df$control, "Controlador"))
df3 = df
df= rbind(df1, df2)
df$V1 = as.numeric(as.character(df$V1))
class(df$V1)
## [1] "numeric"
par(mfrow=c(1, 1))
boxplot(df$V1~df$V2,
col=c("#0195A6", "#FF682D") ,
ylab="Velocidade média" , xlab="Amostra", main=paste("Média Waze:", round(mean(df3$waze),2), "Média Controlador:", round(mean(df3$control),2), sep = " "))
df3
## [1] "Waze: 9.94 Controlador: 15.8829787234043"
## [1] "Hora: 08:50: Waze: 9.94 Controlador: 15.8829787234043"
## [1] "Hora: 07:38: Waze: 10.76 Controlador: 22.4044943820225"
## [1] "Hora: 08:48: Waze: 17.19 Controlador: 18.9322033898305"
## [1] "Hora: 09:42: Waze: 10.28 Controlador: 13.8735632183908"
## [1] "Hora: 09:59: Waze: 15.98 Controlador: 21.7428571428571"
## [1] "Hora: 08:57: Waze: 11.97 Controlador: 24.125"
## [1] "numeric"
## [1] "Waze: 10.35 Controlador: 26.7285714285714"
## [1] "Hora: 13:49: Waze: 10.35 Controlador: 26.7285714285714"
## [1] "Hora: 15:35: Waze: 10.62 Controlador: 28.2613065326633"
## [1] "Hora: 13:51: Waze: 9.75 Controlador: 25.8301886792453"
## [1] "Hora: 09:23: Waze: 11.72 Controlador: 17.16"
## [1] "Hora: 13:53: Waze: 8.28 Controlador: 24.4615384615385"
## [1] "Hora: 13:54: Waze: 8.29 Controlador: 26.9143968871595"
## [1] "numeric"
## [1] "Waze: 9.1 Controlador: 28.5808823529412"
## [1] "Hora: 17:20: Waze: 9.1 Controlador: 28.5808823529412"
## [1] "Hora: 18:54: Waze: 19.91 Controlador: 29.9308357348703"
## [1] "Hora: 18:57: Waze: 19.67 Controlador: 29.3072463768116"
## [1] "Hora: 17:47: Waze: 22.85 Controlador: 28.9139784946237"
## [1] "Hora: 17:38: Waze: 16.21 Controlador: 28.9774011299435"
## [1] "Hora: 17:54: Waze: 18.78 Controlador: 30.0724637681159"
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## pseudoinverse used at 22.919
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## neighborhood radius 4.1388
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## reciprocal condition number 0
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## There are other near singularities as well. 6.6049
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## pseudoinverse used at 22.919
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## neighborhood radius 4.1388
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## reciprocal condition number 0
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## There are other near singularities as well. 6.6049
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## pseudoinverse used at 22.919
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## neighborhood radius 4.1388
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## reciprocal condition number 0
## Warning in simpleLoess(y, x, w, span, degree = degree, parametric = FALSE, :
## There are other near singularities as well. 6.6049
## [1] "numeric"
## [1] "Waze: 10.04 Controlador: 28.5745257452575"
## [1] "Hora: 07:07: Waze: 10.04 Controlador: 28.5745257452575"
## [1] "Hora: 07:45: Waze: 16.86 Controlador: 30.5714285714286"
## [1] "Hora: 07:48: Waze: 21.46 Controlador: 12.9848484848485"
## [1] "Hora: 07:25: Waze: 13.72 Controlador: 30.7651715039578"
## [1] "Hora: 07:27: Waze: 10.5 Controlador: 25.1682242990654"
## [1] "Hora: 07:52: Waze: 15.86 Controlador: 27.7594202898551"
## [1] "numeric"