A compra de passagens aéreas pode ser um processo complicado devido à variação dos preços, que é influenciada por diversos fatores, como a antecedência da compra, a companhia aérea, o horário de partida e chegada, o número de paradas e a classe do assento. Esses fatores podem fazer uma grande diferença no custo final do bilhete. Compreender como cada um desses elementos afeta o preço das passagens é fundamental para que os passageiros possam economizar e tomar decisões de compra mais informadas.
Este estudo se propõe a explorar essas variáveis para identificar padrões e fornecer insights que possam beneficiar os consumidores ao planejar suas viagens. Através da análise dos dados de reservas de voos, buscamos revelar como diferentes condições impactam os preços, possibilitando que os passageiros aproveitem as melhores ofertas e façam escolhas mais estratégicas.
Para abordar essa declaração do problema, utilizaremos um conjunto de dados coletado do site “Ease My Trip”, que inclui mais de 300 mil registros de voos entre as principais cidades da Índia. A metodologia será baseada exclusivamente na Análise Exploratória de Dados (EDA). Utilizando EDA, examinaremos os dados para identificar padrões, tendências e relações significativas entre as variáveis que afetam o preço das passagens. A análise se concentrará em visualizações e estatísticas descritivas para entender como diversos fatores influenciam os preços.
A análise proporcionará várias vantagens para os consumidores:
Essa análise ajudará os passageiros a compreender melhor os fatores que impactam o custo das passagens aéreas e a tomar decisões de compra mais inteligentes e vantajosas.
Os seguintes pacotes são necessários:
# Carregar pacotes
library(knitr) # Para geração dinâmica de relatórios em R
library(DT) # Para criar tabelas interativas
library(rmdformats) # Para usar temas de documentos RMarkdown
library(rmarkdown) # Para converter documentos R Markdown em uma variedade de formatos
library(dplyr) # Para manipulação e transformação de dados
library(lares) # Para obter feriados
library(readr) # Para importar facilmente dados delimitados
library(lubridate) # Para facilitar o trabalho com datas
library(ggplot2) # Para criar gráficos estáticos e personalizados
library(plotly) # Para criar gráficos interativos e dinâmicosOs dados foram obtidos do Kaggle através do conjunto de dados Flight Price Prediction. O objetivo original desse conjunto de dados era realizar uma análise detalhada das reservas de voos extraídas do site Ease My Trip. O foco era conduzir testes de hipóteses estatísticas para extrair informações significativas e aplicar o algoritmo de regressão linear para treinar o modelo e prever uma variável-alvo contínua.
“Ease My Trip” é uma plataforma online para reserva de passagens aéreas, utilizada por passageiros em potencial para adquirir bilhetes de voo. A coleta dos dados foi realizada usando a ferramenta de web scraping Octoparse, que permite extrair informações diretamente de sites.
O conjunto de dados contém informações sobre reserva de voos para viagens entre as seis principais cidades metropolitanas da Índia. No total, foram extraídas 300.261 opções distintas de reserva, divididas em dois arquivos: um para bilhetes de classe econômica (economy.csv) e outro para bilhetes de classe executiva (business.csv).
Primeiro adicionamos uma coluna chamada classe, para identificar o tipo de passagem:
Utilizei funções para me ajudar a tratar os dados:
Para transformar o horário de chegada e saída em uma categoria. Recebe o horário e retorna qual turno é:
# Função para determinar o turno do dia a partir do horário
get_turno <- function(horario) {
hora <- as.numeric(substr(horario, 1, 2)) # Extrai a hora do horário
if (hora >= 5 & hora < 12) {
return("manhã")
} else if (hora >= 12 & hora < 18) {
return("tarde")
} else if (hora >= 18 & hora < 24) {
return("noite")
} else {
return("madrugada")
}
}Para transformar a coluna stop em uma categoria:
# Função para categorizar o número de paradas
get_paradas <- function(stop) {
stop <- tolower(trimws(stop)) # Remove espaços e converte para minúsculas
if (startsWith(stop, "non")) {
return("zero") # Zero paradas
} else if (startsWith(stop, "1")) {
return("um") # Uma parada
} else {
return("dois_ou_mais") # Duas ou mais paradas
}
}Para transformar a duração do voo de horas minutos(h m) para horas no valor númerico:
# Função para converter a duração do voo para horas
converter_para_horas <- function(time_str) {
# Remove espaços da string
time_str <- gsub(" ", "", time_str)
# Extrai as horas (números antes do 'h')
horas <- as.numeric(gsub("h.*", "", time_str))
# Extrai os minutos (números entre 'h' e 'm')
minutos_str <- gsub(".*h|m", "", time_str)
minutos <- ifelse(nchar(minutos_str) > 0, as.numeric(minutos_str), 0)
# Converte minutos para horas e soma
total_horas <- horas + (minutos / 60)
return(total_horas)
}Obtém os feriados da Índia e utiliza a função para ver se a data foi durante um feriado, depois do feriado(1 dia depois), antes do feriado(1 dia antes) ou se não teve feriado perto:
# Obter os feriados na Índia para o ano de 2022
feriados_india_dates <- as.Date(holidays(
countries = "India",
years = 2022,
quiet = TRUE, # Desativa a verbosidade
include_regions = TRUE # Inclui detalhes sobre regiões internas
)$holiday)
# Função para categorizar a data com base nos feriados
get_feriado <- function(data) {
if (data %in% feriados_india_dates) {
return("durante") # Data é um feriado
} else if ((data - 1) %in% feriados_india_dates) {
return("depois") # Dia após um feriado
} else if ((data + 1) %in% feriados_india_dates) {
return("antes") # Dia antes de um feriado
} else {
return("sem feriado") # Nenhuma das opções acima
}
}dados_limpos <- bind_rows(business, economy) %>%
mutate(
# Transformações e criação de novas colunas
date = as.Date(date, format = "%d-%m-%Y"), # Converte a coluna de data para o formato Date
mes_viagem = factor(month(date, label = TRUE, abbr = FALSE)), # Extrai o mês da data
dia_da_semana = factor(weekdays(date)), # Extrai o dia da semana da data
companhia = factor(airline), # Converte 'airline' para fator
cidade_origem = factor(from), # Converte 'from' para fator
turno_saida = factor(sapply(dep_time, get_turno)), # Determina o turno de saída
paradas = factor(sapply(stop, get_paradas)), # Categoriza o número de paradas
cidade_destino = factor(to), # Converte 'to' para fator
turno_chegada = factor(sapply(arr_time, get_turno)), # Determina o turno de chegada
classe = factor(classe), # Converte 'classe' para fator
duracao = converter_para_horas(time_taken), # Converte a duração para horas
preco = as.integer(gsub(",", "", price)), # Remove vírgulas e converte 'price' para inteiro
feriado = factor(sapply(date, get_feriado)) # Determina a categoria de feriado
) %>%
select(
companhia, cidade_origem, turno_saida, paradas,
cidade_destino, turno_chegada, classe, duracao, preco,
mes_viagem, dia_da_semana, feriado
)Temos uma amostra dos dados limpos:
Neste tópico, vamos explorar como diferentes características dos voos influenciam o preço das passagens. Os gráficos apresentados aqui ajudam a entender o impacto de fatores como a companhia aérea, o número de paradas, a duração do voo e a classe em que o passageiro viaja.
# Gráfico de Distribuição do Preço por Companhia
ggplotly(
ggplot(dados_limpos %>%
select(preco, companhia),
aes(x = companhia, y = preco)) +
geom_boxplot(aes(color = companhia)) +
labs(title = "Distribuição do Preço por Companhia", x = "Companhia", y = "Preço") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
)As companhias Air India e Vistara se destacam com medianas de preço mais elevadas, sugerindo que suas passagens tendem a ser mais caras em comparação com as demais. Além disso, elas apresentam caixas (IQR) maiores, indicando uma ampla variação nos preços das passagens. No entanto, a ausência de outliers sugere que essas variações de preço são relativamente consistentes e não há preços extremamente altos fora do padrão esperado para essas companhias.
As companhias AirAsia, Go First, Indigo, e SpiceJet apresentam medianas de preço que estão na média em comparação com as demais companhias. Essas empresas têm caixas (IQR) pequenas, indicando que a faixa de preços das passagens é mais restrita e menos variável. No entanto, essas companhias têm uma quantidade significativa de outliers, o que sugere que, apesar dos preços médios estarem na média, há casos de preços muito altos. Isso indica que, enquanto a maioria das passagens tem preços relativamente estáveis, ainda existem variações significativas que não são refletidas na mediana.
StarAir apresenta uma caixa (IQR) um pouco maior em comparação com companhias como AirAsia, Go First, Indigo e SpiceJet, mas ainda menor que as caixas de Air India e Vistara. A ausência de outliers sugere que a maioria das passagens tem preços mais consistentes e previsíveis.
Por outro lado, Trujet possui a menor mediana de preços, o que indica que os preços médios das passagens são mais baixos em comparação com as outras companhias. A caixa é tão pequena que mal é visível no gráfico, e poucos outliers estão presentes, sugerindo que a variação nos preços é limitada e que há uma predominância de preços baixos e consistentes para as passagens da Trujet.
# Gráfico de Preço Médio por Número de Paradas e Classe
ggplotly(
ggplot(dados_limpos %>%
select(paradas, classe, preco) %>%
group_by(paradas, classe) %>%
summarise(preco_medio = mean(preco, na.rm = TRUE), .groups = 'drop'),
aes(x = paradas, y = preco_medio, fill = classe)) +
geom_bar(stat = "identity", position = "dodge", color = "black") +
labs(title = "Preço Médio por Número de Paradas e Classe", x = "Número de Paradas", y = "Preço Médio") +
theme_minimal() +
scale_fill_manual(values = c("economica" = "skyblue", "executiva" = "salmon")) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
)Embora a teoria inicial fosse que voos diretos seriam mais baratos, os dados sugerem que, no contexto analisado, o custo adicional das paradas pode estar associado a um aumento geral no preço das passagens. Isso pode estar relacionado a uma série de fatores, incluindo complexidade e custo dos itinerários mais longos.
# Gráfico da Relação entre Duração do Voo e Preço
ggplotly(
ggplot(dados_limpos %>%
group_by(duracao) %>%
summarise(preco_medio = mean(preco, na.rm = TRUE), .groups = 'drop'),
aes(x = duracao, y = preco_medio)) +
geom_point(color = "blue", size = 2) +
geom_smooth(method = "loess", color = "red", se = FALSE) +
labs(title = "Relação entre Duração do Voo e Preço", x = "Duração do Voo (horas)", y = "Preço Médio") +
theme_minimal()
)O gráfico apresenta a relação entre a duração do voo e o preço médio, evidenciando uma tendência geral de aumento dos preços com o incremento da duração até aproximadamente 20 horas. Após esse ponto, o preço médio começa a diminuir entre 20 e 40 horas de duração. A linha vermelha no gráfico representa uma suavização dos dados, que ajuda a visualizar essas tendências gerais mais claramente.
A análise sugere que voos com duração média até 20 horas tendem a ter preços mais altos, enquanto voos de duração intermediária (entre 20 e 40 horas) apresentam uma faixa de preço mais baixa. Isso pode ser reflexo de estratégias de preços das companhias aéreas, como ofertas especiais ou promoções para durações específicas de voo. A linha suavizada destaca essas tendências e facilita a interpretação das variações de preço em relação à duração do voo.
# Gráfico de Preços por Classe
ggplotly(
ggplot(dados_limpos %>%
select(preco, classe),
aes(x = classe, y = preco)) +
geom_boxplot(aes(color = classe)) +
labs(title = "Preços por Classe", x = "Classe", y = "Preço") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
)Na classe econômica, o boxplot revela uma caixa menor localizada em torno de preços mais baixos. Isso indica que a maioria das passagens está concentrada em um intervalo de preços relativamente restrito e baixo. No entanto, existem outliers para preços mais altos, sugerindo que, apesar de a classe econômica ser predominantemente mais acessível, há algumas exceções com passagens significativamente mais caras.
Por outro lado, a classe executiva exibe uma caixa maior, abrangendo uma faixa de preços mais ampla, com valores mínimos e máximos mais elevados. Essa ampla faixa de preços indica que, embora algumas passagens executivas possam estar em um intervalo de preços mais baixo, a maioria dos preços é substancialmente mais alta. A classe executiva apresenta outliers tanto para preços mais altos quanto mais baixos, refletindo uma maior variabilidade e dispersão nos preços das passagens.
Em resumo, o boxplot mostra que a classe econômica tende a ter preços mais baixos e uma distribuição mais uniforme, com alguns outliers mais caros. Em contraste, a classe executiva é caracterizada por uma maior variação nos preços, com uma caixa maior e outliers em ambas as extremidades da distribuição, indicando uma ampla gama de preços.
# Gráfico do Preço Médio das Passagens por Dia da Semana
ggplotly(
ggplot(dados_limpos %>%
group_by(dia_da_semana) %>%
summarise(preco_medio = mean(preco, na.rm = TRUE), .groups = 'drop'),
aes(x = reorder(dia_da_semana, preco_medio), y = preco_medio, fill = dia_da_semana)) +
geom_bar(stat = "identity", color = "black") +
labs(title = "Preço Médio das Passagens por Dia da Semana", x = "Dia da Semana", y = "Preço Médio") +
theme_minimal() +
coord_flip() +
scale_fill_manual(values = c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2"))
) %>%
layout(legend = list(title = list(text = "Dia da Semana")))O gráfico revela que, de forma geral, não há grandes diferenças significativas entre os preços médios das passagens ao longo da semana. A maioria dos dias apresenta valores semelhantes, sem grandes variações. No entanto, é possível observar que os preços médios das passagens nos sábados e domingos são ligeiramente mais altos em comparação com os dias úteis. Isso sugere que, apesar de uma leve tendência de aumento no fim de semana, os preços médios mantêm uma estabilidade ao longo da semana, sem disparidades significativas.
# Gráfico do Preço Médio por Período de Feriado
ggplotly(
ggplot(dados_limpos %>%
group_by(feriado) %>%
summarise(preco_medio = mean(preco, na.rm = TRUE), .groups = 'drop'),
aes(x = feriado, y = preco_medio, fill = feriado)) +
geom_bar(stat = "identity", color = "black") +
labs(title = "Preço Médio por Período de Feriado", x = "Período de Feriado", y = "Preço Médio") +
theme_minimal() +
scale_fill_brewer(palette = "Set3")
)O gráfico apresenta a variação do preço médio das passagens em diferentes períodos de feriado. De forma geral, os preços médios não mostram grandes discrepâncias entre os períodos analisados. No entanto, é possível observar que os valores tendem a ser um pouco mais elevados nos períodos que antecedem os feriados, sugerindo uma demanda maior nesse intervalo. Já para os períodos sem feriados, os preços são ligeiramente mais baixos, indicando uma possível menor procura e, consequentemente, um ajuste de preço. Embora as diferenças sejam sutis, elas apontam para um leve impacto dos feriados no valor das passagens.
# Gráfico da Média dos Preços por Turno de Saída e Chegada
preco_media_turnos <- dados_limpos %>%
select(preco, turno_saida, turno_chegada) %>%
group_by(turno_saida, turno_chegada) %>%
summarise(preco_medio = mean(preco, na.rm = TRUE), .groups = 'drop')
# Criar o gráfico de calor
ggplotly(ggplot(preco_media_turnos, aes(
x = factor(turno_saida, levels = c("madrugada", "manhã", "tarde", "noite")),
y = factor(turno_chegada, levels = c("madrugada", "manhã", "tarde", "noite")),
fill = preco_medio
)) +
geom_tile() +
scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = median(preco_media_turnos$preco_medio)) +
labs(title = "Média dos Preços por Turno de Saída e Chegada",
x = "Turno de Saída",
y = "Turno de Chegada",
fill = "Preço Médio") +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
theme_minimal())A análise dos preços médios em relação aos turnos de saída e chegada revela que voos que partem ou chegam na madrugada apresentam preços mais baixos em comparação com outros horários do dia. Isso pode ser uma opção vantajosa para viajantes que buscam economizar em suas passagens aéreas. A maior acessibilidade financeira desses horários pode ser atribuída a uma menor demanda, o que faz com que as companhias aéreas ajustem os preços para atrair passageiros durante períodos menos populares.
# Gráfico do Preço Médio por Cidade de Origem e Destino
preco_media_cidades <- dados_limpos %>%
select(cidade_origem, cidade_destino, preco) %>%
group_by(cidade_origem, cidade_destino) %>%
summarise(preco_medio = mean(preco, na.rm = TRUE), .groups = 'drop')
# Criando o gráfico de calor
ggplotly(ggplot(preco_media_cidades, aes(x = cidade_origem, y = cidade_destino, fill = preco_medio)) +
geom_tile() +
scale_fill_gradient2(low = "green", mid = "yellow", high = "red", midpoint = median(preco_media_cidades$preco_medio)) +
labs(title = "Preço Médio por Cidade de Origem e Destino", x = "Cidade de Origem", y = "Cidade de Destino", fill = "Preço Médio") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)))O gráfico de calor ilustra o preço médio das passagens entre diferentes combinações de cidades de origem e destino. As cores variam de verde a vermelho, representando os preços médios mais baixos a mais altos, respectivamente.
A partir do gráfico, é evidente que Delhi se destaca como a cidade com os preços médios mais baixos, indicados pela cor verde. Isso sugere que, ao considerar voos com origem ou destino em Delhi, os passageiros podem encontrar as tarifas mais econômicas em comparação com outras cidades.
# Gráfico da Distribuição de Preços
ggplotly(
ggplot(dados_limpos %>%
select(preco), aes(x = preco)) +
geom_histogram(binwidth = 10000, fill = "lightgreen", color = "black", alpha = 0.7) +
scale_x_continuous(labels = scales::label_comma()) + # Formata os rótulos do eixo x com separador de milhar
scale_y_continuous(labels = scales::label_number(scale = 1)) + # Formata os rótulos do eixo y como números inteiros
labs(title = "Distribuição de Preços", x = "Preço", y = "Frequência") +
theme_minimal()
)O histograma revela que a maioria dos preços das passagens de voo está concentrada nas faixas mais baixas, com uma diminuição significativa na frequência à medida que os preços aumentam. As barras mais altas estão localizadas entre 0 e 20.000, sugerindo que há uma predominância de passagens com preços mais baixos. À medida que avançamos para faixas de preços mais elevados, a frequência das ocorrências diminui, indicando uma crescente escassez de passagens em intervalos de preços entre 20.000 e 120.000.
Especificamente, a distribuição mostra duas barras destacadas na faixa de 0 a 20.000, o que indica uma alta concentração de passagens a preços baixos. Entre 20.000 e 40.000, a frequência diminui, sugerindo uma menor quantidade de passagens nesse intervalo de preço. De 40.000 a 60.000, a frequência aumenta novamente, mas diminui nas faixas de 60.000 a 80.000, indicando uma variação na oferta ou demanda. Finalmente, acima de 80.000, as barras são quase invisíveis, o que indica que passagens com preços muito altos são raras na base de dados.
Esses padrões sugerem que passagens de voo com preços mais baixos são muito mais comuns, enquanto passagens mais caras são relativamente raras. Isso pode refletir uma tendência geral no mercado de passagens aéreas, onde a maioria das ofertas está disponível em faixas de preços mais acessíveis, com menos opções para passagens de preços elevados.
O problema abordado neste estudo foi como diversos fatores influenciam o preço das passagens aéreas e como os passageiros podem utilizar essas informações para economizar e tomar decisões mais informadas. Com a ampla gama de variáveis que afetam o custo das passagens, desde a antecedência da compra até as companhias aéreas e os horários dos voos, é essencial entender esses fatores para otimizar os gastos com viagens.
Para abordar essa questão, utilizamos um conjunto de dados fornecido pelo site “Ease My Trip”, que inclui mais de 300 mil registros de voos entre principais cidades da Índia. A metodologia empregada foi a Análise Exploratória de Dados (EDA), utilizando visualizações gráficas e estatísticas descritivas. As análises incluíram a distribuição dos preços por companhia aérea, número de paradas, duração do voo, classe, dia da semana, período de feriado e turno de saída e chegada.
1. Companhias Aéreas: A análise revelou que companhias como Air India e Vistara tendem a ter preços mais altos, enquanto companhias como Trujet oferecem preços mais baixos e consistentes. Essa informação pode ajudar os passageiros a escolher entre opções mais econômicas e mais caras.
2. Número de Paradas: Surpreendentemente, voos com paradas adicionais não apresentaram uma redução de preço como esperado, sugerindo que a complexidade e o custo dos itinerários com paradas adicionais podem ser mais altos.
3. Duração do Voo: Os preços mostram um aumento até cerca de 20 horas de duração do voo, seguido por uma diminuição. Isso pode refletir uma estratégia de precificação das companhias aéreas que se ajusta com a duração do voo.
4. Classe e Turno: A classe executiva tem preços significativamente mais altos e variáveis, enquanto os preços são geralmente mais baixos em horários menos convencionais e em voos sem paradas.
5. Feriados e Dias da Semana: Os preços tendem a ser mais altos antes dos feriados e nos finais de semana, indicando uma maior demanda.
Os passageiros podem usar esses insights para planejar melhor suas viagens, identificando as melhores épocas e companhias aéreas para obter passagens mais baratas. Com base nas análises, é possível ajustar o planejamento de viagem para evitar períodos de alta demanda e considerar horários alternativos e companhias aéreas mais econômicas.
Embora a análise forneça uma visão abrangente sobre os fatores que influenciam o preço das passagens aéreas, algumas limitações precisam ser consideradas:
Dados Limitados a uma Região: Os dados usados são específicos para voos na Índia, e as conclusões podem não se aplicar a outros mercados.
Variáveis Não Incluídas: Fatores adicionais, como o tempo de compra ou eventos especiais, não foram analisados e podem afetar os preços.
Dados de Qualidade: A qualidade e a completude dos dados podem impactar a precisão dos resultados.
Para aprimorar a análise, seria útil expandir o conjunto de dados para incluir voos de outras regiões e considerar mais variáveis. Além disso, a implementação de modelos de previsão baseados em aprendizado de máquina poderia oferecer insights mais detalhados e precisos sobre os preços das passagens aéreas.