O melhor filme do Tom Hanks

14 minuto(s) de leitura

No Episódio 606 do Podcast RapaduraCast, os participantes discutem e escolhem o melhor filme do Tom Hanks. Na conversa, eles opinam sobre os filmes que o Tom Hanks atua até chegarem em um consenso e elegerem o melhor filme. Mas a questão é: a escolha do Rapadura é a mesma que das avaliações do Internet Movie Database (IMDb)? Para responder a essa pergunta, vamos analisar os filmes que Tom Hanks participa como ator (em qualquer nível) com relação às informações do IMDb com o R.

Primeiramente, vamos carregar os pacotes do R que utilizaremos.

library(dplyr)          # transformar dados
library(readr)          # ler dados
library(magrittr)       # para operadores
library(stringr)        # manipular texto
library(purrr)          # criar funcionais
library(questionr)      # fazer tabela de frequência legal
library(forcats)        # lidar com variáveis categóricas
library(tidyr)          # tratar os dados
library(jsonlite)       # tratar os arquivos no formato JSON
library(glue)           # colar texto
library(plotly)         # fazer gráficos interativos
library(ggplot2)        # fazer gráficos

Para acessar aos dados do IMDb, vamos seguir alguns passos que Athos recomenda no post, ao obter uma API KEY no site OMDB.

Coloquei a chave obtida no arquivo .Renviron, ao inserir: omdb_chave = minha chave. Dessa forma, só preciso chamar no código Sys.getenv('omdb_chave').

readRenviron(".Renviron")
Sys.getenv('omdb_chave')

No vetor abaixo estão as IMDb IDs dos filmes que queremos analisar.

#imdb ids dos filmes que Tom Hanks atua
filmes_ids <- c('0080850', '0086927', '0088161', '0089543', '0090274', '0091019',
                '0091541', '0091653', '0092925', '0094737', '0095927', '0096734',
                '0098536', '0099165', '0099892', '0104694', '0105211', '0107818',
                '0108160', '0109830', '0112384', '0114709', '0117887', '0120815',
                '0128853', '0120363', '0120689', '0162222', '0257044', '0264464',
                '0335245', '0338348', '0362227', '0377057', '0317219', '0382625', 
                '0462538', '0472062', '0460810', '0808151', '0435761', '0477302',
                '1583420', '1371111', '1535109', '2140373', '3501590', '3682448',
                '2980210', '3062096', '3263904', '4287320', '6294822', '1979376',
                '3224458', '13143964', '6048922', '6878306')
              

Podemos observar que há 58 filmes. Também consideramos a função que o Athos apresenta para extrair as informações do ID como argumento.

#função para pegar as informações do filme identificado pelo argumento imdbid
pega_info_imdb <- function(imdbid) {
  glue("http://www.omdbapi.com/?apikey={Sys.getenv('omdb_chave')}&i=tt{imdbid}") %>%
    fromJSON() %>%
    as_tibble()
}

Agora vamos aplicar a função aos ids dos filmes do Tom Hanks e arrumar a base de dados.

#aplicar a função 'pega_info_imdb' aos ids
dados1 <- map(filmes_ids, pega_info_imdb)

