A Cyclistic é uma empresa de compartilhamento de bicicletas com sede em Chicago que oferece diferentes tipos de passes: diários, mensais e anuais.Embora os usuários casuais representem uma parte significativa das viagens, os membros anuais são mais rentáveis, pois garantem receita recorrente e maior previsibilidade financeira.
Com o objetivo de aumentar o número de assinaturas anuais, a empresa pretende desenvolver um novo programa de marketing baseado em evidências e direcionado por dados. Para isso, a equipe de análise foi encarregada de investigar o comportamento dos usuários e fornecer recomendações estratégicas fundamentadas.
Três perguntas guiam o projeto:
1. Como membros anuais e usuários casuais utilizam as bicicletas da
Cyclistic de forma diferente?
2. Por que usuários casuais optariam por adquirir uma assinatura
anual?
3. Como a mídia digital pode influenciar os casuais a se tornarem
membros?
Meu trabalho é responder à primeira pergunta, conduzindo uma análise detalhada dos padrões de uso entre os dois grupos. O objetivo é gerar insights que ajudem a compreender o perfil e as motivações de cada tipo de usuário, fornecendo à equipe de marketing informações sólidas para apoiar a criação de campanhas eficazes de conversão e fidelização.
A análise segue as seis etapas do processo de análise de dados apresentados no curso. De forma resumida, as etapas são:
• Compartilhar: os analistas devem resumir seus resultados com visuais claros e atraentes de suas análises usando dados por meio de ferramentas como gráficos ou painéis. • Agir: Os analistas devem pegar tudo o que aprenderam com sua análise de dados e colocá-lo em uso. Isso pode significar fornecer às partes interessadas recomendações com base em suas descobertas para que possam tomar decisões baseadas em dados. *
Os analistas nesta fase inicial devem definir o problema que estão tentando resolver, certificar-se de que entendem completamente as expectativas das partes interessadas, concentrar-se no problema real e evitar distrações, colaborar com as partes interessadas e manter uma linha de comunicação aberta e dar um passo para trás e ver toda a situação no contexto.
O problema a ser resolvido é compreender como os membros anuais e os
usuários casuais utilizam as bicicletas da Cyclistic de forma
diferente.
Esses insights permitirão identificar padrões de comportamento e
orientar decisões de marketing voltadas à conversão de usuários casuais
em assinantes anuais.
A tarefa de negócio vai ser analisar os dados de uso do sistema de bicicletas para revelar diferenças entre os dois tipos de usuários e, a partir disso, apoiar o desenvolvimento de estratégias que aumentem o número de membros anuais.
Considero como principais partes interessadas
(stakeholders):
- Diretora de marketing da Cyclistic, responsável pela estratégia
geral;
- Equipe de análise de dados, encarregada da coleta, limpeza e
interpretação dos dados;
- Equipe de marketing, que aplicará os resultados na formulação de
campanhas direcionadas.
Os analistas devem decidir quais dados precisam coletar para responder às suas perguntas e como organizá-los para que sejam úteis.
Para esta análise, foram utilizados dados históricos de viagens do sistema de bicicletas compartilhadas da Cyclistic, disponibilizados publicamente pela empresa Motivate International Inc. sob licença de uso aberto. Os dados contêm diversas informações sobre as viagens realizadas. Por questões de privacidade, os conjuntos de dados não incluem informações pessoais dos usuários. Dessa forma, não é possível identificar indivíduos nem vincular múltiplas viagens a um mesmo cliente.
Para fins deste estudo, foi utilizado o conjunto de dados dos
trimestres Divvy 2019 Q1 e Divvy 2020
Q1, compatíveis com o ambiente gratuito do RStudio, e adequados
para analisar as diferenças de uso entre os dois tipos de usuários.
Nesta fase iremos: - Fazer o download dos conjuntos de dados históricos
e armazená-los de forma organizada.
- Identificar como os dados estão estruturados e verificar a coerência
entre os períodos analisados.
- Classificar e filtrar os registros conforme critérios de qualidade
definidos.
Os arquivos Divvy 2019 Q1 e Divvy 2020
Q1 foram importados para o RStudio utilizando funções do pacote
readr.
#Instalar fora do R Markdown
#install.packages("tidyverse")
#install.packages("conflicted")
#install.packages("skimr")
library(tidyverse)
library(conflicted)
library("skimr")
# Resolve conflitos
conflict_prefer("filter", "dplyr")
conflict_prefer("lag", "dplyr")
# Evitar notação científica nos eixosd dos gráficos
options(scipen = 999)
# # Imoorta Divvy datasets (csv files)
q1_2019 <- read_csv("Divvy_Trips_2019_Q1.csv")
q1_2020 <- read_csv("Divvy_Trips_2020_Q1.csv")
# Importação no kaggle:
#library(readr)
#q1_2019 <- read_csv("/kaggle/input/<nome-do-dataset>/Divvy_Trips_2019_Q1.csv")
#q1_2020 <- read_csv("/kaggle/input/<nome-do-dataset>/Divvy_Trips_2020_Q1.csv")
Após a importação, foram verificados nomes de colunas, estrutura e tipos de dados.
glimpse(q1_2019)
## Rows: 365,069
## Columns: 12
## $ trip_id <dbl> 21742443, 21742444, 21742445, 21742446, 21742447, 21…
## $ start_time <chr> "2019-01-01 0:04:37", "2019-01-01 0:08:13", "2019-01…
## $ end_time <chr> "2019-01-01 0:11:07", "2019-01-01 0:15:34", "2019-01…
## $ bikeid <dbl> 2167, 4386, 1524, 252, 1170, 2437, 2708, 2796, 6205,…
## $ tripduration <dbl> 390, 441, 829, 1783, 364, 216, 177, 100, 1727, 336, …
## $ from_station_id <dbl> 199, 44, 15, 123, 173, 98, 98, 211, 150, 268, 299, 2…
## $ from_station_name <chr> "Wabash Ave & Grand Ave", "State St & Randolph St", …
## $ to_station_id <dbl> 84, 624, 644, 176, 35, 49, 49, 142, 148, 141, 295, 4…
## $ to_station_name <chr> "Milwaukee Ave & Grand Ave", "Dearborn St & Van Bure…
## $ usertype <chr> "Subscriber", "Subscriber", "Subscriber", "Subscribe…
## $ gender <chr> "Male", "Female", "Female", "Male", "Male", "Female"…
## $ birthyear <dbl> 1989, 1990, 1994, 1993, 1994, 1983, 1984, 1990, 1995…
glimpse(q1_2020)
## Rows: 426,887
## Columns: 13
## $ ride_id <chr> "EACB19130B0CDA4A", "8FED874C809DC021", "789F3C21E4…
## $ rideable_type <chr> "docked_bike", "docked_bike", "docked_bike", "docke…
## $ started_at <chr> "2020-01-21 20:06:59", "2020-01-30 14:22:39", "2020…
## $ ended_at <chr> "2020-01-21 20:14:30", "2020-01-30 14:26:22", "2020…
## $ start_station_name <chr> "Western Ave & Leland Ave", "Clark St & Montrose Av…
## $ start_station_id <dbl> 239, 234, 296, 51, 66, 212, 96, 96, 212, 38, 117, 1…
## $ end_station_name <chr> "Clark St & Leland Ave", "Southport Ave & Irving Pa…
## $ end_station_id <dbl> 326, 318, 117, 24, 212, 96, 212, 212, 96, 100, 632,…
## $ start_lat <dbl> 41.9665, 41.9616, 41.9401, 41.8846, 41.8856, 41.889…
## $ start_lng <dbl> -87.6884, -87.6660, -87.6455, -87.6319, -87.6418, -…
## $ end_lat <dbl> 41.9671, 41.9542, 41.9402, 41.8918, 41.8899, 41.884…
## $ end_lng <dbl> -87.6674, -87.6644, -87.6530, -87.6206, -87.6343, -…
## $ member_casual <chr> "member", "member", "member", "member", "member", "…
Os dois conjuntos de dados apresentam estruturas semelhantes, mas com diferenças nos nomes e tipos de variáveis.
Divvy 2019 Q1 As principais variáveis são:
trip_id, start_time, end_time,
bikeid, tripduration, estações de origem e
destino, além de informações sobre o tipo de usuário
(usertype), gênero e ano de nascimento.
Divvy 2020 Q1 As principais variáveis
são:ride_id, rideable_type,
started_at, ended_at, coordenadas geográficas
(start_lat, start_lng, end_lat,
end_lng) e o tipo de usuário
(member_casual).Este conjunto não possui informações de
gênero nem ano de nascimento, mas inclui latitude e longitude.
Observa-se que existe diferença de nomes e estrutura entre as duas bases, o que exigirá renomeação de colunas e padronização de variáveis na próxima fase.
Nesta etapa, os analistas limpam e transformam os dados para garantir que estejam prontos para análise. O objetivo é corrigir inconsistências, eliminar registros inválidos e criar variáveis derivadas.
Após a inspeção inicial, foi verificado que os conjuntos Divvy 2019 Q1 e Divvy 2020 Q1 apresentavam diferenças em nomes de colunas e estrutura de variáveis. Para viabilizar a análise conjunta, as colunas do conjunto de 2019 foram modificados para seguir o padrão de 2020.
#Paronização de variáveis
(q1_2019 <- rename(q1_2019
,ride_id = trip_id
,rideable_type = bikeid
,started_at = start_time
,ended_at = end_time
,start_station_name = from_station_name
,start_station_id = from_station_id
,end_station_name = to_station_name
,end_station_id = to_station_id
,member_casual = usertype
))
## # A tibble: 365,069 × 12
## ride_id started_at ended_at rideable_type tripduration start_station_id
## <dbl> <chr> <chr> <dbl> <dbl> <dbl>
## 1 21742443 2019-01-01 0:0… 2019-01… 2167 390 199
## 2 21742444 2019-01-01 0:0… 2019-01… 4386 441 44
## 3 21742445 2019-01-01 0:1… 2019-01… 1524 829 15
## 4 21742446 2019-01-01 0:1… 2019-01… 252 1783 123
## 5 21742447 2019-01-01 0:1… 2019-01… 1170 364 173
## 6 21742448 2019-01-01 0:1… 2019-01… 2437 216 98
## 7 21742449 2019-01-01 0:1… 2019-01… 2708 177 98
## 8 21742450 2019-01-01 0:1… 2019-01… 2796 100 211
## 9 21742451 2019-01-01 0:1… 2019-01… 6205 1727 150
## 10 21742452 2019-01-01 0:1… 2019-01… 3939 336 268
## # ℹ 365,059 more rows
## # ℹ 6 more variables: start_station_name <chr>, end_station_id <dbl>,
## # end_station_name <chr>, member_casual <chr>, gender <chr>, birthyear <dbl>
#Converter as variáveis ride_id e rideable_type para o tipo character para que a base q1_2019 possa ser empilhadas corretamente q1_2020
q1_2019 <- mutate(q1_2019, ride_id = as.character(ride_id)
,rideable_type = as.character(rideable_type))
Em seguida, os dois conjuntos foram combinados em um único dataframe
por meio da função bind_rows(). Variáveis que deixaram de
existir a partir de 2020, como birthyear e
gender, foram removidas para manter a consistência. OBS: A
variável tripduration vai ser recalculada, pois não existe em
q1_2020.
# Juntar 2019 e 2020
all_trips <- bind_rows(q1_2019, q1_2020)
# Remover variáveis desnecessárias
all_trips <- all_trips %>%
select(-c(start_lat, start_lng, end_lat, end_lng, birthyear, gender, "tripduration"))
glimpse(all_trips)
## Rows: 791,956
## Columns: 9
## $ ride_id <chr> "21742443", "21742444", "21742445", "21742446", "21…
## $ started_at <chr> "2019-01-01 0:04:37", "2019-01-01 0:08:13", "2019-0…
## $ ended_at <chr> "2019-01-01 0:11:07", "2019-01-01 0:15:34", "2019-0…
## $ rideable_type <chr> "2167", "4386", "1524", "252", "1170", "2437", "270…
## $ start_station_id <dbl> 199, 44, 15, 123, 173, 98, 98, 211, 150, 268, 299, …
## $ start_station_name <chr> "Wabash Ave & Grand Ave", "State St & Randolph St",…
## $ end_station_id <dbl> 84, 624, 644, 176, 35, 49, 49, 142, 148, 141, 295, …
## $ end_station_name <chr> "Milwaukee Ave & Grand Ave", "Dearborn St & Van Bur…
## $ member_casual <chr> "Subscriber", "Subscriber", "Subscriber", "Subscrib…
Após a padronização e combinação dos conjuntos Divvy 2019 Q1 e Divvy 2020 Q1, obteve-se o dataframe consolidado all_trips com 791956 registros e 9 variáveis. Iremos agora providenciar a limpeza desta base.
skim(all_trips) # Crítica de inconsistências da base
| Name | all_trips |
| Number of rows | 791956 |
| Number of columns | 9 |
| _______________________ | |
| Column type frequency: | |
| character | 7 |
| numeric | 2 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| ride_id | 0 | 1 | 8 | 16 | 0 | 791956 | 0 |
| started_at | 0 | 1 | 18 | 19 | 0 | 742287 | 0 |
| ended_at | 0 | 1 | 18 | 19 | 0 | 737899 | 0 |
| rideable_type | 0 | 1 | 1 | 11 | 0 | 4770 | 0 |
| start_station_name | 0 | 1 | 5 | 43 | 0 | 636 | 0 |
| end_station_name | 1 | 1 | 5 | 43 | 0 | 636 | 0 |
| member_casual | 0 | 1 | 6 | 10 | 0 | 4 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| start_station_id | 0 | 1 | 204.40 | 158.92 | 2 | 77 | 174 | 291 | 675 | ▇▅▃▁▁ |
| end_station_id | 1 | 1 | 204.38 | 159.32 | 2 | 77 | 174 | 291 | 675 | ▇▅▃▁▁ |
A função skim() foi utilizada para compreender a
estrutura e a completude dos dados. Foram verificadas oito variáveis,
todas com taxa de preenchimento superior a 99%, o que é muito
positivo.
Nesta crítica foi verificado que a variável
rideable_type é inviável de usar na análise, pois apresenta
um alto número de valores únicos, sendo que o esperado era 3 (tipos de
bicicletas). Além disso, existem alguns problemas que tivemos que
corrigir:
n_unique=4
e que existiam dois nomes para membros (“member” e “Subscriber”) e dois
nomes para usuários casuais (“Customer” e “casual”). Foi necessário
consolidar esses quatro rótulos em apenas dois.# Estuda variável
table(all_trips$member_casual)
##
## casual Customer member Subscriber
## 48480 23163 378407 341906
# Corrige variável
all_trips <- all_trips %>%
mutate(member_casual = recode(member_casual
,"Subscriber" = "member"
,"Customer" = "casual"))
# Ver resultado
table(all_trips$member_casual)
##
## casual member
## 71643 720313
all_trips$date <- as.Date(all_trips$started_at)
all_trips$month <- format(as.Date(all_trips$started_at), "%m")
all_trips$day <- format(as.Date(all_trips$started_at), "%d")
all_trips$year <- format(as.Date(all_trips$started_at), "%Y")
all_trips$day_of_week <- format(as.Date(all_trips$started_at), "%A")
ride_length para manter a consistência entre os
períodos.all_trips$ride_length <- difftime(all_trips$ended_at,all_trips$started_at)
# Converte "ride_length" de Factor para numeric
is.factor(all_trips$ride_length)
## [1] FALSE
all_trips$ride_length <- as.numeric(as.character(all_trips$ride_length))
is.numeric(all_trips$ride_length)
## [1] TRUE
skim(all_trips) # Crítica de inconsistências da base
| Name | all_trips |
| Number of rows | 791956 |
| Number of columns | 15 |
| _______________________ | |
| Column type frequency: | |
| character | 11 |
| Date | 1 |
| numeric | 3 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| ride_id | 0 | 1 | 8 | 16 | 0 | 791956 | 0 |
| started_at | 0 | 1 | 18 | 19 | 0 | 742287 | 0 |
| ended_at | 0 | 1 | 18 | 19 | 0 | 737899 | 0 |
| rideable_type | 0 | 1 | 1 | 11 | 0 | 4770 | 0 |
| start_station_name | 0 | 1 | 5 | 43 | 0 | 636 | 0 |
| end_station_name | 1 | 1 | 5 | 43 | 0 | 636 | 0 |
| member_casual | 0 | 1 | 6 | 6 | 0 | 2 | 0 |
| month | 0 | 1 | 2 | 2 | 0 | 3 | 0 |
| day | 0 | 1 | 2 | 2 | 0 | 31 | 0 |
| year | 0 | 1 | 4 | 4 | 0 | 2 | 0 |
| day_of_week | 0 | 1 | 6 | 13 | 0 | 7 | 0 |
Variable type: Date
| skim_variable | n_missing | complete_rate | min | max | median | n_unique |
|---|---|---|---|---|---|---|
| date | 0 | 1 | 2019-01-01 | 2020-03-31 | 2020-01-07 | 181 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| start_station_id | 0 | 1 | 204.40 | 158.92 | 2 | 77 | 174 | 291 | 675 | ▇▅▃▁▁ |
| end_station_id | 1 | 1 | 204.38 | 159.32 | 2 | 77 | 174 | 291 | 675 | ▇▅▃▁▁ |
| ride_length | 0 | 1 | 1183.91 | 33217.34 | -552 | 328 | 537 | 910 | 10635622 | ▇▁▁▁▁ |
all_trips_v2 <- all_trips %>%
filter(ride_length > 0 & ride_length < 86400)
summary(all_trips_v2)
## ride_id started_at ended_at rideable_type
## Length:791264 Length:791264 Length:791264 Length:791264
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## start_station_id start_station_name end_station_id end_station_name
## Min. : 2.0 Length:791264 Min. : 2.0 Length:791264
## 1st Qu.: 77.0 Class :character 1st Qu.: 77.0 Class :character
## Median :174.0 Mode :character Median :174.0 Mode :character
## Mean :204.3 Mean :204.2
## 3rd Qu.:291.0 3rd Qu.:291.0
## Max. :675.0 Max. :675.0
## member_casual date month day
## Length:791264 Min. :2019-01-01 Length:791264 Length:791264
## Class :character 1st Qu.:2019-02-28 Class :character Class :character
## Mode :character Median :2020-01-07 Mode :character Mode :character
## Mean :2019-08-31
## 3rd Qu.:2020-02-19
## Max. :2020-03-31
## year day_of_week ride_length
## Length:791264 Length:791264 Min. : 1.0
## Class :character Class :character 1st Qu.: 328.0
## Mode :character Mode :character Median : 537.0
## Mean : 819.8
## 3rd Qu.: 909.0
## Max. :86155.0
Com os dados baixados, limpos, classificados e validados, o conjunto está pronto para a fase Analyze. Após a limpeza e de dados, obteve-se o dataframe consolidado all_trips_v2 com 791264 registros e 15 variáveis.
Os analistas devem pensar analiticamente nesta fase sobre seus dados para realizar cálculos, combinar dados de várias fontes e criar tabelas com seus resultados.
Com os dados consolidados e limpos, esta etapa tem como objetivo identificar padrões de comportamento entre os dois grupos de usuários — membros anuais e usuários casuais — a partir das viagens registradas no sistema da Cyclistic. A análise busca responder à pergunta principal do estudo:
Como membros anuais e usuários casuais utilizam as bicicletas da Cyclistic de forma diferente?
Desta forma, as principais tarefas consistem em agregar e formatar os dados, calcular estatísticas descritivas, explorar padrões de uso por dia da semana e tipo de usuário e produzir visualizações comparativas para apoiar a interpretação dos resultados.
#Ver resultado do volume total de viagens em 2019 e 2020
table(all_trips_v2$member_casual,all_trips_v2$year) # TABELA 1
##
## 2019 2020
## casual 23095 48043
## member 341782 378344
Os resultados mostram o volume total de viagens por tipo de usuário em 2019 e 2020. Em 2019, o sistema registrou 364.877 viagens, das quais 341.782 foram realizadas por membros anuais e 23.095 por usuários casuais. Em 2020, o total subiu para 426.387 viagens, com 378.344 de membros e 48.043 de casuais. Isso corresponde a um aumento de cerca de 11% entre membros e de 108% entre casuais, indicando crescimento proporcionalmente maior do uso casual do sistema.
table(all_trips_v2$member_casual, all_trips_v2$month, all_trips_v2$year) # TABELA 2
## , , = 2019
##
##
## 01 02 03
## casual 4591 2627 15877
## member 98601 93522 149659
##
## , , = 2020
##
##
## 01 02 03
## casual 7721 12797 27525
## member 136082 126696 115566
*Os resultados mensais indicam que março concentra o maior uso do sistema, sobretudo entre usuários casuais. Em 2019, as viagens casuais sobem de 4.591 (jan) e 2.627 (fev) para 15.877 em março. Em 2020, o mesmo padrão se repete: 7.721 (jan) e 12.927 (fev) contra 27.525 viagens casuais em março, reforçando que esse mês reúne mais usuários casuais.
GRAFICO 1 - Volume total de viagens por ano e tipo de usuário
# Agregar os dados como na TABELA 1
vol_ano <- all_trips_v2 |>
count(year, member_casual)
ggplot(vol_ano,
aes(x = factor(year),
y = n,
fill = member_casual)) +
geom_col(position = "dodge") +
scale_fill_manual(
name = "Tipo de usuário",
values = c(
"member" = "#009E73", # verde
"casual" = "#CC79A7" # rosa
),
labels = c("member" = "Membro", "casual" = "Casual")
) +
labs(
x = "Ano",
y = "Número de viagens",
title = "Volume total de viagens por ano e tipo de usuário"
) +
theme_minimal()
GRAFICO 2 - Volume total de viagens por mês, ano e tipo de usuário
# Agregar como na TABELA 2: ano, mês e tipo de usuário
vol_mes_ano <- all_trips_v2 |>
count(year, month, member_casual) |>
mutate(
month = factor(month, levels = sprintf("%02d", 1:3)),
month_num = as.integer(month)
)
ggplot(
vol_mes_ano,
aes(
x = month_num, # meses 1–3
y = n,
color = member_casual,
group = member_casual
)
) +
geom_line(linewidth = 1) +
geom_point() +
facet_wrap(~ year) +
scale_color_manual(
name = "Tipo de usuário",
values = c(
"member" = "#009E73", # verde
"casual" = "#CC79A7" # rosa
),
labels = c("member" = "Membro", "casual" = "Casual")
) +
scale_x_continuous(
breaks = 1:3,
labels = c("Jan","Fev","Mar")
) +
labs(
x = "Mês",
y = "Número de viagens",
title = "Volume de viagens por mês, ano e tipo de usuário"
) +
theme_minimal()
# Ver resultado de dias da semana no trimestre
table(all_trips_v2$day_of_week, all_trips_v2$month, all_trips_v2$year) #TABELA 3
## , , = 2019
##
##
## 01 02 03
## domingo 6893 6384 14700
## quarta-feira 18143 17346 24903
## quinta-feira 20092 19257 27523
## sábado 8914 7397 18946
## segunda-feira 12480 15763 22140
## sexta-feira 19255 13667 30096
## terça-feira 17415 16335 27228
##
## , , = 2020
##
##
## 01 02 03
## domingo 8229 17903 24647
## quarta-feira 26479 20110 23226
## quinta-feira 28952 16881 20222
## sábado 6948 17358 13234
## segunda-feira 22467 23929 20305
## sexta-feira 24507 19080 16993
## terça-feira 26221 24232 24464
Nos dois anos, as viagens se concentram em dias úteis, com valores mais altos de terça a sexta. Domingos e sábados mantêm volumes menores na maior parte dos meses.
table(all_trips_v2$member_casual,all_trips_v2$day_of_week, all_trips_v2$month, all_trips_v2$year) #TABELA 4
## , , = 01, = 2019
##
##
## domingo quarta-feira quinta-feira sábado segunda-feira sexta-feira
## casual 573 352 466 1533 238 935
## member 6320 17791 19626 7381 12242 18320
##
## terça-feira
## casual 494
## member 16921
##
## , , = 02, = 2019
##
##
## domingo quarta-feira quinta-feira sábado segunda-feira sexta-feira
## casual 437 295 441 493 316 385
## member 5947 17051 18816 6904 15447 13282
##
## terça-feira
## casual 260
## member 16075
##
## , , = 03, = 2019
##
##
## domingo quarta-feira quinta-feira sábado segunda-feira sexta-feira
## casual 2748 1835 2003 3945 1333 2043
## member 11952 23068 25520 15001 20807 28053
##
## terça-feira
## casual 1970
## member 25258
##
## , , = 01, = 2020
##
##
## domingo quarta-feira quinta-feira sábado segunda-feira sexta-feira
## casual 911 1279 1559 714 857 1330
## member 7318 25200 27393 6234 21610 23177
##
## terça-feira
## casual 1071
## member 25150
##
## , , = 02, = 2020
##
##
## domingo quarta-feira quinta-feira sábado segunda-feira sexta-feira
## casual 4720 953 659 3231 1063 1239
## member 13183 19157 16222 14127 22866 17841
##
## terça-feira
## casual 932
## member 23300
##
## , , = 03, = 2020
##
##
## domingo quarta-feira quinta-feira sábado segunda-feira sexta-feira
## casual 9189 3614 2601 3500 2865 2534
## member 15458 19612 17621 9734 17440 14459
##
## terça-feira
## casual 3222
## member 21242
Em 2019, observa-se que os membros realizaram a maior parte das viagens durante a semana, enquanto os casuais concentraram o uso nos finais de semana. Essa diferença reforça o padrão funcional dos membros, que utilizam o sistema durante a rotina semanal, em contraste com o comportamento recreativo dos casuais.
Em 2020, há um crescimento no volume total de viagens para ambos os grupos, mas o aumento é mais expressivo entre os usuários casuais, especialmente aos domingos e sábados, o que indica uma ampliação do uso voltado ao lazer. Entre os membros, o padrão de maior uso nos dias úteis se mantém, sugerindo continuidade do uso associado a deslocamentos regulares.
De forma geral, os dados mostram dois perfis distintos de utilização:
a) Membros: uso frequente e distribuído ao longo da semana, com picos em dias úteis. b) Casuais: uso concentrado nos finais de semana.
GRAFICO 3 - Uso por dia da semana, por tipo de usuário e ano
# Agregar como na tabela 4
uso_dia_semana_ano <- all_trips_v2 |>
count(year, day_of_week, member_casual) |>
mutate(
# ordenar e abreviar dias
day_of_week = factor(
day_of_week,
levels = c("segunda-feira", "terça-feira", "quarta-feira",
"quinta-feira", "sexta-feira", "sábado", "domingo"),
labels = c("Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom")
),
# ordenar facetas: casual à esquerda, member à direita
member_casual = factor(member_casual,
levels = c("casual", "member"))
)
ggplot(
uso_dia_semana_ano,
aes(x = day_of_week, y = n, fill = member_casual)
) +
geom_col() +
facet_grid(year ~ member_casual) + # linhas = anos, colunas = tipo
scale_fill_manual(
name = "Tipo de usuário",
values = c(
"member" = "#009E73", # verde
"casual" = "#CC79A7" # rosa
),
labels = c("member" = "Membro", "casual" = "Casual")
) +
labs(
x = "Dia da semana",
y = "Número de viagens",
title = "Uso por dia da semana, por tipo de usuário e ano"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1)
)
# Ver resultado de viagens diárias no trimestre
table(all_trips_v2$day, all_trips_v2$month, all_trips_v2$year) #TABELA 5
## , , = 2019
##
##
## 01 02 03
## 01 1309 1786 4988
## 02 4169 1902 2440
## 03 5616 2580 1645
## 04 6790 5591 2720
## 05 6174 5245 3555
## 06 3676 5483 4394
## 07 4730 3954 4753
## 08 6949 2881 4989
## 09 5095 1945 2084
## 10 5244 1416 2263
## 11 5750 4070 6234
## 12 1390 2368 7813
## 13 1757 3681 6351
## 14 5073 5709 6884
## 15 5246 3748 5507
## 16 5722 2237 4236
## 17 5678 1002 4542
## 18 4991 2226 7019
## 19 528 4539 8541
## 20 754 3392 4970
## 21 1644 5030 6555
## 22 2882 5252 6968
## 23 2994 1313 6663
## 24 3205 1386 3247
## 25 1724 3876 6167
## 26 822 4183 7319
## 27 706 4790 9188
## 28 1033 4564 9331
## 29 1029 0 7644
## 30 163 0 3523
## 31 349 0 3003
##
## , , = 2020
##
##
## 01 02 03
## 01 2138 3201 7402
## 02 6473 5411 8319
## 03 5889 7278 8215
## 04 3184 6161 8388
## 05 3030 5370 8260
## 06 7071 3244 6132
## 07 7294 5245 6697
## 08 5448 3237 11159
## 09 6799 1815 4489
## 10 5689 6323 7812
## 11 964 6469 7627
## 12 1766 4912 8327
## 13 6155 3033 7060
## 14 7065 2991 2974
## 15 6930 1839 3311
## 16 5494 2926 3596
## 17 3854 3605 4389
## 18 1074 6617 2059
## 19 893 5728 1974
## 20 2928 4902 2317
## 21 5187 5506 2124
## 22 5509 5446 1317
## 23 3610 7751 1964
## 24 3651 6723 2429
## 25 1726 4985 5152
## 26 2540 4100 1661
## 27 6313 5702 1484
## 28 6675 5338 1439
## 29 6454 3635 1458
## 30 6576 0 1937
## 31 5424 0 1619
Em 2019, o número diário de viagens ficou entre 163 e 9.331, com expansão do máximo de janeiro (6.949 viagens) para março (9.331). Em 2020, o intervalo diário passou a 893–11.159 viagens, com pico em 8 de março de 2020 (11.159 viagens). A amplitude diária subiu de 9.168 viagens em 2019 para 10.266 em 2020, com aumento tanto do mínimo (de 163 para 893) quanto do máximo (de 9.331 para 11.159).
GRAFICO 4 - Viagens diárias por mês, comparando 2019 e 2020
# Agregar como TABELA 5
vol_dia <- all_trips_v2 |>
count(year, month, day) |>
mutate(
day = as.integer(day),
month = factor(
month,
levels = sprintf("%02d", 1:12),
labels = c("Jan","Fev","Mar","Abr","Mai","Jun",
"Jul","Ago","Set","Out","Nov","Dez")
),
year = factor(year) # para usar como label/legenda
)
ggplot(
vol_dia,
aes(x = day, y = n,
color = year, group = year)
) +
geom_line(linewidth = 0.9) +
geom_point(size = 1) +
facet_wrap(~ month) + # gráfico por mês; linhas = anos
scale_x_continuous(breaks = seq(1, 31, by = 5)) +
scale_color_manual(
name = "Ano",
values = c("2019" = "#08519C", # azul mais escuro
"2020" = "#9ECAE1") # azul mais claro
) +
labs(
x = "Dia do mês",
y = "Número de viagens",
title = "Viagens diárias por mês, comparando 2019 e 2020"
) +
theme_minimal()
# Resumo estatístico geral da duração das viagens(segundos)
summary(all_trips_v2$ride_length)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.0 328.0 537.0 819.8 909.0 86155.0
Verifica-se que a maioria das viagens é curta (entre 5 e 15 minutos), mas há algumas viagens longas que elevam a média acima da mediana. Isso confirma o comportamento típico do sistema Cyclistic: uso concentrado em trajetos curtos, coerente com um serviço de deslocamento urbano. As viagens têm duração mínima de 1 segundo e máxima de aproximadamente 86 mil segundos (cerca de 24 horas), o que representa o limite superior estabelecido na limpeza dos dados para eliminar registros atípicos. O primeiro quartil, de 328 segundos, indica que 25% das viagens duram menos de 5 minutos e meio. A mediana, de 537 segundos (aproximadamente 9 minutos), mostra que metade das viagens é inferior a esse valor, enquanto o terceiro quartil, de 909 segundos (cerca de 15 minutos), indica que 75% das viagens não ultrapassam esse tempo.
# Comparação da duração de viagens entre membros e usuários casuais
aggregate(all_trips_v2$ride_length ~ all_trips_v2$member_casual, FUN = mean)
## all_trips_v2$member_casual all_trips_v2$ride_length
## 1 casual 2187.843
## 2 member 684.621
aggregate(all_trips_v2$ride_length ~ all_trips_v2$member_casual, FUN = median)
## all_trips_v2$member_casual all_trips_v2$ride_length
## 1 casual 1318
## 2 member 508
aggregate(all_trips_v2$ride_length ~ all_trips_v2$member_casual, FUN = max)
## all_trips_v2$member_casual all_trips_v2$ride_length
## 1 casual 86155
## 2 member 85984
aggregate(all_trips_v2$ride_length ~ all_trips_v2$member_casual, FUN = min)
## all_trips_v2$member_casual all_trips_v2$ride_length
## 1 casual 1
## 2 member 1
Os resultados mostram diferenças claras entre os dois grupos de usuários. A média de duração das viagens dos casuais é de aproximadamente 2.188 segundos (cerca de 36 minutos), enquanto entre os membros é de 685 segundos (pouco mais de 11 minutos). A mediana confirma essa diferença: 1.318 segundos (22 minutos) para casuais e 508 segundos (8 minutos) para membros. Esses valores indicam que os usuários casuais costumam realizar viagens mais longas, provavelmente com fins de lazer ou turismo, enquanto os membros anuais utilizam o sistema em trajetos mais curtos e rotineiros, possivelmente como meio de transporte diário.
GRAFICO 5 - Duração média das viagens por tipo de usuário
library(ggplot2)
# Recomendo usar a forma com 'data ='
media_duracao <- aggregate(
ride_length ~ member_casual,
data = all_trips_v2,
FUN = mean
)
# Opcional: converter para minutos
media_duracao$ride_length_min <- media_duracao$ride_length / 60
ggplot(media_duracao,
aes(x = member_casual,
y = ride_length_min,
fill = member_casual)) +
geom_col(width = 0.6) +
scale_fill_manual(
name = "Tipo de usuário",
values = c(
"member" = "#009E73", # verde
"casual" = "#CC79A7" # rosa
),
labels = c("member" = "Membro", "casual" = "Casual")
) +
labs(
x = "Tipo de usuário",
y = "Duração média da viagem (minutos)",
title = "Duração média das viagens por tipo de usuário"
) +
theme_minimal()
# Duração média das viagens por dia da semana e tipo de usuário
aggregate(all_trips_v2$ride_length ~ all_trips_v2$member_casual + all_trips_v2$month, FUN = mean)
## all_trips_v2$member_casual all_trips_v2$month all_trips_v2$ride_length
## 1 casual 01 2169.9170
## 2 member 01 663.6025
## 3 casual 02 2170.9924
## 4 member 02 665.2609
## 5 casual 03 2198.9159
## 6 member 03 719.2938
Os usuários casuais apresentam tempos médios de viagem mais altos em todos os meses do trimestre, em torno de 2.170 a 2.200 segundos (cerca de 36 a 37 minutos). Já os membros anuais mantêm médias bem menores e relativamente estáveis, entre aproximadamente 660 e 720 segundos (cerca de 11 a 12 minutos). Isso indica que, ao longo de janeiro, fevereiro e março, as viagens de casuais tendem a ser mais longas, enquanto as de membros são mais curtas e regulares.
# Duração média das viagens por dia da semana e tipo de usuário
aggregate(all_trips_v2$ride_length ~ all_trips_v2$member_casual + all_trips_v2$day, FUN = mean)
## all_trips_v2$member_casual all_trips_v2$day all_trips_v2$ride_length
## 1 casual 01 2547.2730
## 2 member 01 760.7731
## 3 casual 02 1863.3818
## 4 member 02 716.6235
## 5 casual 03 1734.9062
## 6 member 03 673.6097
## 7 casual 04 1792.0467
## 8 member 04 675.7466
## 9 casual 05 2032.7924
## 10 member 05 691.1908
## 11 casual 06 1682.5803
## 12 member 06 663.3267
## 13 casual 07 2217.7469
## 14 member 07 679.9292
## 15 casual 08 2560.8044
## 16 member 08 706.4749
## 17 casual 09 1615.6022
## 18 member 09 643.9929
## 19 casual 10 1682.8738
## 20 member 10 644.9335
## 21 casual 11 2108.0689
## 22 member 11 645.0546
## 23 casual 12 2315.6492
## 24 member 12 691.4301
## 25 casual 13 2074.2205
## 26 member 13 691.1965
## 27 casual 14 2040.3487
## 28 member 14 667.0547
## 29 casual 15 2255.0835
## 30 member 15 652.0888
## 31 casual 16 1831.7271
## 32 member 16 674.6512
## 33 casual 17 2241.7416
## 34 member 17 701.0181
## 35 casual 18 1807.2339
## 36 member 18 654.7650
## 37 casual 19 2208.1187
## 38 member 19 665.7248
## 39 casual 20 2334.8683
## 40 member 20 660.3731
## 41 casual 21 2442.8112
## 42 member 21 676.6021
## 43 casual 22 2293.0718
## 44 member 22 705.9180
## 45 casual 23 2400.6257
## 46 member 23 786.9000
## 47 casual 24 2058.4439
## 48 member 24 699.6471
## 49 casual 25 3035.5495
## 50 member 25 728.1185
## 51 casual 26 1799.7072
## 52 member 26 671.1487
## 53 casual 27 2332.1870
## 54 member 27 678.7301
## 55 casual 28 2241.9681
## 56 member 28 680.0913
## 57 casual 29 2311.8780
## 58 member 29 697.9489
## 59 casual 30 2012.3237
## 60 member 30 710.3362
## 61 casual 31 2117.1040
## 62 member 31 728.3447
A análise diária confirma o padrão consistente de diferença entre os dois grupos de usuários: As viagens realizadas por usuários casuais mantêm duração média muito superior à dos membros anuais em praticamente todos os dias do mês; Não há indícios de picos sazonais ou de eventos pontuais que alterem o comportamento geral dos usuários. Isso indica estabilidade operacional e regularidade de uso — os membros mantêm seu padrão funcional de deslocamento diário, enquanto os casuais utilizam o serviço de forma mais prolongada e esporádica.Esses resultados consolidam o entendimento de que o tipo de assinatura é o principal fator explicativo das diferenças de comportamento entre os usuários, mais relevante que o dia ou o mês de uso.
# analisar os dados de uso por tipo de usuário e dia da semana
all_trips_v2 %>%
mutate(weekday = wday(started_at, label = TRUE)) %>% # cria a variável 'weekday' (dia da semana) a partir da data de início
group_by(member_casual, weekday) %>% # agrupa os dados por tipo de usuário e dia da semana
summarise(
number_of_rides = n(), # calcula o número total de viagens em cada grupo
average_duration = mean(ride_length) # calcula a duração média das viagens
) %>%
arrange(member_casual, weekday) # ordena o resultado por tipo de usuário e dia da semana
## `summarise()` has grouped output by 'member_casual'. You can override using the
## `.groups` argument.
## # A tibble: 14 × 4
## # Groups: member_casual [2]
## member_casual weekday number_of_rides average_duration
## <chr> <ord> <int> <dbl>
## 1 casual dom 18578 2451.
## 2 casual seg 6672 1725.
## 3 casual ter 7949 1957.
## 4 casual qua 8328 2268.
## 5 casual qui 7729 1946.
## 6 casual sex 8466 2097.
## 7 casual sáb 13416 2337.
## 8 member dom 60178 775.
## 9 member seg 110412 666.
## 10 member ter 127946 679.
## 11 member qua 121879 670.
## 12 member qui 125198 664.
## 13 member sex 115132 666.
## 14 member sáb 59381 747.
Usuários casuais fazem menos viagens, mas com duração média maior (cerca de 1.700–2.450 segundos), sobretudo aos fins de semana.Membros concentram o maior número de viagens nos dias úteis, com mais de 100 mil viagens em cada dia de segunda a sexta.Entre membros, a duração média é menor e mais estável (aproximadamente 660–750 segundos), compatível com deslocamentos cotidianos
Considerando que o objetivo desta etapa foi avaliar: como membros anuais e usuários casuais utilizam as bicicletas da Cyclistic de forma diferente?. verificou-se que: a) Os membros anuais realizam viagens curtas e frequentes durante os dias úteis, com pouca variação ao longo da semana. b) Os usuários casuais pedalam menos vezes, porém fazem viagens mais longas, especialmente aos sábados e domingos. c) As estatísticas descritivas mostram um padrão recreativo para casuais e funcional para membros.