Como explorar os dados do MOBLAB

Versão de dezembro de 2022

Introdução

Objetivos.

Formato dos dados

Os dados coletados dos sistemas da Prefeitura do Rio de Janeiro1 são filtrados para remoção de campos corrompidos ou duplicatas e os seguintes campos são utilizados como entrada de um pipeline de reconstrução:

erDiagram DATUM { datetime GPSTIMESTAMP "GMT-0 Date" string BUSID "Número de ordem do veículo" string LINE "Linha do serviço" double LATITUDE "Latitude" double LONGITUDE "Longitude" double VELOCITY "Velocidade instantânea medida pelo GPS" }

O pipeline de reconstrução é mostrado na figura abaixo e cada etapa gera uma DST (Data Summary Table) que apresenta novos campos que representam o beneficiamento dos dados para análise e estudo da mobilidade urbana da cidade.

graph LR A --> B B --> C C --> D D --> E

As etapas do pipeline mostradas na figura acima adicionam os seguintes beneficiamentos nos dados do laboratório:

  • A - Dado filtrado (erros de aquisição, dado corrompido, etc), beneficiado com a elevação
  • B - Dado com a informação da região administrativa e bairro
  • C - Daco com a região pluviométrica
  • D - Dado com intervalo da amostra, distância percorrida, velocidade média, aceleração, inclinação
  • E - Dado com as emissões segundo o modelo de Richmond.

Manipulação de dados

Cada DST é armazenada no formato Parquet (Apache Parquet) e pode ser manipulado no R, Python e outras linguagens de programação. Além das DTS com o beneficiamento, existem algumas DST que dão suporte a dados relacionados com o beneficiamento. Como exemplos, temos as DTS das regiões administrativas, regiões pluviométricas, bairros, etc. A seguir é mostrado os relacionamentos gerado pelo pipeline de reconstrução.

