import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
Velocidades operacionais em Curitiba-PR
Medindo o V85 nas vias através de dados naturalísticos
Introdução
A velocidade é um fator central na ocorrência de óbitos no trânsito, influenciando diretamente na gravidade de um sinistro considerando a energia de impacto a na chance de ocorrência afetando negativamente o tempo de reação e a visão periférica do condutor.
Uma forma de medir a velocidade praticada em uma via ou trecho de via é a partir do calculo da velocidade de 85º percentil (V85). Com essa medição é possível definir a velocidade operacional de uma via, extraindo o quantil de 85% de uma distribuição de velocidades observadas em um ou mais pontos das vias.
Neste post o objetivo é calcular o V85 para as vias de Curitiba. Os dados de velocidades utilizados aqui foram extraídos da base do Estudo Naturalístico de Direção Brasileiro (NDS-BR)1
Aplicação do cálculo
Primeiro foi necessário carregar as bibliotecas pandas
e geopandas
para lidar com os dados do NDS-BR; matplotlib
e numpy
para plotar os resultados e explorar os dados.
Os dados do NDS-BR estão salvos no formato .parquet
, do Apache Arrow. Aqui foram selecionadas apenas as colunas necessárias para o cálculo: longitude, latitude e velocidade praticada em quilômetros por hora.
= "data/ndsbr_full.parquet"
nds_path = ['long', 'lat', 'spd_kmh']
cols = pd.read_parquet(nds_path, columns=cols)
nds_sample nds_sample.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2382504 entries, 0 to 564053
Data columns (total 3 columns):
# Column Dtype
--- ------ -----
0 long float64
1 lat float64
2 spd_kmh float64
dtypes: float64(3)
memory usage: 72.7 MB
Distribuição da velocidade
Antes de atribuir os dados de velocidade às vias de Curitiba, foi elaborado um histograma para analisar a distribuição dos dados (Figura 1). Observa-se que grande parte da amostra possui velocidade entre 0 e 10 km/h. Isso pode ser reflexo da característica do tráfego urbano, em que os condutores passam boa parte de suas viagens parados ou em velocidade quase zerada.
'font.family'] = 'monospace'
mpl.rcParams[
= plt.subplots()
fig, ax 'spd_kmh'], bins=16, edgecolor='white', color='grey')
ax.hist(nds_sample[set(
ax.=np.arange(0, 170, 10),
xticks='Velocidade (km/h)',
xlabel='Tempo de viagem (s)'
ylabel
)True)
ax.set_axisbelow(=0.5)
plt.grid(alpha plt.show()
As velocidades iguais ou próximas a zero foram removidas da amostra para garantir que e o V85 represente as velocidades de fluxo não-congestionado nas vias. Assim, foram filtradas as velocidades acima de 5 km/h, resultando na distribuição representada na Figura 2.
= nds_sample[nds_sample['spd_kmh'] > 5]
nds_valid_speed = plt.subplots()
fig, ax 'spd_kmh'], bins=16, edgecolor='white', color = 'grey')
ax.hist(nds_valid_speed[set(
ax.=np.arange(0, 170, 10),
xticks='Velocidade (km/h)',
xlabel='Tempo de viagem (s)'
ylabel
)True)
ax.set_axisbelow(=0.5)
plt.grid(alpha plt.show()
Cálculo de velocidade nas vias
Outro conjunto de dados necessários inclui os eixos de vias de Curitiba, disponibilizado pelo Instituto de Pesquisa e Planejamento Urbano de Curitiba. Com auxílio do gpd.read_file()
foi possível importar o arquivo espacial diretamente para o projeto.
= 'https://ippuc.org.br/geodownloads/SHAPES_SIRGAS/EIXO_RUA_SIRGAS.zip'
url_vias = ['CHAVE', 'HIERARQUIA']
vias_cols = gpd.read_file(url_vias, encoding='Latin1', columns=vias_cols) vias
Em seguida os dados do NDS-BR foram transformados para objetos espaciais, utilizando as coordenadas do dataframe como referência. Para associar os dados do NDS-BR aos dados das vias, utilizou-se o método sjoin_nearest()
do geopandas
. Com o método foi possível verificar qual trecho de via (identificado por uma chave única) é o mais próximo ao ponto do NDS-BR, em um limite de até 20 metros.
Os dados de velocidade foram agrupados pela chave da via e com o quantile(0.85)
foi calculada a velocidade de 85º percentil para cada trecho. Por fim, foi realizado um merge()
para unir os dados de V85 ao shape das vias.
= gpd.GeoDataFrame(
nds_points
nds_valid_speed,=gpd.points_from_xy(
geometry'long'],
nds_valid_speed['lat']
nds_valid_speed[
),='epsg:4674'
crs
)
= nds_points.to_crs('31982')
nds_points
= gpd.sjoin_nearest(
nds_nearest
nds_points,
vias,='left',
how=20
max_distance
)
= nds_nearest.groupby('CHAVE')['spd_kmh'].quantile(0.85)
v85_spd = v85_spd.reset_index()
v85_spd = pd.merge(vias, v85_spd, how='left', on='CHAVE')
vias_v85 = vias_v85.dropna(subset=['spd_kmh']) vias_v85
Resultados
A Figura 3 apresenta o V85 para as vias de Curitiba-PR. Devido à abrangência da amostra do NDS-BR, não foi possível calcular esse valor para todas as vias da cidade.
= plt.subplots(figsize=(6,10))
fig, ax =ax, linewidth=0.3, color='grey', alpha=0.5)
vias.plot(ax
vias_v85.plot(=ax,
ax=vias_v85['spd_kmh'] / 75,
linewidth='spd_kmh',
column=True,
legend='inferno_r',
cmap={'shrink': 0.78}
legend_kwds
)True)
ax.set_axisbelow(=0.3)
plt.grid(alpha plt.show()
Conclusão
Com a base de dados do projeto de pesquisa Estudo Naturalístico de Direção Brasileiro (NDS-BR) foi possível identificar o V85 de trechos de vias em Curitiba. Tal análise pode servir de subsídio para identificar locais de risco à mobilidade segura, considerando as consequências negativas de velocidade inseguras.