#tirar os dados da lista
ai <- data.frame()
for (i in 1:58) {
  oi <- dados1[[i]]
  ai <- bind_rows(ai, oi)
}
str(ai)
## 'data.frame':	166 obs. of  25 variables:
## $ Title     : chr  "He Knows You're Alone" "He Knows You're Alone" "Bachelor Party" "Bachelor Party" ...
## $ Year      : chr  "1980" "1980" "1984" "1984" ...
## $ Rated     : chr  "R" "R" "R" "R" ...
## $ Released  : chr  "29 Aug 1980" "29 Aug 1980" "29 Jun 1984" "29 Jun 1984" ...
## $ Runtime   : chr  "94 min" "94 min" "105 min" "105 min" ...
## $ Genre     : chr  "Horror, Thriller" "Horror, Thriller" "Comedy" "Comedy" ...
## $ Director  : chr  "Armand Mastroianni" "Armand Mastroianni" "Neal Israel" "Neal Israel" ...
## $ Writer    : chr  "Scott Parker" "Scott Parker" "Bob Israel (story), Neal Israel (screenplay), Pat Proft (screenplay)" "Bob Israel (story), Neal Israel (screenplay), Pat Proft (screenplay)" ...
## $ Actors    : chr  "Don Scardino, Caitlin O'Heaney, Elizabeth Kemp, Tom Rolfing" "Don Scardino, Caitlin O'Heaney, Elizabeth Kemp, Tom Rolfing" "Tom Hanks, Tawny Kitaen, Adrian Zmed, George Grizzard" "Tom Hanks, Tawny Kitaen, Adrian Zmed, George Grizzard" ...
## $ Plot      : chr  "A young bride-to-be is being stalked upon by a serial killer in Staten Island. She gets help from a former love"| __truncated__ "A young bride-to-be is being stalked upon by a serial killer in Staten Island. She gets help from a former love"| __truncated__ "A soon-to-be-married man's friends throw him the ultimate bachelor party." "A soon-to-be-married man's friends throw him the ultimate bachelor party." ...
## $ Language  : chr  "English" "English" "English, Japanese" "English, Japanese" ...
## $ Country   : chr  "USA" "USA" "USA" "USA" ...
## $ Awards    : chr  "N/A" "N/A" "N/A" "N/A" ...
## $ Poster    : chr  "https://m.media-amazon.com/images/M/MV5BZGNlYjk3NmMtNTVlNS00ODg5LWExNmYtNmUyNWZmZTA2MDk4XkEyXkFqcGdeQXVyMTQxNzM"| __truncated__ "https://m.media-amazon.com/images/M/MV5BZGNlYjk3NmMtNTVlNS00ODg5LWExNmYtNmUyNWZmZTA2MDk4XkEyXkFqcGdeQXVyMTQxNzM"| __truncated__ "https://m.media-amazon.com/images/M/MV5BYjgxOWYxMGQtMTc4MC00MzdmLWI0NTgtYzc1NzFiMGU4MWRjXkEyXkFqcGdeQXVyMzYxMzc"| __truncated__ "https://m.media-amazon.com/images/M/MV5BYjgxOWYxMGQtMTc4MC00MzdmLWI0NTgtYzc1NzFiMGU4MWRjXkEyXkFqcGdeQXVyMzYxMzc"| __truncated__ ...
## $ Ratings   :'data.frame':	166 obs. of  2 variables:
##  ..$ Source: chr  "Internet Movie Database" "Rotten Tomatoes" "Internet Movie Database" "Rotten Tomatoes" ...
##  ..$ Value : chr  "5.1/10" "22%" "6.3/10" "54%" ...
## $ Metascore : chr  "N/A" "N/A" "56" "56" ...
## $ imdbRating: chr  "5.1" "5.1" "6.3" "6.3" ...
## $ imdbVotes : chr  "3,209" "3,209" "35,766" "35,766" ...
## $ imdbID    : chr  "tt0080850" "tt0080850" "tt0086927" "tt0086927" ...
## $ Type      : chr  "movie" "movie" "movie" "movie" ...
## $ DVD       : chr  "01 Jan 2009" "01 Jan 2009" "01 Jul 2017" "01 Jul 2017" ...
## $ BoxOffice : chr  "$4,875,436" "$4,875,436" "$38,435,947" "$38,435,947" ...
## $ Production: chr  "Metro-Goldwyn-Mayer" "Metro-Goldwyn-Mayer" "Aspect Ratio Film" "Aspect Ratio Film" ...
## $ Website   : chr  "N/A" "N/A" "N/A" "N/A" ...
## $ Response  : chr  "True" "True" "True" "True" ...

Veja que todas as variáveis foram lidas como character. A seguir são arrumadas as variáveis quantitativas que vamos analisar: ‘imdbRating_num’ é a nota do filme, ‘ano’ é o ano do filme e ‘num_votos’ é o número de votos recebidos.

#arrumar as variáveis quntitativas que estão como texto
dados <- ai %>% 
  mutate(imdbRating_num = imdbRating %>% parse_number(), 
         ano = Year %>% parse_number(), 
         num_votos = imdbVotes %>% parse_number()
  )

Vamos ver as variáveis contidas na base de dados:

