Preparação e análise exploratória dos dados do Capital Bikeshare para investigar como tempo, rotina urbana e condições ambientais se relacionam com a demanda por bicicletas compartilhadas.
Pergunta-guia: em quais condições a cidade pedala
mais?
Este relatório investiga como fatores de calendário,
clima, horário e perfil de usuário se relacionam com a demanda por
bicicletas compartilhadas em Washington D.C. A proposta é transformar
registros brutos de aluguel em uma leitura analítica sobre mobilidade
urbana.
Sistemas de bicicletas compartilhadas fazem parte da infraestrutura de mobilidade urbana. Eles permitem deslocamentos curtos, reduzem a dependência de automóveis em alguns trajetos e produzem registros detalhados sobre o uso da cidade ao longo do tempo.
O problema central deste projeto é compreender como a demanda por bicicletas varia conforme as condições do dia e da hora. A quantidade de aluguéis pode mudar de acordo com o mês, a estação do ano, o dia da semana, a ocorrência de feriado, o horário, a temperatura, a umidade, o vento e a condição climática. Entender essas variações é importante porque o sistema não funciona da mesma forma em todos os contextos: há dias de maior pressão operacional, períodos de baixa procura e situações em que o clima pode alterar fortemente o comportamento dos usuários.
A análise será construída a partir do Bike Sharing Dataset, que contém registros do sistema Capital Bikeshare, de Washington D.C., nos anos de 2011 e 2012. A base possui dois níveis de agregação: registros diários e registros horários.
A abordagem adotada será dividida em cinco etapas:
day.csv e
hour.csv;A técnica principal será uma análise exploratória de dados. Antes dos gráficos finais, será feito um pré-processamento para tornar a base mais legível e analiticamente útil.
As variáveis de data serão convertidas para o tipo adequado, as variáveis categóricas serão renomeadas com rótulos compreensíveis e as variáveis climáticas normalizadas serão transformadas para escalas mais intuitivas, como temperatura em graus Celsius e umidade em percentual. Também serão criadas variáveis derivadas, como fim de semana, faixa de temperatura, proporção de usuários casuais e proporção de usuários registrados.
A análise exploratória será usada para comparar a demanda por mês, estação, condição climática, tipo de dia, horário e perfil dos usuários. O objetivo não é criar um modelo preditivo final, mas identificar padrões relevantes e produzir uma narrativa coerente sobre o comportamento do sistema.
A análise pode ser útil para gestores de mobilidade urbana, operadores de sistemas de bicicletas compartilhadas e equipes responsáveis por planejamento operacional. Ao identificar períodos e condições associados a maior ou menor demanda, torna-se possível apoiar decisões como redistribuição de bicicletas, planejamento de manutenção, reforço de estações em períodos críticos e comunicação com usuários.
Para um operador do sistema, saber que determinados meses, horários, estações ou condições climáticas alteram a demanda ajuda a antecipar problemas. Para gestores públicos, a análise contribui para entender como a bicicleta compartilhada se encaixa na rotina da cidade e em quais contextos ela é mais utilizada.
library(tidyverse)
library(lubridate)
library(janitor)
library(knitr)
library(plotly)
library(DT)
library(scales)
tidyverse: leitura, seleção, transformação, resumo e
visualização dos dados.
lubridate: tratamento da coluna de data.
janitor: padronização dos nomes das variáveis.
knitr: apresentação de tabelas no relatório.
plotly: criação de gráfico interativo.
DT: criação de tabela interativa.
scales: formatação de números, percentuais e eixos dos
gráficos.
Os dados utilizados pertencem ao Bike Sharing Dataset, elaborado por Hadi Fanaee-T e associado ao sistema Capital Bikeshare, de Washington D.C., nos Estados Unidos. A base está disponível publicamente no repositório da UCI Machine Learning Repository.
Fonte dos dados: UCI Machine Learning Repository — Bike Sharing Dataset
A base foi construída para estudar o comportamento de aluguel de bicicletas compartilhadas em relação a fatores temporais, climáticos e sazonais. A documentação do conjunto de dados indica que a demanda por bicicletas pode ser influenciada por condições como temperatura, precipitação, estação do ano, dia da semana e horário do dia.
Por isso, a base é adequada para tarefas como regressão, quando o objetivo é estimar a quantidade de bicicletas alugadas, e também para identificação de eventos ou anomalias, quando determinados dias apresentam comportamento fora do padrão esperado.
Os registros correspondem a dois anos de funcionamento do sistema Capital Bikeshare: 2011 e 2012. Os dados originais de aluguel foram obtidos a partir dos registros históricos do sistema, enquanto as informações meteorológicas foram incorporadas posteriormente a partir de fontes climáticas.
O conjunto de dados foi disponibilizado em dois níveis de agregação:
day.csv: dados agregados por dia, com 731
registros;hour.csv: dados agregados por hora, com 17.379
registros.Essa duplicidade é útil para o projeto porque permite trabalhar com uma visão diária mais sintética e, ao mesmo tempo, explorar padrões de horário que não aparecem na base diária.
Os arquivos day.csv e hour.csv possuem
variáveis muito semelhantes. A principal diferença é que o arquivo
horário contém a variável hr, que representa a hora do dia,
enquanto o arquivo diário não possui essa coluna.
As variáveis podem ser agrupadas em quatro blocos:
A variável cnt representa o total de bicicletas alugadas
e corresponde à soma das variáveis casual e
registered.
Algumas variáveis da base original estão codificadas numericamente. Por exemplo, a estação do ano aparece como valores de 1 a 4, o ano aparece como 0 para 2011 e 1 para 2012, e a condição climática também aparece como uma escala numérica. Essas codificações são práticas para armazenamento, mas dificultam a leitura do relatório. Por isso, no pré-processamento, elas serão convertidas para categorias com nomes compreensíveis.
Outra peculiaridade importante é que as variáveis climáticas estão normalizadas. A temperatura, por exemplo, não aparece diretamente em graus Celsius: ela está dividida por um valor máximo. O mesmo ocorre com sensação térmica, umidade e velocidade do vento. Para facilitar a interpretação, essas variáveis serão convertidas para escalas mais próximas da leitura comum.
A documentação da base não informa uma codificação especial para valores ausentes. Por esse motivo, a presença de valores faltantes será verificada diretamente nos arquivos importados, durante o diagnóstico da base bruta.
Antes de importar, o código abaixo verifica se os arquivos estão na mesma pasta do relatório. Isso evita um erro comum no RStudio: tentar ler um arquivo que está em outro diretório.
arquivos_necessarios <- c("day.csv", "hour.csv")
arquivos_ausentes <- arquivos_necessarios[!file.exists(arquivos_necessarios)]
if (length(arquivos_ausentes) > 0) {
stop(
paste(
"Arquivo(s) não encontrado(s):",
paste(arquivos_ausentes, collapse = ", "),
"\nColoque os arquivos CSV na mesma pasta deste relatório Rmd."
)
)
}
day_raw <- read_csv("day.csv")
hour_raw <- read_csv("hour.csv")
dimensoes <- tibble(
arquivo = c("day.csv", "hour.csv"),
unidade_de_observacao = c("Um dia", "Uma hora"),
linhas = c(nrow(day_raw), nrow(hour_raw)),
colunas = c(ncol(day_raw), ncol(hour_raw))
)
kable(dimensoes)
| arquivo | unidade_de_observacao | linhas | colunas |
|---|---|---|---|
| day.csv | Um dia | 731 | 16 |
| hour.csv | Uma hora | 17379 | 17 |
Leitura inicial: a base diária resume a demanda por dia, enquanto a base horária abre a mesma dinâmica em mais detalhe. Essa combinação permite olhar o sistema em duas escalas: a escala do calendário e a escala da rotina diária.
glimpse(day_raw)
## Rows: 731
## Columns: 16
## $ instant <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, …
## $ dteday <date> 2011-01-01, 2011-01-02, 2011-01-03, 2011-01-04, 2011-01-05…
## $ season <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
## $ yr <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
## $ mnth <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
## $ holiday <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,…
## $ weekday <dbl> 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4,…
## $ workingday <dbl> 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1,…
## $ weathersit <dbl> 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 2, 2,…
## $ temp <dbl> 0.3441670, 0.3634780, 0.1963640, 0.2000000, 0.2269570, 0.20…
## $ atemp <dbl> 0.3636250, 0.3537390, 0.1894050, 0.2121220, 0.2292700, 0.23…
## $ hum <dbl> 0.805833, 0.696087, 0.437273, 0.590435, 0.436957, 0.518261,…
## $ windspeed <dbl> 0.1604460, 0.2485390, 0.2483090, 0.1602960, 0.1869000, 0.08…
## $ casual <dbl> 331, 131, 120, 108, 82, 88, 148, 68, 54, 41, 43, 25, 38, 54…
## $ registered <dbl> 654, 670, 1229, 1454, 1518, 1518, 1362, 891, 768, 1280, 122…
## $ cnt <dbl> 985, 801, 1349, 1562, 1600, 1606, 1510, 959, 822, 1321, 126…
A base original contém variáveis de identificação, calendário, clima e demanda. Algumas vêm codificadas por números, o que é útil para armazenamento, mas pouco amigável para interpretação.
dicionario <- tibble(
variavel_original = c(
"instant", "dteday", "season", "yr", "mnth", "hr", "holiday", "weekday",
"workingday", "weathersit", "temp", "atemp", "hum", "windspeed",
"casual", "registered", "cnt"
),
significado = c(
"Índice do registro",
"Data da observação",
"Estação do ano codificada numericamente",
"Ano codificado: 0 para 2011 e 1 para 2012",
"Mês do ano",
"Hora do dia, presente apenas na base horária",
"Indica se o dia é feriado",
"Dia da semana codificado numericamente",
"Indica se o dia é útil",
"Condição climática codificada numericamente",
"Temperatura normalizada",
"Sensação térmica normalizada",
"Umidade normalizada",
"Velocidade do vento normalizada",
"Quantidade de usuários casuais",
"Quantidade de usuários registrados",
"Total de bicicletas alugadas"
)
)
kable(dicionario)
| variavel_original | significado |
|---|---|
| instant | Índice do registro |
| dteday | Data da observação |
| season | Estação do ano codificada numericamente |
| yr | Ano codificado: 0 para 2011 e 1 para 2012 |
| mnth | Mês do ano |
| hr | Hora do dia, presente apenas na base horária |
| holiday | Indica se o dia é feriado |
| weekday | Dia da semana codificado numericamente |
| workingday | Indica se o dia é útil |
| weathersit | Condição climática codificada numericamente |
| temp | Temperatura normalizada |
| atemp | Sensação térmica normalizada |
| hum | Umidade normalizada |
| windspeed | Velocidade do vento normalizada |
| casual | Quantidade de usuários casuais |
| registered | Quantidade de usuários registrados |
| cnt | Total de bicicletas alugadas |
ausentes_day <- day_raw %>%
summarise(across(everything(), ~ sum(is.na(.)))) %>%
pivot_longer(
cols = everything(),
names_to = "variavel",
values_to = "quantidade_ausente"
)
ausentes_hour <- hour_raw %>%
summarise(across(everything(), ~ sum(is.na(.)))) %>%
pivot_longer(
cols = everything(),
names_to = "variavel",
values_to = "quantidade_ausente"
)
kable(ausentes_day)
| variavel | quantidade_ausente |
|---|---|
| instant | 0 |
| dteday | 0 |
| season | 0 |
| yr | 0 |
| mnth | 0 |
| holiday | 0 |
| weekday | 0 |
| workingday | 0 |
| weathersit | 0 |
| temp | 0 |
| atemp | 0 |
| hum | 0 |
| windspeed | 0 |
| casual | 0 |
| registered | 0 |
| cnt | 0 |
kable(ausentes_hour)
| variavel | quantidade_ausente |
|---|---|
| instant | 0 |
| dteday | 0 |
| season | 0 |
| yr | 0 |
| mnth | 0 |
| hr | 0 |
| holiday | 0 |
| weekday | 0 |
| workingday | 0 |
| weathersit | 0 |
| temp | 0 |
| atemp | 0 |
| hum | 0 |
| windspeed | 0 |
| casual | 0 |
| registered | 0 |
| cnt | 0 |
duplicatas <- tibble(
arquivo = c("day.csv", "hour.csv"),
linhas_duplicadas = c(
sum(duplicated(day_raw)),
sum(duplicated(hour_raw))
)
)
kable(duplicatas)
| arquivo | linhas_duplicadas |
|---|---|
| day.csv | 0 |
| hour.csv | 0 |
Decisão de limpeza:
Mesmo quando uma base
parece organizada, esta etapa é necessária. Valores ausentes, duplicatas
ou codificações pouco claras podem distorcer médias, gráficos e
interpretações. Aqui, o principal trabalho não é “consertar erro grave”,
mas transformar uma base técnica em uma base analítica.
A preparação da base diária segue cinco decisões principais:
day_clean <- day_raw %>%
clean_names() %>%
mutate(
data = ymd(dteday),
ano = if_else(yr == 0, 2011, 2012),
numero_mes = mnth,
mes = factor(
mnth,
levels = 1:12,
labels = c(
"Jan", "Fev", "Mar", "Abr", "Mai", "Jun",
"Jul", "Ago", "Set", "Out", "Nov", "Dez"
)
),
estacao = factor(
season,
levels = c(1, 2, 3, 4),
labels = c("Primavera", "Verão", "Outono", "Inverno")
),
dia_semana = factor(
weekday,
levels = 0:6,
labels = c(
"Domingo", "Segunda", "Terça", "Quarta",
"Quinta", "Sexta", "Sábado"
)
),
fim_de_semana = factor(
if_else(dia_semana %in% c("Sábado", "Domingo"), "Sim", "Não"),
levels = c("Não", "Sim")
),
feriado = factor(
holiday,
levels = c(0, 1),
labels = c("Não", "Sim")
),
dia_util = factor(
workingday,
levels = c(0, 1),
labels = c("Não", "Sim")
),
clima = factor(
weathersit,
levels = c(1, 2, 3, 4),
labels = c(
"Claro ou parcialmente nublado",
"Neblina ou nublado",
"Chuva ou neve leve",
"Chuva forte ou neve intensa"
)
),
temperatura_celsius = temp * 41,
sensacao_termica_celsius = atemp * 50,
umidade_percentual = hum * 100,
velocidade_vento = windspeed * 67,
percentual_casuais = casual / cnt * 100,
percentual_registrados = registered / cnt * 100,
faixa_temperatura = case_when(
temperatura_celsius < 10 ~ "Frio",
temperatura_celsius < 20 ~ "Ameno",
temperatura_celsius < 30 ~ "Quente",
TRUE ~ "Muito quente"
),
faixa_temperatura = factor(
faixa_temperatura,
levels = c("Frio", "Ameno", "Quente", "Muito quente")
),
classe_demanda = ntile(cnt, 4),
classe_demanda = factor(
classe_demanda,
levels = c(1, 2, 3, 4),
labels = c("Baixa", "Média-baixa", "Média-alta", "Alta")
)
) %>%
select(
data,
ano,
numero_mes,
mes,
dia_semana,
fim_de_semana,
feriado,
dia_util,
estacao,
clima,
faixa_temperatura,
temperatura_celsius,
sensacao_termica_celsius,
umidade_percentual,
velocidade_vento,
casual,
registered,
cnt,
percentual_casuais,
percentual_registrados,
classe_demanda
)
A base horária é preparada para permitir a análise dos padrões de uso ao longo do dia. Além das transformações de data e ano, são criadas variáveis para identificar período do dia, dia útil, fim de semana e condição climática.
hour_clean <- hour_raw %>%
clean_names() %>%
mutate(
data = ymd(dteday),
ano = if_else(yr == 0, 2011, 2012),
numero_mes = mnth,
mes = factor(
mnth,
levels = 1:12,
labels = c(
"Jan", "Fev", "Mar", "Abr", "Mai", "Jun",
"Jul", "Ago", "Set", "Out", "Nov", "Dez"
)
),
hora = hr,
dia_semana = factor(
weekday,
levels = 0:6,
labels = c(
"Domingo", "Segunda", "Terça", "Quarta",
"Quinta", "Sexta", "Sábado"
)
),
fim_de_semana = factor(
if_else(dia_semana %in% c("Sábado", "Domingo"), "Sim", "Não"),
levels = c("Não", "Sim")
),
dia_util = factor(
workingday,
levels = c(0, 1),
labels = c("Não", "Sim")
),
periodo_dia = case_when(
hora >= 5 & hora <= 11 ~ "Manhã",
hora >= 12 & hora <= 17 ~ "Tarde",
hora >= 18 & hora <= 23 ~ "Noite",
TRUE ~ "Madrugada"
),
periodo_dia = factor(
periodo_dia,
levels = c("Madrugada", "Manhã", "Tarde", "Noite")
),
clima = factor(
weathersit,
levels = c(1, 2, 3, 4),
labels = c(
"Claro ou parcialmente nublado",
"Neblina ou nublado",
"Chuva ou neve leve",
"Chuva forte ou neve intensa"
)
),
temperatura_celsius = temp * 41,
umidade_percentual = hum * 100
)
Como existem dois arquivos, é possível fazer uma checagem simples: somar os aluguéis por hora em cada data e comparar com o total diário. Essa etapa funciona como uma “conferência de quilometragem” antes de seguir viagem com a análise.
validacao_agregacao <- hour_clean %>%
group_by(data) %>%
summarise(
cnt_somado_pelas_horas = sum(cnt),
casual_somado_pelas_horas = sum(casual),
registered_somado_pelas_horas = sum(registered),
.groups = "drop"
)
day_prepared <- day_clean %>%
left_join(validacao_agregacao, by = "data") %>%
mutate(
diferenca_total = cnt - cnt_somado_pelas_horas,
diferenca_casual = casual - casual_somado_pelas_horas,
diferenca_registrados = registered - registered_somado_pelas_horas
)
resumo_validacao <- day_prepared %>%
summarise(
dias_comparados = n(),
maior_diferenca_total = max(abs(diferenca_total), na.rm = TRUE),
maior_diferenca_casual = max(abs(diferenca_casual), na.rm = TRUE),
maior_diferenca_registrados = max(abs(diferenca_registrados), na.rm = TRUE)
)
kable(resumo_validacao)
| dias_comparados | maior_diferenca_total | maior_diferenca_casual | maior_diferenca_registrados |
|---|---|---|---|
| 731 | 0 | 0 | 0 |
Resultado da validação: se as diferenças acima forem iguais a zero, a base diária está coerente com a soma da base horária. Isso aumenta a confiança para usar a base diária como principal fonte da análise de calendário, mantendo a base horária para investigar a rotina diária de uso.
Após a limpeza, a base passa a ter datas reais, categorias nomeadas, variáveis climáticas em escala interpretável e variáveis derivadas para apoiar a análise.
day_prepared %>%
select(
data, ano, mes, dia_semana, fim_de_semana, estacao, clima,
temperatura_celsius, casual, registered, cnt, classe_demanda
) %>%
head(12) %>%
kable(digits = 2)
| data | ano | mes | dia_semana | fim_de_semana | estacao | clima | temperatura_celsius | casual | registered | cnt | classe_demanda |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 2011-01-01 | 2011 | Jan | Sábado | Sim | Primavera | Neblina ou nublado | 14.11 | 331 | 654 | 985 | Baixa |
| 2011-01-02 | 2011 | Jan | Domingo | Sim | Primavera | Neblina ou nublado | 14.90 | 131 | 670 | 801 | Baixa |
| 2011-01-03 | 2011 | Jan | Segunda | Não | Primavera | Claro ou parcialmente nublado | 8.05 | 120 | 1229 | 1349 | Baixa |
| 2011-01-04 | 2011 | Jan | Terça | Não | Primavera | Claro ou parcialmente nublado | 8.20 | 108 | 1454 | 1562 | Baixa |
| 2011-01-05 | 2011 | Jan | Quarta | Não | Primavera | Claro ou parcialmente nublado | 9.31 | 82 | 1518 | 1600 | Baixa |
| 2011-01-06 | 2011 | Jan | Quinta | Não | Primavera | Claro ou parcialmente nublado | 8.38 | 88 | 1518 | 1606 | Baixa |
| 2011-01-07 | 2011 | Jan | Sexta | Não | Primavera | Neblina ou nublado | 8.06 | 148 | 1362 | 1510 | Baixa |
| 2011-01-08 | 2011 | Jan | Sábado | Sim | Primavera | Neblina ou nublado | 6.77 | 68 | 891 | 959 | Baixa |
| 2011-01-09 | 2011 | Jan | Domingo | Sim | Primavera | Claro ou parcialmente nublado | 5.67 | 54 | 768 | 822 | Baixa |
| 2011-01-10 | 2011 | Jan | Segunda | Não | Primavera | Claro ou parcialmente nublado | 6.18 | 41 | 1280 | 1321 | Baixa |
| 2011-01-11 | 2011 | Jan | Terça | Não | Primavera | Neblina ou nublado | 6.93 | 43 | 1220 | 1263 | Baixa |
| 2011-01-12 | 2011 | Jan | Quarta | Não | Primavera | Claro ou parcialmente nublado | 7.08 | 25 | 1137 | 1162 | Baixa |
resumo_geral <- day_prepared %>%
summarise(
data_inicial = min(data),
data_final = max(data),
dias_observados = n(),
media_alugueis_dia = mean(cnt),
mediana_alugueis_dia = median(cnt),
menor_demanda = min(cnt),
maior_demanda = max(cnt),
media_temperatura_celsius = mean(temperatura_celsius),
media_umidade_percentual = mean(umidade_percentual),
media_vento = mean(velocidade_vento),
media_percentual_registrados = mean(percentual_registrados),
media_percentual_casuais = mean(percentual_casuais)
)
kable(resumo_geral, digits = 2)
| data_inicial | data_final | dias_observados | media_alugueis_dia | mediana_alugueis_dia | menor_demanda | maior_demanda | media_temperatura_celsius | media_umidade_percentual | media_vento | media_percentual_registrados | media_percentual_casuais |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 2011-01-01 | 2012-12-31 | 731 | 4504.35 | 4548 | 22 | 8714 | 20.31 | 62.79 | 12.76 | 82.44 | 17.56 |
resumo_variaveis <- tibble(
variavel = c(
"cnt", "casual", "registered", "temperatura_celsius",
"umidade_percentual", "velocidade_vento"
),
descricao = c(
"Total diário de bicicletas alugadas",
"Total diário de usuários casuais",
"Total diário de usuários registrados",
"Temperatura convertida para graus Celsius",
"Umidade convertida para percentual",
"Velocidade do vento convertida para escala original aproximada"
),
minimo = c(
min(day_prepared$cnt),
min(day_prepared$casual),
min(day_prepared$registered),
min(day_prepared$temperatura_celsius),
min(day_prepared$umidade_percentual),
min(day_prepared$velocidade_vento)
),
media = c(
mean(day_prepared$cnt),
mean(day_prepared$casual),
mean(day_prepared$registered),
mean(day_prepared$temperatura_celsius),
mean(day_prepared$umidade_percentual),
mean(day_prepared$velocidade_vento)
),
mediana = c(
median(day_prepared$cnt),
median(day_prepared$casual),
median(day_prepared$registered),
median(day_prepared$temperatura_celsius),
median(day_prepared$umidade_percentual),
median(day_prepared$velocidade_vento)
),
maximo = c(
max(day_prepared$cnt),
max(day_prepared$casual),
max(day_prepared$registered),
max(day_prepared$temperatura_celsius),
max(day_prepared$umidade_percentual),
max(day_prepared$velocidade_vento)
)
)
kable(resumo_variaveis, digits = 2)
| variavel | descricao | minimo | media | mediana | maximo |
|---|---|---|---|---|---|
| cnt | Total diário de bicicletas alugadas | 22.00 | 4504.35 | 4548.00 | 8714.00 |
| casual | Total diário de usuários casuais | 2.00 | 848.18 | 713.00 | 3410.00 |
| registered | Total diário de usuários registrados | 20.00 | 3656.17 | 3662.00 | 6946.00 |
| temperatura_celsius | Temperatura convertida para graus Celsius | 2.42 | 20.31 | 20.43 | 35.33 |
| umidade_percentual | Umidade convertida para percentual | 0.00 | 62.79 | 62.67 | 97.25 |
| velocidade_vento | Velocidade do vento convertida para escala original aproximada | 1.50 | 12.76 | 12.13 | 34.00 |
write_csv(day_prepared, "bike_day_preprocessado.csv")
Base analítica: a partir daqui, a análise usa
principalmente a base day_prepared para padrões diários e a
base hour_clean para padrões horários.
A análise exploratória foi organizada para responder à pergunta-guia do projeto: em quais condições a cidade pedala mais?
Para isso, os dados serão observados por seis ângulos:
A primeira leitura busca entender se o uso do sistema permaneceu estável ou se mudou ao longo dos dois anos observados.
resumo_ano <- day_prepared %>%
group_by(ano) %>%
summarise(
dias_observados = n(),
total_alugueis = sum(cnt),
media_alugueis = mean(cnt),
media_casuais = mean(casual),
media_registrados = mean(registered),
.groups = "drop"
) %>%
arrange(ano)
kable(resumo_ano, digits = 2)
| ano | dias_observados | total_alugueis | media_alugueis | media_casuais | media_registrados |
|---|---|---|---|---|---|
| 2011 | 365 | 1243103 | 3405.76 | 677.40 | 2728.36 |
| 2012 | 366 | 2049576 | 5599.93 | 1018.48 | 4581.45 |
day_prepared_temporal <- day_prepared %>%
arrange(data) %>%
mutate(
media_movel_30 = as.numeric(stats::filter(cnt, rep(1 / 30, 30), sides = 2))
)
grafico_temporal <- plot_ly(
data = day_prepared_temporal,
x = ~data,
y = ~cnt,
type = "scatter",
mode = "lines",
line = list(color = "#34495e", width = 1),
text = ~paste(
"Data:", data,
"<br>Total:", cnt,
"<br>Temperatura:", round(temperatura_celsius, 1), "°C",
"<br>Clima:", clima
),
hoverinfo = "text",
name = "Demanda diária"
) %>%
add_trace(
data = day_prepared_temporal,
x = ~data,
y = ~media_movel_30,
type = "scatter",
mode = "lines",
line = list(color = "#2f9e44", width = 3),
name = "Média móvel de 30 dias",
hoverinfo = "skip"
) %>%
layout(
title = list(
text = "Evolução diária da demanda por bicicletas<br><sup>A linha verde mostra a média móvel de 30 dias</sup>"
),
xaxis = list(title = "Data"),
yaxis = list(title = "Total de bicicletas alugadas"),
legend = list(orientation = "h", x = 0, y = -0.2),
margin = list(l = 70, r = 30, t = 80, b = 70)
)
grafico_temporal
Leitura do gráfico: a demanda diária apresenta oscilações fortes, mas a média móvel indica que o sistema não se comporta como uma série totalmente aleatória. O ano com maior média diária foi 2012, com aproximadamente 5.600 aluguéis por dia. Em relação à média diária de 2011, a média de 2012 teve variação aproximada de 64,4%.
Depois de observar a série temporal, o próximo passo é verificar se existe sazonalidade. Em sistemas de bicicleta, isso é esperado porque temperatura, chuva e rotina urbana mudam ao longo do ano.
demanda_mes <- day_prepared %>%
group_by(numero_mes, mes) %>%
summarise(
dias_observados = n(),
media_alugueis = mean(cnt),
mediana_alugueis = median(cnt),
media_temperatura = mean(temperatura_celsius),
.groups = "drop"
) %>%
arrange(numero_mes)
kable(demanda_mes, digits = 2)
| numero_mes | mes | dias_observados | media_alugueis | mediana_alugueis | media_temperatura |
|---|---|---|---|---|---|
| 1 | Jan | 62 | 2176.34 | 1939.0 | 9.69 |
| 2 | Fev | 57 | 2655.30 | 2402.0 | 12.27 |
| 3 | Mar | 62 | 3692.26 | 3216.5 | 16.01 |
| 4 | Abr | 60 | 4484.90 | 4293.5 | 19.27 |
| 5 | Mai | 62 | 5349.77 | 4890.5 | 24.39 |
| 6 | Jun | 60 | 5772.37 | 5308.5 | 28.05 |
| 7 | Jul | 62 | 5563.68 | 5446.5 | 30.97 |
| 8 | Ago | 62 | 5664.42 | 5229.5 | 29.05 |
| 9 | Set | 60 | 5766.52 | 5384.0 | 25.28 |
| 10 | Out | 62 | 5199.23 | 5013.0 | 19.89 |
| 11 | Nov | 60 | 4247.18 | 4081.0 | 15.14 |
| 12 | Dez | 62 | 3403.81 | 3444.0 | 13.29 |
ggplot(demanda_mes, aes(x = mes, y = media_alugueis)) +
geom_col(fill = "#2f9e44") +
geom_text(
aes(label = round(media_alugueis, 0)),
vjust = -0.35,
size = 3
) +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
labs(
title = "Demanda média por mês",
subtitle = "Meses mais quentes tendem a concentrar maior uso do sistema",
x = "Mês",
y = "Média diária de aluguéis"
) +
tema_bike
demanda_estacao <- day_prepared %>%
group_by(estacao) %>%
summarise(
dias_observados = n(),
media_alugueis = mean(cnt),
mediana_alugueis = median(cnt),
media_temperatura = mean(temperatura_celsius),
media_casuais = mean(casual),
media_registrados = mean(registered),
.groups = "drop"
) %>%
arrange(desc(media_alugueis))
kable(demanda_estacao, digits = 2)
| estacao | dias_observados | media_alugueis | mediana_alugueis | media_temperatura | media_casuais | media_registrados |
|---|---|---|---|---|---|---|
| Outono | 188 | 5644.30 | 5353.5 | 28.96 | 1202.61 | 4441.69 |
| Verão | 184 | 4992.33 | 4941.5 | 22.32 | 1106.10 | 3886.23 |
| Inverno | 178 | 4728.16 | 4634.5 | 17.34 | 729.11 | 3999.05 |
| Primavera | 181 | 2604.13 | 2209.0 | 12.21 | 334.93 | 2269.20 |
ggplot(demanda_estacao, aes(x = reorder(estacao, media_alugueis), y = media_alugueis)) +
geom_col(fill = "#34495e") +
coord_flip() +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
labs(
title = "Demanda média por estação do ano",
subtitle = "A estação organiza a leitura sazonal da demanda",
x = "Estação",
y = "Média diária de aluguéis"
) +
tema_bike
Leitura da sazonalidade: o mês com maior média de aluguéis foi Jun, com aproximadamente 5.772 aluguéis por dia. Já o mês com menor média foi Jan. Por estação, a maior média ocorreu em Outono, enquanto a menor ocorreu em Primavera. Isso reforça que o uso da bicicleta compartilhada está associado ao calendário e às condições sazonais.
A base separa usuários em dois grupos: casual e
registered. Essa divisão é importante porque permite
investigar se o sistema é usado do mesmo modo por usuários ocasionais e
por usuários registrados.
perfil_tipo_dia <- day_prepared %>%
group_by(fim_de_semana) %>%
summarise(
dias_observados = n(),
media_total = mean(cnt),
media_casuais = mean(casual),
media_registrados = mean(registered),
percentual_medio_casuais = mean(percentual_casuais),
percentual_medio_registrados = mean(percentual_registrados),
.groups = "drop"
)
kable(perfil_tipo_dia, digits = 2)
| fim_de_semana | dias_observados | media_total | media_casuais | media_registrados | percentual_medio_casuais | percentual_medio_registrados |
|---|---|---|---|---|---|---|
| Não | 521 | 4550.57 | 625.04 | 3925.53 | 12.85 | 87.15 |
| Sim | 210 | 4389.69 | 1401.78 | 2987.91 | 29.24 | 70.76 |
perfil_dia_util <- day_prepared %>%
group_by(dia_util) %>%
summarise(
dias_observados = n(),
media_total = mean(cnt),
media_casuais = mean(casual),
media_registrados = mean(registered),
percentual_medio_casuais = mean(percentual_casuais),
percentual_medio_registrados = mean(percentual_registrados),
.groups = "drop"
)
kable(perfil_dia_util, digits = 2)
| dia_util | dias_observados | media_total | media_casuais | media_registrados | percentual_medio_casuais | percentual_medio_registrados |
|---|---|---|---|---|---|---|
| Não | 231 | 4330.17 | 1371.13 | 2959.03 | 29.05 | 70.95 |
| Sim | 500 | 4584.82 | 606.57 | 3978.25 | 12.25 | 87.75 |
perfil_usuario_tipo <- day_prepared %>%
group_by(fim_de_semana) %>%
summarise(
casual = mean(casual),
registrado = mean(registered),
.groups = "drop"
) %>%
pivot_longer(
cols = c(casual, registrado),
names_to = "tipo_usuario",
values_to = "media_alugueis"
) %>%
mutate(
tipo_usuario = recode(
tipo_usuario,
casual = "Usuários casuais",
registrado = "Usuários registrados"
)
)
ggplot(perfil_usuario_tipo, aes(x = fim_de_semana, y = media_alugueis, fill = tipo_usuario)) +
geom_col(position = "dodge") +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_fill_manual(values = c("#f59f00", "#2f9e44")) +
labs(
title = "Perfil médio de uso em dias de semana e fins de semana",
subtitle = "A separação entre usuários casuais e registrados ajuda a distinguir lazer e rotina",
x = "Fim de semana?",
y = "Média diária de aluguéis",
fill = "Tipo de usuário"
) +
tema_bike
Leitura do perfil dos usuários: os usuários registrados representam a maior parte da demanda média, o que sugere uso recorrente do sistema. Porém, a participação média de usuários casuais muda conforme o tipo de dia: em fins de semana, eles representam cerca de 29,2% da demanda, contra cerca de 12,9% nos demais dias. Isso indica que o sistema combina deslocamentos de rotina com usos mais ocasionais.
A documentação da base indica que o aluguel de bicicletas é associado a fatores ambientais e sazonais. Por isso, temperatura, umidade, vento e situação climática são variáveis importantes para a análise.
ggplot(day_prepared, aes(x = temperatura_celsius, y = cnt)) +
geom_point(alpha = 0.45, color = "#34495e") +
geom_smooth(se = FALSE, color = "#2f9e44", linewidth = 1.1) +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
labs(
title = "Relação entre temperatura e demanda",
subtitle = "A linha suavizada mostra como a demanda se comporta conforme a temperatura aumenta",
x = "Temperatura aproximada em °C",
y = "Total diário de aluguéis"
) +
tema_bike
demanda_faixa_temperatura <- day_prepared %>%
group_by(faixa_temperatura) %>%
summarise(
dias_observados = n(),
media_alugueis = mean(cnt),
mediana_alugueis = median(cnt),
media_casuais = mean(casual),
media_registrados = mean(registered),
.groups = "drop"
) %>%
arrange(desc(media_alugueis))
kable(demanda_faixa_temperatura, digits = 2)
| faixa_temperatura | dias_observados | media_alugueis | mediana_alugueis | media_casuais | media_registrados |
|---|---|---|---|---|---|
| Quente | 300 | 5661.69 | 5353.5 | 1208.93 | 4452.76 |
| Muito quente | 72 | 5409.96 | 5000.0 | 1131.96 | 4278.00 |
| Ameno | 299 | 3692.27 | 3649.0 | 563.39 | 3128.89 |
| Frio | 60 | 1677.77 | 1529.5 | 123.07 | 1554.70 |
demanda_clima <- day_prepared %>%
group_by(clima) %>%
summarise(
dias_observados = n(),
media_alugueis = mean(cnt),
mediana_alugueis = median(cnt),
media_temperatura = mean(temperatura_celsius),
media_umidade = mean(umidade_percentual),
.groups = "drop"
) %>%
arrange(desc(media_alugueis))
kable(demanda_clima, digits = 2)
| clima | dias_observados | media_alugueis | mediana_alugueis | media_temperatura | media_umidade |
|---|---|---|---|---|---|
| Claro ou parcialmente nublado | 463 | 4876.79 | 4844 | 20.97 | 56.56 |
| Neblina ou nublado | 247 | 4035.86 | 4040 | 19.28 | 72.59 |
| Chuva ou neve leve | 21 | 1803.29 | 1817 | 17.77 | 84.89 |
ggplot(day_prepared, aes(x = clima, y = cnt)) +
geom_boxplot(fill = "#8ce99a", color = "#1f2933", outlier.alpha = 0.35) +
coord_flip() +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
labs(
title = "Distribuição da demanda por condição climática",
subtitle = "O boxplot mostra não apenas a média, mas também a variação dos dias",
x = "Condição climática",
y = "Total diário de aluguéis"
) +
tema_bike
Leitura do clima: a faixa de temperatura com maior média de aluguéis foi Quente, com aproximadamente 5.662 aluguéis por dia. Em relação à condição climática, a maior média ocorreu em dias classificados como Claro ou parcialmente nublado, enquanto a menor média ocorreu em Chuva ou neve leve. Isso sugere que o ambiente interfere diretamente no uso do sistema.
A base diária mostra o comportamento geral, mas a base horária permite observar a rotina da cidade. Nesta seção, a pergunta muda de “em quais dias se pedala mais?” para “em quais horas se pedala mais?”.
demanda_hora <- hour_clean %>%
group_by(hora) %>%
summarise(
media_total = mean(cnt),
media_casuais = mean(casual),
media_registrados = mean(registered),
.groups = "drop"
)
kable(demanda_hora, digits = 2)
| hora | media_total | media_casuais | media_registrados |
|---|---|---|---|
| 0 | 53.90 | 10.16 | 43.74 |
| 1 | 33.38 | 6.50 | 26.87 |
| 2 | 22.87 | 4.77 | 18.10 |
| 3 | 11.73 | 2.72 | 9.01 |
| 4 | 6.35 | 1.25 | 5.10 |
| 5 | 19.89 | 1.41 | 18.48 |
| 6 | 76.04 | 4.16 | 71.88 |
| 7 | 212.06 | 11.06 | 201.01 |
| 8 | 359.01 | 21.68 | 337.33 |
| 9 | 219.31 | 30.89 | 188.42 |
| 10 | 173.67 | 46.48 | 127.19 |
| 11 | 208.14 | 59.54 | 148.60 |
| 12 | 253.32 | 68.29 | 185.02 |
| 13 | 253.66 | 72.31 | 181.35 |
| 14 | 240.95 | 75.57 | 165.38 |
| 15 | 251.23 | 74.91 | 176.33 |
| 16 | 311.98 | 73.75 | 238.24 |
| 17 | 461.45 | 74.27 | 387.18 |
| 18 | 425.51 | 61.12 | 364.39 |
| 19 | 311.52 | 48.77 | 262.75 |
| 20 | 226.03 | 36.23 | 189.80 |
| 21 | 172.31 | 28.26 | 144.06 |
| 22 | 131.34 | 22.25 | 109.08 |
| 23 | 87.83 | 15.20 | 72.63 |
ggplot(demanda_hora, aes(x = hora, y = media_total)) +
geom_line(color = "#2f9e44", linewidth = 1.1) +
geom_point(color = "#1f2933", size = 2) +
scale_x_continuous(breaks = 0:23) +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
labs(
title = "Demanda média por hora do dia",
subtitle = "A base horária revela os picos de uso que a base diária não mostra",
x = "Hora do dia",
y = "Média de aluguéis por hora"
) +
tema_bike
demanda_hora_tipo_dia <- hour_clean %>%
group_by(hora, dia_util) %>%
summarise(
media_total = mean(cnt),
media_casuais = mean(casual),
media_registrados = mean(registered),
.groups = "drop"
)
ggplot(demanda_hora_tipo_dia, aes(x = hora, y = media_total, color = dia_util)) +
geom_line(linewidth = 1.1) +
geom_point(size = 1.6) +
scale_x_continuous(breaks = 0:23) +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_color_manual(values = c("#f59f00", "#2f9e44")) +
labs(
title = "Padrão horário em dias úteis e não úteis",
subtitle = "Comparação entre rotina de trabalho e dias sem expediente regular",
x = "Hora do dia",
y = "Média de aluguéis por hora",
color = "Dia útil?"
) +
tema_bike
demanda_hora_usuario <- hour_clean %>%
group_by(hora) %>%
summarise(
`Usuários casuais` = mean(casual),
`Usuários registrados` = mean(registered),
.groups = "drop"
) %>%
pivot_longer(
cols = c(`Usuários casuais`, `Usuários registrados`),
names_to = "tipo_usuario",
values_to = "media_alugueis"
)
ggplot(demanda_hora_usuario, aes(x = hora, y = media_alugueis, color = tipo_usuario)) +
geom_line(linewidth = 1.1) +
scale_x_continuous(breaks = 0:23) +
scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +
scale_color_manual(values = c("#f59f00", "#2f9e44")) +
labs(
title = "Padrão horário por tipo de usuário",
subtitle = "Usuários registrados e casuais não necessariamente usam o sistema nos mesmos horários",
x = "Hora do dia",
y = "Média de aluguéis por hora",
color = "Tipo de usuário"
) +
tema_bike
Leitura do padrão horário: a hora com maior média geral de aluguéis foi 17h. Em dias úteis, o maior pico médio ocorreu às 17h, enquanto em dias não úteis o maior pico médio ocorreu às 13h. Essa diferença é importante porque mostra que a operação do sistema deve considerar tanto o calendário quanto o horário.
Além das médias, também é útil observar os extremos. Os dias de maior e menor demanda podem revelar combinações específicas de calendário, clima e temperatura.
dias_extremos <- bind_rows(
day_prepared %>%
arrange(cnt) %>%
slice_head(n = 10) %>%
mutate(tipo_extremo = "Menor demanda"),
day_prepared %>%
arrange(desc(cnt)) %>%
slice_head(n = 10) %>%
mutate(tipo_extremo = "Maior demanda")
) %>%
select(
tipo_extremo,
data,
ano,
mes,
dia_semana,
fim_de_semana,
feriado,
dia_util,
estacao,
clima,
temperatura_celsius,
umidade_percentual,
casual,
registered,
cnt
)
datatable(
dias_extremos,
rownames = FALSE,
filter = "top",
options = list(
pageLength = 10,
scrollX = TRUE,
language = list(url = "https://cdn.datatables.net/plug-ins/1.10.11/i18n/Portuguese-Brasil.json")
)
)
resumo_extremos <- dias_extremos %>%
group_by(tipo_extremo) %>%
summarise(
media_temperatura = mean(temperatura_celsius),
media_umidade = mean(umidade_percentual),
media_casuais = mean(casual),
media_registrados = mean(registered),
media_total = mean(cnt),
.groups = "drop"
)
kable(resumo_extremos, digits = 2)
| tipo_extremo | media_temperatura | media_umidade | media_casuais | media_registrados | media_total |
|---|---|---|---|---|---|
| Maior demanda | 25.15 | 56.85 | 2365.4 | 5950.9 | 8316.3 |
| Menor demanda | 12.37 | 75.97 | 63.9 | 475.8 | 539.7 |
Leitura dos extremos: a tabela interativa permite filtrar os dias de maior e menor demanda e comparar características como clima, temperatura, fim de semana e perfil dos usuários. Essa leitura é útil porque os extremos ajudam a entender situações operacionais críticas: dias de baixa utilização podem indicar restrições climáticas ou sazonais, enquanto dias de alta utilização exigem maior disponibilidade de bicicletas.
Narrativa consolidada:
Os dados mostram que
a demanda por bicicletas compartilhadas não depende de um único fator.
Ela muda ao longo do ano, varia conforme a temperatura, responde às
condições climáticas e assume padrões diferentes ao longo do dia. Além
disso, usuários registrados e casuais não representam exatamente o mesmo
tipo de uso: os registrados parecem sustentar uma parte recorrente da
demanda, enquanto os casuais ganham importância relativa em contextos
mais associados ao lazer.
O problema abordado neste projeto foi compreender em quais condições a cidade de Washington D.C. mais utiliza o sistema de bicicletas compartilhadas Capital Bikeshare. A pergunta central foi: em quais condições a cidade pedala mais?
Essa pergunta é relevante porque sistemas de bicicletas compartilhadas precisam ser gerenciados de forma dinâmica. A demanda pode mudar por mês, estação, temperatura, tipo de dia, horário e perfil do usuário. Sem esse entendimento, a operação corre o risco de distribuir bicicletas de forma inadequada, planejar manutenção em momentos ruins ou não se preparar para períodos de maior uso.
A análise usou o Bike Sharing Dataset, composto por dois arquivos:
day.csv, com dados agregados por dia, e
hour.csv, com dados agregados por hora. O processo começou
com a importação dos dados, diagnóstico de ausentes e duplicatas,
transformação de códigos numéricos em categorias interpretáveis e
conversão das variáveis climáticas para escalas mais compreensíveis.
Em seguida, a base diária foi validada com a base horária, comparando o total diário com a soma dos registros por hora. Depois disso, a análise exploratória investigou padrões temporais, sazonais, climáticos, horários e diferenças entre usuários casuais e registrados.
Os resultados indicam que a demanda não é uniforme. O uso do sistema varia ao longo do tempo e apresenta diferenças relevantes entre anos, meses e estações. A análise também mostra que temperatura e clima são fatores importantes: dias com condições mais favoráveis tendem a concentrar maior demanda do que dias de clima mais restritivo.
Outro achado importante é a diferença entre usuários casuais e registrados. Usuários registrados sustentam grande parte da demanda média, sugerindo um uso mais recorrente do sistema. Por outro lado, a participação dos usuários casuais tende a mudar conforme o tipo de dia, o que indica um componente de lazer ou uso ocasional.
A base horária acrescenta uma camada importante à análise. Ela mostra que a demanda também depende da hora do dia, e que o padrão de dias úteis pode ser diferente do padrão de dias não úteis. Isso reforça que a operação do sistema deve considerar não apenas “qual dia” terá mais demanda, mas também “em qual horário” essa demanda deve ocorrer.
Para operadores de sistemas de bicicletas compartilhadas, os resultados ajudam a planejar a redistribuição de bicicletas, reforçar a disponibilidade em períodos de pico e organizar manutenção em momentos de menor demanda. Para gestores públicos, a análise oferece evidências sobre como a bicicleta compartilhada se relaciona com a rotina urbana, o calendário e o ambiente.
A análise também pode apoiar decisões de comunicação com usuários. Em períodos de maior demanda, campanhas podem incentivar o uso consciente e informar sobre disponibilidade. Em períodos de menor demanda, ações promocionais ou melhorias de infraestrutura podem ser consideradas para estimular o uso.
A análise é exploratória e não estabelece causalidade. Embora seja possível observar associações entre temperatura, clima, calendário e demanda, não é possível afirmar que um fator isolado causa diretamente o aumento ou a queda dos aluguéis.
Outra limitação é que a base está agregada por dia e por hora. Ela não contém informações sobre origem e destino das viagens, localização das estações, disponibilidade de bicicletas em tempo real ou perfil individual dos usuários. Essas informações poderiam enriquecer a análise operacional.
Além disso, os dados cobrem apenas os anos de 2011 e 2012 em Washington D.C. Assim, os padrões encontrados não devem ser automaticamente generalizados para outras cidades, outros períodos ou sistemas com características diferentes.
Uma continuação natural do projeto seria construir um modelo preditivo para estimar a demanda com base em variáveis climáticas, temporais e sazonais. Também seria possível incorporar dados externos, como eventos locais, feriados específicos, informações de infraestrutura cicloviária ou localização das estações.
Outra melhoria seria realizar uma análise espacial, caso houvesse dados por estação de retirada e devolução. Isso permitiria identificar regiões de maior pressão operacional e melhorar o planejamento da redistribuição das bicicletas.
Fanaee-T, Hadi; Gama, João. Event labeling combining ensemble detectors and background knowledge. Progress in Artificial Intelligence, Springer Berlin Heidelberg, 2013. DOI: 10.1007/s13748-013-0040-3.
Base utilizada: Bike Sharing Dataset — UCI Machine Learning Repository ````