1. Introdução

Este relatório analisa o conjunto de dados Rotten Tomatoes Movies and Reviews (Kaggle) para responder:

Top Critics são mais rigorosos do que os demais críticos?

A análise combina mais de 1 milhão de críticas. Avaliamos: - proporção de críticas “Fresh”/“Rotten” - diferenças por gênero - tendências temporais (com filtragem para anos válidos)


2. Importação e Preparação dos Dados

movies_raw  <- read_csv("dataset/rotten_tomatoes_movies.csv")
reviews_raw <- read_csv("dataset/rotten_tomatoes_critic_reviews.csv")

movies  <- movies_raw %>% clean_names()
reviews <- reviews_raw %>% clean_names()

3. Seleção e Limpeza

movies_sel <- movies %>%
  select(rotten_tomatoes_link, movie_title, genres, content_rating, original_release_date) %>%
  mutate(original_release_date = ymd(original_release_date),
         release_year = year(original_release_date))

reviews_sel <- reviews %>%
  select(rotten_tomatoes_link, critic_name, top_critic, publisher_name,
         review_type, review_score, review_date, review_content) %>%
  mutate(review_date = ymd(review_date),
         review_year = year(review_date),
         top_critic = as.factor(top_critic),
         review_type = as.factor(review_type))

4. Dataset Final Integrado

dados <- reviews_sel %>%
  inner_join(movies_sel, by = "rotten_tomatoes_link")

glimpse(dados)
## Rows: 1,129,887
## Columns: 14
## $ rotten_tomatoes_link  <chr> "m/0814255", "m/0814255", "m/0814255", "m/081425…
## $ critic_name           <chr> "Andrew L. Urban", "Louise Keller", NA, "Ben McE…
## $ top_critic            <fct> FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, T…
## $ publisher_name        <chr> "Urban Cinefile", "Urban Cinefile", "FILMINK (Au…
## $ review_type           <fct> Fresh, Fresh, Fresh, Fresh, Rotten, Rotten, Rott…
## $ review_score          <chr> NA, NA, NA, "3.5/5", NA, NA, "1/4", "3.5/5", "B"…
## $ review_date           <date> 2010-02-06, 2010-02-06, 2010-02-09, 2010-02-09,…
## $ review_content        <chr> "A fantasy adventure that fuses Greek mythology …
## $ review_year           <dbl> 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, …
## $ movie_title           <chr> "Percy Jackson & the Olympians: The Lightning Th…
## $ genres                <chr> "Action & Adventure, Comedy, Drama, Science Fict…
## $ content_rating        <chr> "PG", "PG", "PG", "PG", "PG", "PG", "PG", "PG", …
## $ original_release_date <date> 2010-02-12, 2010-02-12, 2010-02-12, 2010-02-12,…
## $ release_year          <dbl> 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, …

5. Resultados

5.1 Fresh vs Rotten por Tipo de Crítico

prop_tipo_critica <- dados %>%
  count(top_critic, review_type) %>%
  group_by(top_critic) %>%
  mutate(prop = n / sum(n))

kable(prop_tipo_critica)
top_critic review_type n prop
FALSE Fresh 549814 0.6534638
FALSE Rotten 291570 0.3465362
TRUE Fresh 170299 0.5902850
TRUE Rotten 118204 0.4097150
ggplot(prop_tipo_critica, aes(x = top_critic, y = prop, fill = review_type)) +
  geom_col(position = "fill") +
  scale_y_continuous(labels = percent_format()) +
  labs(title = "Proporção Fresh/Rotten por Tipo de Crítico") +
  theme_minimal()


6. Análise por Gênero

dados_generos <- dados %>%
  filter(!is.na(genres)) %>%
  separate_rows(genres, sep = ",") %>%
  mutate(genres = str_trim(genres))

top_generos <- dados_generos %>% count(genres, sort = TRUE)
kable(head(top_generos, 15))
genres n
Drama 638038
Comedy 370743
Action & Adventure 296654
Mystery & Suspense 240766
Science Fiction & Fantasy 176166
Romance 120400
Art House & International 111180
Horror 107823
Kids & Family 82570
Documentary 77818
Animation 56199
Special Interest 48833
Musical & Performing Arts 47259
Classics 41673
Western 12278

6 Gêneros Mais Frequentes

generos_foco <- top_generos %>% slice_max(n, n = 6) %>% pull(genres)

prop_genero_topcritic <- dados_generos %>%
  filter(genres %in% generos_foco) %>%
  count(genres, top_critic, review_type) %>%
  group_by(genres, top_critic) %>%
  mutate(prop = n / sum(n))