names(dados)
## [1] "Title"          "Year"          
## [3] "Rated"          "Released"      
## [5] "Runtime"        "Genre"         
## [7] "Director"       "Writer"        
## [9] "Actors"         "Plot"          
## [11] "Language"       "Country"       
## [13] "Awards"         "Poster"        
## [15] "Ratings"        "Metascore"     
## [17] "imdbRating"     "imdbVotes"     
## [19] "imdbID"         "Type"          
## [21] "DVD"            "BoxOffice"     
## [23] "Production"     "Website"       
## [25] "Response"       "imdbRating_num"
## [27] "ano"            "num_votos"  
dim(dados)
 ## [1] 166  28

Note que há 166 observações na base. Isso acontece porque para 54 deles há avaliações da Metacritic e da Rotten Tomatoes, além do IMDb.

dados %>% 
  group_by(Ratings[,1]) %>% 
  summarise(n = n())
# # A tibble: 3 x 2
#   `Ratings[, 1]`              n
#   <chr>                   <int>
# 1 Internet Movie Database    58
# 2 Metacritic                 54
# 3 Rotten Tomatoes            54

Vamos selecionar só as avaliações de IMDb:

#só avaliações do IMDb
dados_imdb <- dados %>% 
  filter(Ratings[,1] == 'Internet Movie Database')

Na coluna “Genre” consta os gêneros do filme em questão.

#gênero do filme
head(dados_imdb$Genre)
  ##    [1] "Horror, Thriller"        
  ##    [2] "Comedy"                  
  ##    [3] "Comedy, Fantasy, Romance"
  ##    [4] "Comedy, Thriller"        
  ##    [5] "Adventure, Comedy"       
  ##    [6] "Drama, Romance, War"  

Como todos os gêneros estão na mesma coluna, precisamos usar um código para verificar se o gênero de interesse está contido na coluna. São os gêneros de interesse aqui: ação, aventura. criminal, drama, mistério, suspense, histórico, biográfico, fantasia, comédia, animação, sci-fi, romance e musical.

#identificar os gêneros de interesse
dados_imdb <- dados_imdb %>% 
  mutate(
    genero_acao = case_when(
      str_detect(Genre, "Action") ~ "sim",
      TRUE ~ "não"
    ), 
    genero_aventura = case_when(
      str_detect(Genre, "Adventure") ~ "sim",
      TRUE ~ "não"
    ),
    genero_crime = case_when(
      str_detect(Genre, "Crime") ~ "sim",
      TRUE ~ "não"
    ), 
    genero_drama = case_when(
      str_detect(Genre, "Drama") ~ "sim",
      TRUE ~ "não"
    ), 
    genero_misterio = case_when(
      str_detect(Genre, "Mystery") ~ "sim",
      TRUE ~ "não"
    ), 
    genero_suspense = case_when(
      str_detect(Genre, "Thriller") ~ "sim",
      TRUE ~ "não"
    ), 
    genero_historico = case_when(
      str_detect(Genre, "History") ~ "sim",
      TRUE ~ "não"
    ), 
    genero_biografico = case_when(
      str_detect(Genre, "Biography") ~ "sim",
      TRUE ~ "não"
    ), 
    genero_fantasia = case_when(
      str_detect(Genre, "Fantasy") ~ "sim",
      TRUE ~ "não"
    ), 
    genero_comedia = case_when(
      str_detect(Genre, "Comedy") ~ "sim",
      TRUE ~ "não"
    ),  
    genero_animacao = case_when(
      str_detect(Genre, "Animation") ~ "sim",
      TRUE ~ "não"
    ),    
    genero_scifi = case_when(
      str_detect(Genre, "Sci-Fi") ~ "sim",
      TRUE ~ "não"
    ),   
    genero_romance = case_when(
      str_detect(Genre, "Romance") ~ "sim",
      TRUE ~ "não"
    ),   
    genero_musical = case_when(
      str_detect(Genre, "Musical") ~ "sim",
      TRUE ~ "não"
    )
)
#frequência dos gêneros dos filmes
dados_imdb %>%
  summarise(
    acao = sum(genero_acao == "sim"),
    aventura = sum(genero_aventura == "sim"),
    drama = sum(genero_drama == "sim"),
    misterio = sum(genero_misterio == "sim"),
    suspense = sum(genero_suspense == "sim"),
    historico = sum(genero_historico == "sim"),
    biografico = sum(genero_biografico == "sim"),
    fantasia = sum(genero_fantasia == "sim"),
    comedia = sum(genero_comedia == "sim"),
    animacao = sum(genero_animacao == "sim"),
    scifi = sum(genero_scifi == "sim"),
    romance = sum(genero_romance == "sim"),
    musical = sum(genero_musical == "sim")
  )
 ##  acao aventura drama misterio suspense historico biografico fantasia comedia animacao scifi