erDiagram DST-A ||--|| DST-B : x DST-A ||--|| DST-D : x DST-A ||--|| DST-E : x DST-A ||--|| DST-C : x REGADM ||--o{ DST-B : x BAIRRO ||--o{ DST-B : x PLMEREG ||--o{ DST-C :x

Observação: Se uma linha das DSTs não apresentam REGADM, BAIRRO e PLMEREG, então, esse ponto está fora da Cidade do Rio de Janeiro, que pode significar um erro no geoposicionamento, ou que o veículo se encontrava fora do município.

Bibliotecas

Os dados foram estruturados para serem analisados em diversas linguagens de programação, incluindo Java, C++, Python, etc. Nesse manuscrito, mostraremos o uso em Python através das bibliotecas Numpy, Pandas e Geopandas.

Leitura dos dados

Para ler os dados, o usuário deve importar as seguintes bibliotecas:

import numpy as np
import pandas as pd
import geopandas as gd

Como primeiro exemplo, vamos ler os dados de uma DST-A com o código abaixo:

df = pd.read_parquet('G1-2014-04-28.parquet')
df.head()

ID

DATE

BUSID

LINE

LATITUDE

LONGITUDE

VELOCITY

ELEVATION

SWVERSION

0

04-28-2014 10:23:34

B63045

SV920

-22.8358

-43.3181

39.63

26

78a5514

1

04-28-2014 07:15:19

B11654

908.0

-22.8773

-43.3193

35.37

41

78a5514

2

04-28-2014 14:39:36

D86789

2381.0

-22.9046

-43.2103

6.11

12

78a5514

3

04-28-2014 02:37:23

B11613

-22.866

-43.3568

0

20

78a5514

4

04-28-2014 15:20:50

C50151

LECD06

-22.9607

-43.2705

36.11

354

78a5514

Na tabela acima, podemos ver os campos que estão armazenados na DST-A. O ID é a chave primária que identifica a n-tupla em todas as DSTs. No caso de $ID = 0$, temos uma observação feita no dia 28 de abril de 2014, às 10h 23 minutos e 34 segundos. O veículo que enviou a informação foi o com BUSID igual a B63045 e ele estava servindo a linha SV920. A geolocalização desse veículo era latitude igual a -22.8358 e longitude igual a -43.3181. A velocidade medida pelo GPS era de 39.63 km/h e nessa geolocalização a elevação é de 26 metros. A versão do software que gerou essa DST foi a do repositório com versão igual a 78a5514.

No caso da n-tupla com ID igual a 3, o veículo não tinha nenhuma linha de serviço registrada naquele momento.

Visualização

Os dados podem ser visualizados de diversas formas, contudo, temos usado a frameworkd Holoviz sobre o Bokeh em Python para fazer as análises.

Para efeturar os gráficos, precisamos ler a DST como mostrado acima e carregar as seguintes bibliotecas.

import holoviews as hv
import hvplot.pandas
from holoviews import opts
from bokeh.plotting import save

pd.options.plotting.backend = 'holoviews'
hv.extension('bokeh')

Visualização de variáveis (gráficos)

Para gerar histogramas, mostramos no exemplo abaixo como gerar o histograma da velocidade de um determinado veículo na base de dados que se encontra carregada no Data Frame df.

df[df.BUSID == 'B63045'].VELOCITY.hist()

histograma

Existe uma outra possibilidade que podemos juntar diversos histogramas na mesma imagem (ou HTML).

df[df.BUSID == 'B63045'].hvplot.hist(['ELEVATION','VELOCITY'])

histograma

Outra possibilidade é fazer um Box Plot como mostrado abaixo.

df[df.BUSID == 'B63045'].hvplot.box(['ELEVATION'])

box plot

No caso de distribuições multimodais, podemos ver em gráficos violino (violin plots), como mostrado abaixo.

df[df.BUSID == 'B63045'].hvplot.violin(['ELEVATION'])

violin

Se precisamos ver a nuvem de pontos, existe o comando abaixo, onde indicamos as duas variáveis a ser plotadas.

df[df.BUSID == 'B63045'].hvplot.scatter('ELEVATION', 'VELOCITY')

scatter

df[df.BUSID == 'B63045'].hvplot.scatter('DATE', 'ELEVATION')

scatter

df['DATE'] = pd.to_datetime(df['DATE'])
df[df.BUSID == 'B63045'].hvplot.scatter('DATE', 'ELEVATION')

scatter

df[df['BUSID'].isin(['B63045','D86789'])].hvplot.scatter(x='DATE', y='VELOCITY', by='BUSID')

scatter

Mais informações e gráficos,nesse link.

Visualização de dados geoposicionados

  • mostrar pontos com informação
h = df[df.BUSID == 'A37564'].hvplot.points('LONGITUDE', 'LATITUDE', geo=True, 
                     color='white', 
                     size=50, 
                     alpha=0.6,
                     tiles='EsriImagery', 
                     hover_cols=['BUSID','LINE', 'ELEVATION']).opts(width=900, height=600,)
h

points

h = df[df.BUSID == 'A37564'].hvplot.hexbin('LONGITUDE', 'LATITUDE', geo=True, 
                     color='white', 
                     size=50, 
                     alpha=0.6,
                     tiles='EsriImagery').opts(width=900, height=600,)
h

hexbin

Você pode optar por salvar em html da seguinte maneira:

hv.save(h,"hexbin.html", fmt="html")
  • mostrar hexbins

Agregação dos dados

Em construção

Mostrar como juntar semanas, meses, etc.

Conclusão

Apendice I

Nesse apêndice, apresento o dicionário de dados das DSTs.

erDiagram DST-A { index ID "Chave primária" datetime GPSTIMESTAMP "GMT-0 Date" string BUSID "Número de ordem do veículo" string LINE "Linha do serviço" double LATITUDE "Latitude" double LONGITUDE "Longitude" double VELOCITY "Velocidade instantânea medida pelo GPS" double ELEVATION "Elevação da coordenada segundo o sensoriamento SMTR1" string SWVERSION "Versão do GIT COMMIT que gerou a DST" }
erDiagram DST-B { index ID string REGADM "Código da Região administrativa da CRJ" string BAIRRO "Código do Bairro da CRJ" string SWVERSION "Versão do GIT COMMIT que gerou a DST" }
erDiagram DST-C { index ID string PLUVIOMETRICREG "Código da Região pluviométrica da CRJ" string SWVERSION "Versão do GIT COMMIT que gerou a DST" }
erDiagram DST-D { index ID double HDISTANCE "Haversine distance between two samples (km)" double HEIGHT "SRTM1 height between two samples (km)" datetime INTERVAL "Tempo decorrido entre a observação anterior e a atual (h)" double DISTANCE "Distância 3D percorrida entre a observação atual e anterior (km)" double SPEED "Velocidade média entre a observação anterior e a atual (km/h)" string SWVERSION "Versão do GIT COMMIT que gerou a DST" }
erDiagram DST-E { index ID double CO "Quantidade de monóxido de carbono (g/s)" double CO_2 "Quantidade de dióxido de carbono (g/s)" double NO_x "Quantidade de NO_x (g/s)" double HC "Quantidade de HC (mg/s)" string SWVERSION "Versão do GIT COMMIT que gerou a DST" }

  1. Via site do data.rio. ↩︎

Diego Carvalho
Diego Carvalho
Professor of Industrial Engineering

My research interests include AI, distributed systems, and computational intelligence.