kable(prop_genero_topcritic)
genres top_critic review_type n prop
Action & Adventure FALSE Fresh 139384 0.6040110
Action & Adventure FALSE Rotten 91380 0.3959890
Action & Adventure TRUE Fresh 34117 0.5177872
Action & Adventure TRUE Rotten 31773 0.4822128
Comedy FALSE Fresh 165946 0.6071780
Comedy FALSE Rotten 107361 0.3928220
Comedy TRUE Fresh 51958 0.5332526
Comedy TRUE Rotten 45478 0.4667474
Drama FALSE Fresh 322935 0.6848735
Drama FALSE Rotten 148590 0.3151265
Drama TRUE Fresh 102348 0.6146547
Drama TRUE Rotten 64165 0.3853453
Mystery & Suspense FALSE Fresh 112681 0.6147321
Mystery & Suspense FALSE Rotten 70620 0.3852679
Mystery & Suspense TRUE Fresh 30524 0.5311755
Mystery & Suspense TRUE Rotten 26941 0.4688245
Romance FALSE Fresh 54972 0.6217427
Romance FALSE Rotten 33444 0.3782573
Romance TRUE Fresh 17505 0.5473049
Romance TRUE Rotten 14479 0.4526951
Science Fiction & Fantasy FALSE Fresh 88498 0.6334996
Science Fiction & Fantasy FALSE Rotten 51199 0.3665004
Science Fiction & Fantasy TRUE Fresh 19815 0.5433382
Science Fiction & Fantasy TRUE Rotten 16654 0.4566618
ggplot(prop_genero_topcritic, aes(x = review_type, y = prop, fill = top_critic)) +
  geom_col(position = "dodge") +
  facet_wrap(~ genres) +
  scale_y_continuous(labels = percent_format()) +
  labs(title = "Proporção Fresh/Rotten por Gênero") +
  theme_minimal()


7. Análise Temporal (Filtrada)

⚠ O dataset contém datas inválidas (ex.: ano 1800).
Aplicamos um filtro para anos ≥ 1980, período em que o volume de críticas é consistente.

prop_ano <- dados %>%
  filter(review_year >= 1980,
         !is.na(review_type),
         !is.na(top_critic)) %>%
  mutate(review_type_bin = if_else(review_type == "Fresh", 1, 0)) %>%
  group_by(review_year, top_critic) %>%
  summarise(
    n = n(),
    prop_fresh = mean(review_type_bin, na.rm = TRUE),
    .groups = "drop"
  )

kable(head(prop_ano, 20))
review_year top_critic n prop_fresh
1980 FALSE 4 1.0000000
1980 TRUE 1 1.0000000
1981 FALSE 11 0.8181818
1981 TRUE 1 1.0000000
1982 FALSE 2 1.0000000
1982 TRUE 2 0.5000000
1983 FALSE 4 0.7500000
1984 FALSE 6 0.8333333
1984 TRUE 3 0.3333333
1985 FALSE 10 0.9000000
1985 TRUE 3 1.0000000
1986 FALSE 5 1.0000000
1986 TRUE 3 1.0000000
1987 FALSE 4 1.0000000
1987 TRUE 3 0.3333333
1988 FALSE 1 0.0000000
1988 TRUE 13 0.4615385
1989 FALSE 3 1.0000000
1989 TRUE 16 0.5000000
1990 FALSE 4 0.7500000
ggplot(prop_ano, aes(x = review_year, y = prop_fresh, color = top_critic)) +
  geom_line() + geom_point() +
  scale_y_continuous(labels = percent_format()) +
  labs(title = "Evolução Temporal das Críticas Fresh (>=1980)") +
  theme_minimal()


8. Conclusões

Os resultados mostram de forma consistente que:

Top Critics são mais rigorosos do que os demais críticos

  • Não-Top Critics aprovam ~65% dos filmes.
  • Top Critics aprovam ~59%.

Essa diferença ocorre em todos os gêneros mais populares, com destaque para: - Drama: maior rigor dos Top Critics. - Action & Adventure e Sci-Fi: diferença menor, mas presente.

✔ Rigor consistente entre gêneros

Independentemente do gênero, Top Critics sempre apresentam: - menos críticas “Fresh” - mais críticas “Rotten”

✔ Sobre a análise temporal

Após filtrar anos inválidos, observa-se: - estabilidade nas proporções ao longo do tempo
- Top Critics seguem sendo mais rigorosos em toda a série histórica recente

✔ Conclusão geral

Sim, Top Critics são de fato mais exigentes do que os demais críticos.
Eles distribuem menos classificações positivas e isso ocorre em praticamente todos os gêneros.


9. Referências

  • Kaggle — Rotten Tomatoes Movies and Reviews Dataset
  • Rotten Tomatoes — Glossário de métricas oficiais