##    5       14    37        7       12         4          6        8      33        7     2
##  romance musical
##     14       1

Dentre os gêneros considerados, aquele que o Tom Hanks mais atuou foi em drama, seguido de perto por comédia.

A variável “Awards” indica os prêmios e/ou indicações dos filmes.

#prêmios e indicações do filme
freq(dados_imdb$Awards)
##    n
## 1 nomination.                                                   4
## 1 win & 1 nomination.                                           1
## 1 win & 2 nominations.                                          1
## 1 win & 5 nominations.                                          2
## 1 win.                                                          1
## 2 nominations.                                                  1
## 2 wins & 3 nominations.                                         1
## 3 nominations.                                                  1
## 3 wins & 1 nomination.                                          1
## 4 wins & 1 nomination.                                          1
## 6 wins & 4 nominations.                                         1
## 7 wins & 8 nominations.                                         1
## N/A                                                             8
## Nominated for 1 Golden Globe. Another 15 wins & 78 nominations. 1
## Nominated for 1 Golden Globe. Another 5 wins & 33 nominations.  1
## .
## .
## .

Vamos então criar a variável de premiação, com as categorias: nenhum, oscar, BAFTA/Golden Globe, nomeado ao Oscar/BAFTA/Golden Globe, outros prêmios e nomeado a outros prêmios.

#criando a variável de premiação
dados_imdb <- dados_imdb %>%
  mutate(
    premiacao = case_when(
      str_detect(Awards, "N/A") | is.na(Awards) ~ "nenhum",
      str_detect(Awards, "Won.*Oscar") ~ "oscar",
      str_detect(Awards, "Won.*(BAFTA|Golden Globe)") ~ "BAFTA/Golden Globe",
      str_detect(Awards, "Nominated") ~ "nomeado ao Oscar/BAFTA/Golden Globe",
      str_detect(Awards, "win") ~ "outros prêmios",
      str_detect(Awards, "nomination") ~ "nomeado a outros prêmios",
      TRUE ~ "outro"
    )
  )

#tabela de frequência para premiacao
freq(dados_imdb$premiacao, total = TRUE)
##                                    n     %  val%
## nenhum                               8  13.8  13.8
## nomeado a outros prêmios             6  10.3  10.3
## nomeado ao Oscar/BAFTA/Golden Globe 26  44.8  44.8
## oscar                                8  13.8  13.8
## outros prêmios                      10  17.2  17.2
## Total                               58 100.0 100.0

Veja que as categorias são ordenadas por ordem alfabética. Vamos reordenar as categorias: oscar, outros prêmios, nomeado ao Oscar/BAFTA/Golden Globe, nomeado a outros prêmios, nenhum.

#arrumar a ordem das categorias usando a função lvls_reorder do forcats
dados_imdb <- dados_imdb %>%  
   mutate(premiacao = as.factor(premiacao), 
   premiacao = lvls_reorder(dados_imdb$premiacao, c(4, 5, 3, 2, 1))
   )

#tabela de frequência para premiacao
freq(dados_imdb$premiacao, total = TRUE)
##                                   n     %  val%
## oscar                                8  13.8  13.8
## outros prêmios                      10  17.2  17.2
## nomeado ao Oscar/BAFTA/Golden Globe 26  44.8  44.8
## nomeado a outros prêmios             6  10.3  10.3
## nenhum                               8  13.8  13.8
## Total                               58 100.0 100.0

Uma curiosidade seria ver quais os filmes ganharam o Oscar.

#identificar os filmes vencedores do Oscar
dados_imdb %>% filter(premiacao == "oscar") %>% 
    select(Title, Year, Genre)
