A indústria cinematográfica brasileira é caracterizada por uma história de extremos, alternando entre períodos de grande popularidade e crises estruturais. Desde o auge nos anos 1970 — impulsionado por políticas de fomento e o sucesso de filmes populares — até o declínio acentuado nas décadas subsequentes, o mercado sempre demonstrou forte correlação com a estabilidade econômica e o ambiente regulatório do país (AIC - Academia Internacional de Cinema 2019).
Após ser duramente atingido pela pandemia de Covid-19 e pela ascensão do streaming, o circuito exibidor brasileiro mostra sinais de recuperação. Em 2023, o país registrou 114,1 milhões de pagantes e cerca de 3.480 salas, embora ainda aquém dos patamares pré-pandemia (Salgado 2024). Essa recuperação é sustentada por marcos regulatórios recentes, como o restabelecimento da Cota de Tela (Lei nº 14.814/2024) (“Lei Nº 14.814, de 15 de Janeiro de 2024,” n.d.), que obriga exibidoras a dedicarem um número mínimo de sessões à produção nacional até 2033. Essa medida é vista como crucial para proteger o cinema nacional e garantir sua participação efetiva nos horários de maior procura.
Embora a recuperação do público seja um indicador positivo, a infraestrutura de exibição no Brasil apresenta um desafio estrutural: a baixa cobertura e a alta concentração. A migração histórica dos cinemas de rua para o modelo de multiplex em shopping centers resultou em um mercado onde 88,4% das salas estão em shoppings, e apenas 8% dos municípios brasileiros (451 de 5.565) possuem acesso a um cinema (Salgado 2024).
Essa concentração levanta a questão central desta análise: se o acesso à experiência cinematográfica está geograficamente restrito e se essa limitação influencia diretamente os hábitos de consumo e a rentabilidade do setor.
Este relatório apresenta uma análise da forma de consumo e disponibilidade de cinemas e filmes no Brasil em 2024, confrontando a infraestrutura de salas (acessibilidade) com o comportamento de bilheteria (demanda).
O estudo utilizará exclusivamente dados consolidados de bilheteria e cadastro de salas da Agência Nacional do Cinema (ANCINE) referentes ao ano de 2024, visando mapear:
Padrões de Consumo: A distribuição temporal (mês, dia, horário) do público e da receita.
Alcance Geográfico: A relação entre o número de salas/complexos por UF e município e o desempenho de público e renda.
Influência da Infraestrutura: Como a disponibilidade e o tipo de sala (e sua localização) se correlacionam com a capacidade de atração de público no cenário pós-pandemia, sob a vigência de novas políticas como a Cota de Tela.
Nesta seção são apresentadas as fontes de dados utilizadas no estudo, ambas disponibilizadas pela Agência Nacional do Cinema (ANCINE) por meio do Portal Brasileiro de Dados Abertos. As duas bases possuem ampla cobertura nacional e seguem padrões de padronização definidos por instruções normativas específicas.
O conjunto de dados de Relatório de Bilheteria Diária de Obras Informadas pelas Exibidoras reúne informações declaradas pelas exibidoras sobre todas as sessões de cinema realizadas no país. Cada registro corresponde a uma sessão individual e inclui data, horário, obra exibida, características da sala e do exibidor, além de indicadores de público e receita.
Os dados são originalmente organizados por ano e mês, mas cada mês é subdividido em arquivos referentes às semanas consolidadas, no formato:
YYYY-MM-s01
YYYY-MM-s02
YYYY-MM-s03
YYYY-MM-s04
YYYY-MM-s05
Por exemplo:
2014-01-s012014-01-s022023-11-s012023-11-s02Essa estrutura permite que a base seja atualizada continuamente, com novas semanas publicadas conforme o envio obrigatório das informações pelas exibidoras. Assim, o conjunto disponibilizado é sempre o mais atualizado possível, porém meses muito recentes podem aparecer ainda incompletos.
Para garantir consistência temporal e evitar problemas decorrentes de semanas não consolidadas, esta análise utiliza exclusivamente os dados referentes a 2024, que apresentam maior estabilidade e cobertura completa.
O envio das informações é regulamentado pela Instrução Normativa nº 123/2015, que define as diretrizes do Sistema de Controle de Bilheteria (SCB).
Mais informações: Instrução Normativa n.º 123, de 22 de dezembro de 2015
A base contém informações como:
Esses campos tornam possível realizar análises temporais, geográficas, econômicas e estruturais do mercado exibidor brasileiro.
A base de Salas de Exibição e Complexos Registrados na ANCINE reúne informações do cadastro oficial de salas, complexos e exibidores registrados na ANCINE. Inclui dados estruturais (capacidade, acessibilidade, operação), localização, situação de funcionamento e informações cadastrais.
Esse cadastro segue normas estabelecidas pelas instruções normativas:
Mais informações:
A base inclui:
Essa base é fundamental para contextualizar as análises de bilheteria com a infraestrutura de exibição existente no país.
Esses são os pacotes necessários para executar a análise descrita nesse documento:
##
## Anexando pacote: 'dplyr'
## Os seguintes objetos são mascarados por 'package:stats':
##
## filter, lag
## Os seguintes objetos são mascarados por 'package:base':
##
## intersect, setdiff, setequal, union
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats 1.0.1 ✔ purrr 1.1.0
## ✔ ggplot2 4.0.0 ✔ tibble 3.3.0
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
##
## Anexando pacote: 'hms'
##
## O seguinte objeto é mascarado por 'package:lubridate':
##
## hms
## Warning: pacote 'DT' foi compilado no R versão 4.5.2
##
## Anexando pacote: 'scales'
##
## O seguinte objeto é mascarado por 'package:purrr':
##
## discard
##
## O seguinte objeto é mascarado por 'package:readr':
##
## col_factor
##
## Anexando pacote: 'plotly'
##
## O seguinte objeto é mascarado por 'package:ggplot2':
##
## last_plot
##
## O seguinte objeto é mascarado por 'package:stats':
##
## filter
##
## O seguinte objeto é mascarado por 'package:graphics':
##
## layout
Os dados de bilheteria diária e das salas de cinema utilizados neste
estudo são disponibilizados pela ANCINE por meio do Portal Brasileiro de
Dados Abertos, como explicado da seção de Introdução. Cada mês é
dividido em arquivos semanais (por exemplo:
2024-01-s01, 2024-01-s02, …), contendo todas
as sessões de cinema realizadas naquela semana.
Embora a base complete constantemente novas semanas ao longo do ano — sendo, portanto, a mais atualizada possível — para esta análise foram utilizados exclusivamente os dados referentes ao ano de 2024, que é o último ano completo no momento dessa análise.
Isso significa que, entre todos os arquivos disponibilizados (2014–2025), foram carregados apenas aqueles que seguem o padrão:
bilheteria-diaria-obras-por-exibidoras-2024-XX-sYY.csv
onde:
XX representa o mês (01 a 12)YY representa a semana do mês (s01 a s05, dependendo do
calendário)A opção por limitar a análise ao ano de 2024 se justifica pela necessidade de trabalhar com:
Além disso, para garantir consistência na correspondência com a base de Salas de Exibição e Complexos, também foi carregada a versão mais recente disponível do cadastro oficial de salas no ano de referência.
Nesta subseção, identificamos na pasta de trabalho apenas os arquivos
semanais do ano de 2024. Os nomes seguem o padrão
YYYY-MM-sXX, o que permite filtrar os arquivos desejados
com expressões regulares. Em seguida, uma função auxiliar extrai o mês
de referência de cada arquivo para que possam ser agrupados.
pasta <- "Bilheteria-Salas-Cinema"
# *Assumindo que os arquivos CSV estão na pasta especificada*
arquivos_bilheteria <- list.files(
pasta,
pattern = "^bilheteria-diaria-obras-por-exibidoras-2024-\\d{2}-s\\d{2}\\.csv$",
full.names = TRUE
)
extrair_mes <- function(caminho) {
nome <- basename(caminho)
sub(".*(2024-\\d{2}).*", "\\1", nome)
}
meses <- sapply(arquivos_bilheteria, extrair_mes)Cada mês do ano é distribuído em múltiplos arquivos semanais. Nesta
etapa, os arquivos são agrupados por mês e combinados em um único data
frame mensal. A função map_dfr() é utilizada para ler e
empilhar todas as semanas daquele mês, removendo colunas irrelevantes
para a análise.
# Usando split() e lapply() para agrupar e carregar
lista_meses_combinados <- lapply(
split(arquivos_bilheteria, meses),
function(arquivos_mes) {
map_dfr(
arquivos_mes,
~read_csv2(
file = .x,
locale = locale(encoding = "UTF-8"),
col_select = -c(REGISTRO_GRUPO_EXIBIDOR, REGISTRO_EXIBIDOR, REGISTRO_COMPLEXO)
)
)
}
)Motivos para o descarte das colunas:
Além da base de bilheteria, também é carregado o cadastro oficial de salas e complexos exibidores da ANCINE. Esses metadados são importantes para complementar e validar as informações de exibição presentes nos relatórios de bilheteria. Algumas colunas menos relevantes são descartadas para otimizar o processamento.
df_salas <- read_csv2(
file = file.path(pasta, "salas-de-exibicao-e-complexos.csv"),
locale = locale(encoding = "UTF-8"),
col_select = -c(
PAGINA_ELETRONICA_COMPLEXO, ENDERECO_COMPLEXO, NUMERO_ENDERECO_COMPLEXO,
COMPLEMENTO_COMPLEXO, BAIRRO_COMPLEXO, DATA_INICIO_FUNCIONAMENTO_SALA, DATA_SITUACAO_SALA, SITUACAO_SALA, DATA_SITUACAO_COMPLEXO, SITUACAO_COMPLEXO, SITUACAO_EXIBIDOR
)
)Motivos para o descarte das colunas:
Após o carregamento das bases, realizamos uma inspeção preliminar para verificar a estrutura dos dados, identificar possíveis problemas e garantir que o conteúdo está coerente com o esperado. A seguir, são exibidos exemplos das primeiras linhas de cada uma das fontes utilizadas.
Essa prévia permite inspecionar nomes de colunas, formatos de data, valores ausentes e outras possíveis inconsistências antes de etapas posteriores de limpeza e integração.
A base de bilheteria foi organizada em uma lista
(lista_meses_combinados), na qual cada elemento corresponde
a um mês completo de 2024 já resultante da combinação de suas
semanas.
A visualização abaixo mostra as primeiras linhas do primeiro mês disponível na lista:
DT::datatable(
head(lista_meses_combinados[[1]], 10),
extensions = "Scroller",
options = list(
deferRender = TRUE,
scrollX = TRUE,
scrollY = 300,
scroller = TRUE
),
rownames = FALSE
)## Rows: 392,667
## Columns: 15
## $ DATA_EXIBICAO <chr> "01/01/2024", "01/01/2024", "01/01/2024", "01/…
## $ SESSAO <chr> "01/01/2024 10:30:00", "01/01/2024 10:40:00", …
## $ TITULO_ORIGINAL <chr> "WONKA", "FALLEN LEAVES", "MIGRATION", "MIGRAT…
## $ TITULO_BRASIL <chr> "WONKA", "FOLHAS DE OUTONO", "PATOS!", "PATOS!…
## $ CPB_ROE <chr> "E2300218300000", "E2300438800000", "E23004593…
## $ AUDIO <chr> "DUBLADO", "ORIGINAL", "DUBLADO", "DUBLADO", "…
## $ LEGENDADA <chr> "NÃO", "SIM", "NÃO", "NÃO", "NÃO", "NÃO", "NÃO…
## $ PAIS_OBRA <chr> "ESTADOS UNIDOS", "ALEMANHA", "ESTADOS UNIDOS"…
## $ REGISTRO_SALA <dbl> 5006728, 5006729, 5006247, 5002819, 5003328, 5…
## $ NOME_SALA <chr> "SALA 01 DO CENTRO CULTURAL UNIMED BH- MINAS",…
## $ PUBLICO <dbl> 2, 3, 0, 0, 4, 6, 19, 8, 0, 0, 2, 3, 4, 9, 1, …
## $ MUNICIPIO_SALA_COMPLEXO <chr> "BELO HORIZONTE", "BELO HORIZONTE", "GOIÂNIA",…
## $ UF_SALA_COMPLEXO <chr> "MG", "MG", "GO", "SC", "SP", "SC", "SC", "RS"…
## $ RAZAO_SOCIAL_EXIBIDORA <chr> "MINAS TÊNIS CLUBE", "MINAS TÊNIS CLUBE", "FRE…
## $ CNPJ_EXIBIDORA <chr> "17.217.951/0001-10", "17.217.951/0001-10", "0…
A visualização abaixo mostra as primeiras linhas da base de dados que descreve as salas de cinema registradas pela ANCINE:
DT::datatable(
head(df_salas),
extensions = "Scroller",
options = list(
deferRender = TRUE,
scrollX = TRUE,
scrollY = 300,
scroller = TRUE
),
rownames = FALSE
)## Rows: 6,303
## Columns: 21
## $ NOME_SALA <chr> "CINE COMPANY JAGUARIUNA", "CINE COMPANY …
## $ REGISTRO_SALA <dbl> 5003332, 5003331, 5003401, 5003402, 50034…
## $ CNPJ_SALA <chr> "10.615.866/0001-60", "10.615.866/0001-60…
## $ ASSENTOS_SALA <dbl> 162, 162, 402, 370, 245, 332, 210, 137, 1…
## $ ASSENTOS_CADEIRANTES <dbl> NA, NA, 8, 8, 5, 5, 4, 3, 3, 6, 5, 5, 5, …
## $ ASSENTOS_MOBILIDADE_REDUZIDA <dbl> NA, NA, 5, 4, 3, 3, 3, 1, 1, 4, 3, 3, 3, …
## $ ASSENTOS_OBESIDADE <dbl> NA, NA, 5, 4, 3, 3, 3, 1, 1, 4, 3, 3, 3, …
## $ ACESSO_ASSENTOS_COM_RAMPA <chr> "NÃO", "NÃO", "SIM", "SIM", "SIM", "SIM",…
## $ ACESSO_SALA_COM_RAMPA <chr> "NÃO", "NÃO", "NÃO", "NÃO", "NÃO", "NÃO",…
## $ BANHEIROS_ACESSIVEIS <chr> "NÃO", "NÃO", "SIM", "SIM", "SIM", "SIM",…
## $ NOME_COMPLEXO <chr> "02 P D & ARAUJO EMPRESA CINEMATOGRAFICA …
## $ REGISTRO_COMPLEXO <dbl> 19955, 19955, 20449, 20449, 20449, 20449,…
## $ MUNICIPIO_COMPLEXO <chr> "JAGUARIÚNA", "JAGUARIÚNA", "SÃO CAETANO …
## $ CEP_COMPLEXO <chr> "13820-000", "13820-000", "09531-190", "0…
## $ UF_COMPLEXO <chr> "SP", "SP", "SP", "SP", "SP", "SP", "SP",…
## $ COMPLEXO_ITINERANTE <chr> "NÃO", "NÃO", "NÃO", "NÃO", "NÃO", "NÃO",…
## $ OPERACAO_USUAL <chr> "COMERCIAL", "COMERCIAL", "COMERCIAL", "C…
## $ NOME_EXIBIDOR <chr> "02 P D & ARAUJO EMPRESA CINEMATOGRAFICA …
## $ REGISTRO_EXIBIDOR <dbl> 19954, 19954, 1843, 1843, 1843, 1843, 184…
## $ CNPJ_EXIBIDOR <chr> "10.615.866/0001-60", "10.615.866/0001-60…
## $ NOME_GRUPO_EXIBIDOR <chr> "NÃO PERTENCE A NENHUM GRUPO EXIBIDOR", "…
Aqui vamos ver como está a situação dos dados quanto a presença de NA’s.
# 1. Calcular percentual de NA por coluna em cada mês
na_pct_por_mes <- lista_meses_combinados %>%
map_dfr(
~ colMeans(is.na(.x)) * 100, # colMeans = média lógica, vira % de NA
.id = "Mes"
)
# 2. Transformar para formato longo (tidy)
na_pct_long <- na_pct_por_mes %>%
pivot_longer(-Mes, names_to = "Coluna", values_to = "Pct_NA")
# 3. Criar o heatmap
ggplot(na_pct_long, aes(x = Mes, y = Coluna, fill = Pct_NA)) +
geom_tile(color = "white") +
scale_fill_gradient(
low = "#FFFFFF",
high = "#0D47A1", # sua cor primária
name = "% NA"
) +
labs(
title = "Percentual de valores NA por coluna e mês",
x = "Mês",
y = "Coluna"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1)
)Observa-se uma maior concentração de valores ausentes nas colunas PAIS_OBRA e TITULO_BRASIL. No caso de PAIS_OBRA, a ausência é esperada, pois esse campo não é preenchido quando o item exibido pertence às categorias “Mostra e Festivais”, “Shows e Musicais” ou “Eventos Esportivos”. Nessas situações, o país de produção não se aplica.
DT::datatable(
lista_meses_combinados[["2024-01"]] %>%
filter(is.na(PAIS_OBRA)) %>%
slice(526:530) %>%
select(DATA_EXIBICAO, TITULO_ORIGINAL, TITULO_BRASIL, PAIS_OBRA),
extensions = "Scroller",
options = list(
deferRender = TRUE,
scrollX = TRUE,
scrollY = 300,
scroller = TRUE
),
rownames = FALSE
)Para evitar que esses casos apareçam como valores faltantes nas análises — o que poderia sugerir erro de preenchimento — optou-se por recodificar esses NA específicos como “Não se aplica”, preservando a interpretação correta do dado.
lista_meses_combinados_tratados <- lista_meses_combinados %>%
map(~.x %>%
mutate(
PAIS_OBRA = ifelse(
TITULO_ORIGINAL %in% c("Mostras e Festivais", "Shows e Musicais", "Eventos Esportivos"),
"Não se aplica",
PAIS_OBRA
)
)
)
DT::datatable(
lista_meses_combinados_tratados[["2024-01"]] %>%
filter(TITULO_ORIGINAL %in% c("Mostras e Festivais", "Shows e Musicais", "Eventos Esportivos")) %>%
slice(526:530) %>%
select(DATA_EXIBICAO, TITULO_ORIGINAL, TITULO_BRASIL, PAIS_OBRA),
extensions = "Scroller",
options = list(
deferRender = TRUE,
scrollX = TRUE,
scrollY = 300,
scroller = TRUE
),
rownames = FALSE
)No caso de TITULO_BRASIL, os valores ausentes ocorrem principalmente porque, para filmes nacionais, apenas a coluna TITULO_ORIGINAL é utilizada, deixando TITULO_BRASIL em branco. Além disso, esse campo também não é preenchido quando o conteúdo exibido pertence às categorias “Mostra e Festivais”, “Shows e Musicais” ou “Eventos Esportivos”.
DT::datatable(
lista_meses_combinados[["2024-01"]] %>%
filter(is.na(TITULO_BRASIL)) %>%
slice(1:10) %>%
select(DATA_EXIBICAO, TITULO_ORIGINAL, TITULO_BRASIL, PAIS_OBRA),
extensions = "Scroller",
options = list(
deferRender = TRUE,
scrollX = TRUE,
scrollY = 300,
scroller = TRUE
),
rownames = FALSE
)Para esse caso, vamos simplesmente repetir o Título Original do filme para a coluna TITULO_BRASIL, já que utilizaremos ela para as análises.
lista_meses_combinados_tratados <- lista_meses_combinados_tratados %>%
map(~.x %>%
mutate(
# Preenche TITULO_BRASIL com TITULO_ORIGINAL se for NA
TITULO_BRASIL = if_else(is.na(TITULO_BRASIL), TITULO_ORIGINAL, TITULO_BRASIL)
)
)
DT::datatable(
lista_meses_combinados_tratados[["2024-01"]] %>%
filter(PAIS_OBRA == "BRASIL") %>%
slice(2:6) %>%
select(DATA_EXIBICAO, TITULO_ORIGINAL, TITULO_BRASIL, PAIS_OBRA),
extensions = "Scroller",
options = list(
deferRender = TRUE,
scrollX = TRUE,
scrollY = 300,
scroller = TRUE
),
rownames = FALSE
)Como mencionado anteriormente, a coluna SESSAO armazena tanto a data quanto o horário da sessão em formato de texto. Nesta etapa, extraímos apenas o horário para manter na coluna SESSAO, enquanto a data é preservada na coluna DATA_EXIBICAO. Em seguida, ambas são convertidas para formatos apropriados: DATA_EXIBICAO para o tipo Date e SESSAO para o tipo hms.
Nesta etapa, convertemos essas colunas para factor, já que representam variáveis categóricas e devem ser tratadas como tal nas análises subsequentes.
Após os tratamentos realizados:
## DATA_EXIBICAO SESSAO TITULO_ORIGINAL
## 0 0 0
## TITULO_BRASIL CPB_ROE AUDIO
## 0 0 0
## LEGENDADA PAIS_OBRA REGISTRO_SALA
## 0 0 0
## NOME_SALA PUBLICO MUNICIPIO_SALA_COMPLEXO
## 0 0 0
## UF_SALA_COMPLEXO RAZAO_SOCIAL_EXIBIDORA CNPJ_EXIBIDORA
## 0 0 0
Aqui apresentamos as colunas que apresentam NA’s e suas quantidades.
df_salas_na <- df_salas %>%
summarise(across(everything(), ~ sum(is.na(.)))) %>%
pivot_longer(everything(),
names_to = "variavel",
values_to = "n_na") %>%
filter(n_na > 0) # << filtra só colunas com NA
ggplot(df_salas_na, aes(x = reorder(variavel, n_na), y = n_na)) +
geom_col(fill = "#1E88E5") +
coord_flip() +
labs(
title = "Quantidade de valores ausentes por variável — df_salas",
x = "Variável",
y = "Nº de valores ausentes"
) +
theme_minimal(base_size = 12)
As colunas ASSENTOS_MOBILIDADE_REDUZIDA, ASSENTOS_OBESIDADE e
ASSENTOS_CADEIRANTES apresentam valores ausentes representando ausência
de assentos, sendo preenchidas com NA em vez de 0. Portanto,
substituímos os NA por 0 nessas variáveis.
df_salas_filtrado <- df_salas %>%
mutate(
across(
c(ASSENTOS_CADEIRANTES, ASSENTOS_MOBILIDADE_REDUZIDA, ASSENTOS_OBESIDADE),
~replace_na(.x, 0)
)
)Para os demais casos de valores ausentes, não identificamos uma relação direta — tratam-se simplesmente de informações que não foram fornecidas. Além disso, as linhas que apresentam esses NAs são, em grande parte, as mesmas, o que impede a obtenção de informações relevantes a partir delas.
DT::datatable(
df_salas_filtrado %>%
filter(is.na(REGISTRO_SALA)) %>%
slice(6:10),
extensions = "Scroller",
options = list(
deferRender = TRUE,
scrollX = TRUE,
scrollY = 300,
scroller = TRUE
),
rownames = FALSE
)Por esse motivo, optamos por excluir essas observações do conjunto de dados.
Aqui é selecionado um conjunto de colunas que representam informações categóricas e as converte para o tipo factor, garantindo que essas variáveis sejam tratadas como categorias. Isso padroniza a estrutura do dataframe e facilita análises estatísticas, modelagem e visualizações que dependem de variáveis categóricas bem definidas.
Após os tratamentos realizados:
## NOME_SALA REGISTRO_SALA
## 0 0
## CNPJ_SALA ASSENTOS_SALA
## 0 0
## ASSENTOS_CADEIRANTES ASSENTOS_MOBILIDADE_REDUZIDA
## 0 0
## ASSENTOS_OBESIDADE ACESSO_ASSENTOS_COM_RAMPA
## 0 0
## ACESSO_SALA_COM_RAMPA BANHEIROS_ACESSIVEIS
## 0 0
## NOME_COMPLEXO REGISTRO_COMPLEXO
## 0 0
## MUNICIPIO_COMPLEXO CEP_COMPLEXO
## 0 0
## UF_COMPLEXO COMPLEXO_ITINERANTE
## 0 0
## OPERACAO_USUAL NOME_EXIBIDOR
## 0 0
## REGISTRO_EXIBIDOR CNPJ_EXIBIDOR
## 0 0
## NOME_GRUPO_EXIBIDOR
## 0
DT::datatable(
df_salas_filtrado,
extensions = "Scroller",
options = list(
deferRender = TRUE,
scrollX = TRUE,
scrollY = 300,
scroller = TRUE
),
rownames = FALSE
)## Warning in instance$preRenderHook(instance): It seems your data is too big for
## client-side DataTables. You may consider server-side processing:
## https://rstudio.github.io/DT/server.html
# 1. Público por estado em cada mês
publico_mensal_por_estado <- lista_meses_combinados_tratados %>%
imap_dfr(~ .x %>%
group_by(UF_SALA_COMPLEXO) %>%
summarise(publico_estado = sum(PUBLICO, na.rm = TRUE),
.groups = "drop") %>%
mutate(Mes = .y))
# 2. Público total do mês
publico_total_mes <- publico_mensal_por_estado %>%
group_by(Mes) %>%
summarise(publico_total = sum(publico_estado), .groups = "drop")
# 3. Juntar e calcular percentual
percentual_estado_mes <- publico_mensal_por_estado %>%
left_join(publico_total_mes, by = "Mes") %>%
mutate(percentual = publico_estado / publico_total)
# 4. Média percentual anual por estado
media_percentual_por_estado <- percentual_estado_mes %>%
group_by(UF_SALA_COMPLEXO) %>%
summarise(media_percentual = mean(percentual), .groups = "drop")
# 5. Gráfico
ggplot(media_percentual_por_estado %>%
arrange(desc(media_percentual)),
aes(x = reorder(UF_SALA_COMPLEXO, media_percentual), y = media_percentual)) +
geom_col(fill = "steelblue") +
scale_y_continuous(labels = scales::label_percent(accuracy = 0.1)) +
labs(
title = "Participação Média do Público por Estado",
x = "Estado",
y = "Participação Média (%)"
) +
coord_flip() +
theme_minimal()# Certificando que Mes é fator para manter a ordem correta
publico_mensal_por_estado <- publico_mensal_por_estado %>%
mutate(Mes = factor(Mes, levels = unique(Mes)))
# Gráfico ggplot
p <- ggplot(publico_mensal_por_estado,
aes(x = Mes,
y = publico_estado,
color = UF_SALA_COMPLEXO,
group = UF_SALA_COMPLEXO,
text = paste("Estado:", UF_SALA_COMPLEXO,
"<br>Mês:", Mes,
"<br>Público:", format(publico_estado, big.mark = ",")))) +
geom_line(size = 1.2) +
geom_point(size = 2) +
scale_y_continuous(labels = scales::label_number(scale = 1e-6, suffix = "M")) +
labs(
title = "Evolução do Público por Estado",
x = "Mês",
y = "Público (em milhões)"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
# Transformando em plotly
ggplotly(p, tooltip = "text") %>%
layout(
autosize = TRUE, # faz o gráfico tentar ocupar todo o espaço disponível
margin = list(l = 150), # aumenta margem esquerda para labels longos
yaxis = list(tickformat = ",") # formata eixo Y com milhares
)# 1. Iterar sobre cada mês e juntar os dados
filmes_mais_assistidos <- lista_meses_combinados_tratados %>%
imap_dfr(~ .x %>%
group_by(UF_SALA_COMPLEXO, TITULO_BRASIL, PAIS_OBRA) %>%
summarise(publico_total = sum(PUBLICO, na.rm = TRUE), .groups = "drop") %>%
group_by(UF_SALA_COMPLEXO) %>%
slice_max(order_by = publico_total, n = 1) %>% # pega o filme mais assistido por estado
ungroup() %>%
mutate(Mes = .y))
# Visualizar
filmes_mais_assistidos## # A tibble: 324 × 5
## UF_SALA_COMPLEXO TITULO_BRASIL PAIS_OBRA publico_total Mes
## <fct> <fct> <fct> <dbl> <chr>
## 1 AC AQUAMAN 2: O REINO PERDIDO ESTADOS UNID… 7630 2024…
## 2 AL AQUAMAN 2: O REINO PERDIDO ESTADOS UNID… 27838 2024…
## 3 AM AQUAMAN 2: O REINO PERDIDO ESTADOS UNID… 49397 2024…
## 4 AP AQUAMAN 2: O REINO PERDIDO ESTADOS UNID… 10782 2024…
## 5 BA AQUAMAN 2: O REINO PERDIDO ESTADOS UNID… 91470 2024…
## 6 CE AQUAMAN 2: O REINO PERDIDO ESTADOS UNID… 69536 2024…
## 7 DF AQUAMAN 2: O REINO PERDIDO ESTADOS UNID… 60077 2024…
## 8 ES AQUAMAN 2: O REINO PERDIDO ESTADOS UNID… 51239 2024…
## 9 GO AQUAMAN 2: O REINO PERDIDO ESTADOS UNID… 73011 2024…
## 10 MA AQUAMAN 2: O REINO PERDIDO ESTADOS UNID… 37824 2024…
## # ℹ 314 more rows
# Pivot para heatmap
origem_filmes_estado <- filmes_mais_assistidos %>%
select(Mes, UF_SALA_COMPLEXO, PAIS_OBRA)
ggplot(origem_filmes_estado, aes(x = Mes, y = UF_SALA_COMPLEXO, fill = PAIS_OBRA)) +
geom_tile(color = "white") +
labs(
title = "Origem dos Filmes Mais Assistidos por Estado e Mês",
x = "Mês",
y = "Estado",
fill = "País do Filme"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))filme_mais_assistido_pais <- lista_meses_combinados_tratados %>%
imap_dfr(~ .x %>%
group_by(TITULO_BRASIL, PAIS_OBRA) %>%
summarise(publico_total = sum(PUBLICO, na.rm = TRUE), .groups = "drop") %>%
slice_max(order_by = publico_total, n = 1) %>% # pega o filme mais assistido do mês
mutate(Mes = .y))
# Agora você pode criar o gráfico
p <- ggplot(filme_mais_assistido_pais,
aes(x = Mes, y = publico_total, fill = PAIS_OBRA,
text = paste("Filme:", TITULO_BRASIL,
"<br>Público:", publico_total,
"<br>País:", PAIS_OBRA))) +
geom_col() +
labs(
title = "Filme Mais Assistido no País por Mês",
x = "Mês",
y = "Público Total",
fill = "País do Filme"
) +
theme_minimal()
# Transformando em plotly
ggplotly(p, tooltip = "text") %>%
layout(
autosize = TRUE, # faz o gráfico tentar ocupar todo o espaço disponível
margin = list(l = 150), # aumenta margem esquerda para labels longos
yaxis = list(tickformat = ",") # formata eixo Y com milhares
)# 1. Juntar todos os meses
todos_filmes <- lista_meses_combinados_tratados %>%
bind_rows() %>%
select(TITULO_BRASIL, PAIS_OBRA) %>%
distinct() # garante que cada filme conte apenas uma vez
# 2. Contar filmes por país (Top 5)
filmes_por_pais_top5 <- todos_filmes %>%
group_by(PAIS_OBRA) %>%
summarise(num_filmes = n(), .groups = "drop") %>%
arrange(desc(num_filmes)) %>%
slice_head(n = 5) # pega apenas o top 5
# 3. Gráfico de barras mostrando a quantidade absoluta de filmes por país
p <- ggplot(filmes_por_pais_top5,
aes(x = fct_reorder(PAIS_OBRA, num_filmes), y = num_filmes, fill = PAIS_OBRA,
text = paste("País:", PAIS_OBRA,
"<br>Número de Filmes:", num_filmes))) +
geom_col() +
geom_text(aes(label = num_filmes), hjust = -0.2, size = 4) +
coord_flip() +
labs(
title = "Top 5 Países por Quantidade de Filmes",
x = "País",
y = "Número de Filmes",
fill = "País"
) +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 14))
# Transformar em plotly
ggplotly(p, tooltip = "text") %>%
layout(
autosize = TRUE,
margin = list(l = 150, r = 50, t = 80, b = 50), # aumenta margens para labels e título
yaxis = list(tickformat = ","),
xaxis = list(tickangle = 0)
)# 1. Filmes únicos por país
filmes_por_pais_tabela <- lista_meses_combinados_tratados %>%
bind_rows() %>%
select(TITULO_BRASIL, PAIS_OBRA) %>%
distinct() %>%
group_by(PAIS_OBRA) %>%
summarise(
num_filmes = n(),
filmes = paste(TITULO_BRASIL, collapse = ", "),
.groups = "drop"
) %>%
arrange(desc(num_filmes))
# 2. Mostrar apenas top 5 países
filmes_por_pais_tabela_top5 <- filmes_por_pais_tabela %>%
slice_head(n = 5)
# 3. Visualizar
filmes_por_pais_tabela_top5## # A tibble: 5 × 3
## PAIS_OBRA num_filmes filmes
## <fct> <int> <chr>
## 1 BRASIL 358 "MAMONAS ASSASSINAS O FILME, MINHA IRMÃ E EU, O SEQ…
## 2 ESTADOS UNIDOS 268 "WONKA, PATOS!, AQUAMAN 2: O REINO PERDIDO, JOGOS V…
## 3 FRANÇA 63 "PARE COM SUAS MENTIRAS, SOFTIE, ALMAS GÊMEAS, NINA…
## 4 ALEMANHA 31 "FOLHAS DE OUTONO, OS TRÊS MOSQUETEIROS: MILADY, AF…
## 5 ESPANHA 20 "SAMSARA, A JORNADA DA ALMA, MEU AMIGO ROBÔ, AS BES…