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)
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()
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))
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, …
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()
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 |
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()
⚠ 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()
Os resultados mostram de forma consistente que:
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.
Independentemente do gênero, Top Critics sempre apresentam: - menos críticas “Fresh” - mais críticas “Rotten”
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
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.