##                Title Year                                         Genre
## 1        Philadelphia 1993                                         Drama
## 2        Forrest Gump 1994                                Drama, Romance
## 3           Apollo 13 1995                     Adventure, Drama, History
## 4 Saving Private Ryan 1998                                    Drama, War
## 5   Road to Perdition 2002                        Crime, Drama, Thriller
## 6         Toy Story 3 2010 Animation, Adventure, Comedy, Family, Fantasy
## 7     Bridge of Spies 2015                      Drama, History, Thriller
## 8         Toy Story 4 2019 Animation, Adventure, Comedy, Family, Fantasy

Em “Philadelphia”, de 1993, Hanks ganhou o oscar de melhor ator, enquanto a música “Streets of Philadelphia”, de Bruce Springsteen, ganhou o oscar de melhor canção original. “Forrest Gump” ganhou o oscar de melhor filme, melhor diretor, melhor ator para Tom Hanks, melhor roteiro adaptado, melhores efeitos visuais e melhor edição. O filme “Apollo 13” (de 1995) ganhou o oscar de melhor edição e melhor som. O filme “O Resgate do Soldado Ryan” (Saving Private Ryan) ganhou o oscar de melhor diretor, melhor fotografia, melhor edição, melhor edição de som e melhor mixagem de som.

O filme “Estrada para Perdição” (Road to Perdition) ganhou o oscar de melhor fotografia. “Toy Story 3” ganhou o oscar de melhor filme de animação e melhor canção original e o “Toy Story 4” ganhou o oscar de melhor animação. O filme “Ponte dos Espiões” (Bridge of Spies), de 2015, levou o oscar de melhor ator coadjuvante.

Agora chegou a hora de ver as medidas descritivas das notas dos filmes.

# descritivas das notas
dados_imdb %>%
  summarise(min = min(imdbRating_num),
            mediana = median(imdbRating_num), 
            media = mean(imdbRating_num), 
            max = max(imdbRating_num),
            dp = sd(imdbRating_num)
  )
##  min mediana    media max        dp
##  5.1     6.9   6.862   8.8   0.905

Podemos observar que a nota média é de 6.87 e que o filme com maior avaliação teve nota 8.8 e o filme com a menor obteve 5.1. Mais adiante vamos identificar esses filmes.

Há uma variável de duração do filme (“Runtime”).

head(dados_imdb$Runtime)
## [1] "94 min"  "105 min" "111 min" "92 min"  "107 min" "98 min" 

Note que há texto no campo da variável. Vamos usar a função extract_numeric do pacote tidyr para retornar apenas o número:

# criando a variável de duração do filme
dados_imdb <- dados_imdb %>% 
    mutate(duracao = Runtime %>%  extract_numeric()
    )
head(dados_imdb$duracao)
## [1]  94 105 111  92 107  98
# descritivas da duracao
dados_imdb %>%
  summarise(min = min(duracao),
            mediana = median(duracao), 
            media = mean(duracao), 
            max = max(duracao),
            dp = sd(duracao)
  )
## min mediana    media max       dp
##  81   108.5  114.67  189   22.27

Vamos considerar um filme longo se este tem mais de 2 horas e vamos criar a variável indicadora de filme longo:

dados_imdb <- dados_imdb %>%
         mutate(duracao_mais_2h = ifelse(duracao >= 120, 
                                         ">2 horas", "<2 horas"
                                         )
               )
#tabela de frequência para duracao_mais_2h
freq(dados_imdb$duracao_mais_2h, total = TRUE)
    ##         n     %  val%
    ##   <2 horas 39  67.2  67.2
    ##   >2 horas 19  32.8  32.8
    ##   Total    58 100.0 100.0

Aproximadamente 33\% dos filmes tem pelo menos 2 horas de duração.

Agora vamos ver a distribuição dos filmes por ano e também ver em quantos filmes ele atuou em média:

dados_imdb %>% 
   group_by(ano) %>% 
   count() %>% 
   ungroup() %>% 
   summarise(media = mean(n)) 
  ## A tibble: 1 x 1
  ##  media
  ##  <dbl>
  ##   1.87
dados_imdb %>% 
   group_by(ano) %>% 
   count() %>% 
   ungroup() %>% 
   ggplot(aes(x = ano, y = n)) +
  geom_col(color = 'black') +
  scale_x_continuous(breaks = 1980:2020) +
  labs(x = "Ano", y = "Número de filmes") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

Em média, Tom Hanks atua em 1.87 filmes por ano. Pelo gráfico acima, o ano de 2004 foi o ano que mais saiu filme com atuação do Hanks (4 filmes). Além disso, nos anos de 81, 82, 83, 91, 97, 2001, 2003, 2005, 2014 e 2018 não foram lançados filmes do ator.

Ao considerar a variável de maior interesse desse post, a nota do IMDb do filme, vamos fazer um gráfico de dispersão dessa variável com o número de votos, com as cores dos pontos identificando a premiação recebida pelo filme. Faremos esse gráfico interativo por meio do pacote Plotly para que o leitor consiga identificar o filme que cada ponto representa e também fazer zoom in e zoom out se assim desejar.

f <- list(
  size = 16,
  color = "black"
)

x <- list(
  title = "Número de votos",
  titlefont = f
)

y <- list(
  title = "Nota do IMDb",
  titlefont = f
)

fig <- plot_ly(dados_imdb, x = ~num_votos, y = ~imdbRating_num, text = ~Title, type = 'scatter', mode = 'markers', color = ~premiacao, colors = 'Paired',
               sizes = c(10, 50),
               marker = list(opacity = 0.5, sizemode = 'diameter'))

fig <- fig %>% layout(
    showlegend = FALSE
         )
         
fig <- fig %>% layout(xaxis = x, yaxis = y)

fig

 

 

 

 

 

 

 

 

 

Nesse momento vamos responder à pergunta que motivou esse post: dentre os filmes que Tom Hanks atua, qual apresenta a maior nota no IMDb?

# filme com maior nota no IMDb
dados_imdb %>%
  filter(imdbRating_num == max(imdbRating_num)) %>% 
  select(Title, ano, Runtime, Genre, imdbRating_num)
##          Title  ano Runtime          Genre imdbRating_num
## 1 Forrest Gump 1994 142 min Drama, Romance            8.8

Pela saída acima e o gráfico anterior, descobrimos que é “Forrest Gump”.

E o filme com a menor nota:

# filme com menor nota no IMDb
dados_imdb %>%
  filter(imdbRating_num == min(imdbRating_num)) %>% 
  select(Title, ano, Runtime, Genre, imdbRating_num)
 ##             Title  ano Runtime            Genre imdbRating_num
 ## 1 He Knows You're Alone 1980  94 min Horror, Thriller            5.1

O filme com a menor nota é “Trilha dos Corpos”” (He Knows You’re Alone) de 1980, o primeiro trabalho de Tom Hanks no cinema. Já o filme com maior número de votantes é:

# filme com maior número de votos no IMDb
dados_imdb %>%
  filter(num_votos == max(num_votos)) %>% 
  select(Title, ano, Runtime, Genre, imdbRating_num, num_votos)
##         Title  ano Runtime          Genre imdbRating_num num_votos
## 1 Forrest Gump 1994 142 min Drama, Romance            8.8   1826575

E o número com o menor número de votos é:

# filme com menor número de votos no IMDb
dados_imdb %>%
  filter(num_votos == min(num_votos)) %>% 
  select(Title, ano, Runtime, Genre, imdbRating_num, num_votos)
##                   Title  ano Runtime               Genre imdbRating_num num_votos
## 1 Every Time We Say Goodbye 1986  98 min Drama, Romance, War            5.9      2221

Já o filme com menor engajamento é “É Preciso Dizer Adeus” (Every Time We Say Goodbye), de 1986.

“Forrest Gump” é o filme com maior número de votos e também o filme com maior nota no IMDb do Tom Hanks. Esse é também o filme vencedor na votação do RapaduraCast e é também um dos meus filmes favoritos. =)

Nesse post exploramos os dados do IMDb com o R para analisar alguns números dos filmes que Tom Hanks atua. Espero que ele tenha motivado você a usar o R para responder curiosidades de seu interesse.

Atualizado em: