Para meu projeto final, irei fazer uma análise dos 10.000 filmes de longa-metragem mais votados do IMDB, com o objetivo de constriuir uma história narrativa em cima das informações por mim extraidas de tais dados. Abaixo estão os diferentes elementos do projeto divididos em cada aba.
Neste trabalho, serão analisadas informações do dataset “IMDB 10,000 Most Voted Feature Films”, obtido do IMDb, sigla que significa Base de Dados de Filmes da Internet (em Inglês: Internet Movie Database), um dos mais respeitados sites de crítica popular de Filmes e Séries do mundo. Junto a uma curta sinopse, cada página dedicada exclusivamente a um único filme comporta uma enquete onde membros do IMDb podem votar na nota, ou rating, de 1 a 10 do filme. A nota final é determinada por uma série de equações e estatísticas que previnem que um indivíduo ou grupo possam alterá-la injustamente.
Por tanto, trata-se de uma base completa e confiável, que recebe o acesso e participação de milhares de usuários, tanto em busca de informações a respeito dos filmes, como também para contribuir com suas avaliações críticas individuais. De posse desses dados, pode ser realizada a sumarização, síntese e novas análises relevantes direcionadas aos entusiastas da sétima arte.
Pretende-se obter e demostrar inicialmente informações, como: quantidade de filmes mais ou menos votados, bem ou mal avaliados, filtrando-os de acordo com o ano, gênero, receita, pontuação e diretor; a fim de se obter diversas informações e insights interessantes a respeito dessa massa de dados.
Para este projeto, a maioria dos pacotes usados são os padrões para organizar, manipular, analisar e exibir dados em bom formato.
## Carregar Pacotes Requeridos ##
library(stringr) ## Manipulando string
library(DT) ## Dados de saída em bom formato
Para este trabalho, os dados foram originalmente obtidos em Kaggle, a maior plataforma de hospedagem para projetos e competições de Data Science que existe atualmente. Originalmente e segundo a sua descrição, o dataset “IMDB 10,000 Most Voted Feature Films” foi retirado do próprio site IMDB, para ser usado para qualquer fim trivial, como: encontrar filmes para assistir procurando uma palavra-chave na descrição e filtrando a partir de todas as variáveis disponíveis, dentre elas o ano, gênero, receita, duração, pontuação e diretor; o objetivo desse dataset foi reunir um conjunto de dados mais atualizado na época e com mais metascores presentes. Os dados foram disponibilizados na plataforma em 04/11/18.
Para iniciar a extração e preparação de dados, comecei carregando o dataset “movies” do meu diretório de trabalho e fiz uma análise visual e estrutural das informações gerais.
# Dataset carregado
movies <- read.csv("movies.csv")
# Analise das informaçoes gerais do dataset View(movies) summary(movies)
Foi constatado que era preciso remover muitos NAs existentes nas colunas Metascore, Director e Revenue. Os NAs foram substituidos por 0 para valores numéricos e "" para as strings.
# Remover NAs existentes das colunas Metascore, Director e Revenue
na_metascore <- which(is.na(movies$Metascore))
na_director <- which(is.na(movies$Director))
na_revenue <- which(is.na(movies$Revenue))
for (data in na_metascore) {
movies[data, "Metascore"] <- 0
}
for (data in na_director) {
movies[data, "Director"] <- ""
}
for (data in na_revenue) {
movies[data, "Revenue"] <- 0
}
Originalmente, o dataset apresentava as colunas: Rank (posição de acordo com o número de votos, em ordem decrescente), Title (título do filme), Year (ano de lançamento), Score (pontuação popular), Metascore (pontuação da crítica especializada), Genre (gênero(s) do filme), Vote (nº de votos), Director (diretor do filme), Runtime (duração), Revenue (receita) e Description (descrição do filme).
# Visualizando
view <- movies[1,]
datatable(view, options = list(scrollX = TRUE))
Foi observado que a coluna Genre era composta por uma string que poderia descrever de um a três gêneros presentes em cada filme. Portanto, para uma análise mais precisa, foi necessário realizar a separação das informações da coluna gênero usando uma matriz de separação de gênero. O processo de separação está descrito nos comentários do código abaixo.
# Realizar separação da coluna de gênero
generos <- movies$Genre
# Retira vigulas
generos <- gsub(",", "", generos)
# Cria matriz de separação de generos
gen_matrix <- matrix("",10000,3)
# Organiza matriz de separação de gêneros
l <- 1
while(l <= nrow(gen_matrix))
{
num_gen <- length(str_split(generos[l], " ", simplify = TRUE))
if(num_gen == 1)
{
linha <- str_split(generos[l], " ", simplify = TRUE)
coluna2 <-c("")
coluna3 <-c("")
linha=cbind(linha, coluna2)
linha=cbind(linha, coluna3)
}
else if(num_gen == 2)
{
linha <- str_split(generos[l], " ", simplify = TRUE)
coluna3 <-c("")
linha=cbind(linha, coluna3)
}
else
{
linha <- str_split(generos[l], " ", simplify = TRUE)
}
c <- 1
while(c <= ncol(gen_matrix)){
gen_matrix[l, c] <- linha[, c]
c <- c + 1
}
l <- l + 1
}
Dessa maneira, foram criadas as colunas Genre_2 e Genre_3, para que fosse possívei distribuir os gêneros dos filmes para facilitar as análises. Depois as colunas foram reordenadas.
# Criando novas colunas de genero
movies$Genre <- gen_matrix[, 1]
movies$Genre_2 <- gen_matrix[, 2]
movies$Genre_3 <- gen_matrix[, 3]
# Reordenado as colunas
movies <- movies[, c(1, 2, 3, 4, 5, 6, 12, 13, 7, 8, 9, 10, 11)]
No final do processo de preparação, o dataset que será explorado ficou com a seguinte estrutura:
# Exibindo dataset que será analisado
datatable(movies, caption = "Tabela 1: Movies Data Set", options = list(scrollX = TRUE))
Toda análise foi feita usando gráficos tradicionais do R. Para começa-la, busquei observar quais tipos de gêneros individuais existiam nas respectiva variáveis Genre, Genre_2 e Genre_3. Foram identificados 20 gêneros no total.
# Observo quais e quantos gêneros individuais existem nas colunas summary.factor(movies$Genre) summary.factor(movies$Genre_2) summary.factor(movies$Genre_3)
Em seguida, criei subsets para reunir todos os filmes que continham a presença individual de cada gênero. Um conjunto de filmes para cada instância de gênero. Depois, para cada instância, reuni as informações da totalidade dos votos e receitas (Milhões de dólares).
# Crio subsets para presença individual de cada gênero
action <- subset(movies, movies$Genre == "Action" | movies$Genre_2 == "Action" | movies$Genre_3 == "Action")
drama <- subset(movies, movies$Genre == "Drama" | movies$Genre_2 == "Drama" | movies$Genre_3 == "Drama")
romance <- subset(movies, movies$Genre == "Romance" | movies$Genre_2 == "Romance" | movies$Genre_3 == "Romance")
scifi <- subset(movies, movies$Genre == "Sci-Fi" | movies$Genre_2 == "Sci-Fi" | movies$Genre_3 == "Sci-Fi")
crime <- subset(movies, movies$Genre == "Crime" | movies$Genre_2 == "Crime" | movies$Genre_3 == "Crime")
fantasy <- subset(movies, movies$Genre == "Fantasy" | movies$Genre_2 == "Fantasy" | movies$Genre_3 == "Fantasy")
mystery <- subset(movies, movies$Genre == "Mystery" | movies$Genre_2 == "Mystery" | movies$Genre_3 == "Mystery")
adventure <- subset(movies, movies$Genre == "Adventure" | movies$Genre_2 == "Adventure" | movies$Genre_3 == "Adventure")
thriller <- subset(movies, movies$Genre == "Thriller" | movies$Genre_2 == "Thriller" | movies$Genre_3 == "Thriller")
biography <- subset(movies, movies$Genre == "Biography" | movies$Genre_2 == "Biography" | movies$Genre_3 == "Biography")
horror <- subset(movies, movies$Genre == "Horror" | movies$Genre_2 == "Horror" | movies$Genre_3 == "Horror")
filmnoir <- subset(movies, movies$Genre == "FilmNoir" | movies$Genre_2 == "FilmNoir" | movies$Genre_3 == "FilmNoir")
animation <- subset(movies, movies$Genre == "Animation" | movies$Genre_2 == "Animation" | movies$Genre_3 == "Animation")
music <- subset(movies, movies$Genre == "Music" | movies$Genre_2 == "Music" | movies$Genre_3 == "Music")
musical<- subset(movies, movies$Genre == "Musical" | movies$Genre_2 == "Musical" | movies$Genre_3 == "Musical")
war <- subset(movies, movies$Genre == "War" | movies$Genre_2 == "War" | movies$Genre_3 == "War")
western <- subset(movies, movies$Genre == "Western" | movies$Genre_2 == "Western" | movies$Genre_3 == "Western")
comedy <- subset(movies, movies$Genre == "Comedy" | movies$Genre_2 == "Comedy" | movies$Genre_3 == "Comedy")
family <- subset(movies, movies$Genre == "Family" | movies$Genre_2 == "Family" | movies$Genre_3 == "Family")
sport <- subset(movies, movies$Genre == "Sport" | movies$Genre_2 == "Sport" | movies$Genre_3 == "Sport")
# Pego a quantidade de votos para cada instância de gênero
votos <- c(sum(drama$Vote)/1000000, sum(romance$Vote)/1000000, sum(scifi$Vote)/1000000, sum(crime$Vote)/1000000, sum(fantasy$Vote)/1000000,
sum(mystery$Vote)/1000000, sum(adventure$Vote)/1000000 , sum(thriller$Vote)/1000000, sum(biography$Vote)/1000000,
sum(horror$Vote)/1000000, sum(filmnoir$Vote)/1000000, sum(animation$Vote)/1000000, sum(music$Vote)/1000000, sum(musical$Vote)/1000000, sum(war$Vote)/1000000,
sum(western$Vote)/1000000, sum(comedy$Vote)/1000000, sum(family$Vote)/1000000, sum(sport$Vote)/1000000, sum(action$Vote)/1000000)
receita <- c(sum(drama$Revenue), sum(romance$Revenue), sum(scifi$Revenue), sum(crime$Revenue), sum(fantasy$Revenue),
sum(mystery$Revenue), sum(adventure$Revenue) , sum(thriller$Revenue), sum(biography$Revenue),
sum(horror$Revenue), sum(filmnoir$Revenue), sum(animation$Revenue), sum(music$Revenue), sum(musical$Revenue), sum(war$Revenue),
sum(western$Revenue), sum(comedy$Revenue), sum(family$Revenue), sum(sport$Revenue), sum(action$Revenue))
# Labels
labels <- c("Drama", "Romance",
"Sci-Fi", "Crime", "Fantasy", "Mystery",
"Adventure", "Thriller", "Biography",
"Horror", "FilmNoir", "Animation", "Music", "Musical",
"War", "Western", "Comedy", "Family", "Sport", "Action")
E essas foram as primeiras análises:
# Gráfico de barras
options("scipen"=10)
barplot(votos, main= "Quantidade de votos (Milhões) por gênero", las=2,
col=rainbow(20), names.arg= labels)
Pode-se concluir que um determinado filme pode ser divido em gêneros principais e subgêneros, com essa analise podemos reunir e distinguir a distribuição da quantidade de filmes mais avaliados pela presença de gêneros “fortes” como Drama, Ação, Comédia e Aventura em relação aos demais subgêneros mais “fracos” que também podem compor um mesmo filme.
# Gráfico de barras
options("scipen"=10)
barplot(receita, main= "Valor da receita nos EUA por gênero", las=2,
col=rainbow(20), names.arg= labels)
Também foi possível ter uma percepção de quais gêneros “fortes” são mais rentáveis nos cinemas, são eles: Comédia, Aventura, Drama e Ação
Posteriomente, achei pertinente investigar se existia uma relação entre o número de votos dos títulos e suas respectivas receitas em milhões de dólares arrecadados nos cinemas norte americanos. Foi feita a análise primeiro para os 10 filmes mais votados, depois para os 100 filmes mais votados e, por fim, para os 1000 filmes mais votados.
10 filmes mais votados:
# Pego subset dos 10 filmes mais votados
votes_10 <- subset(movies, movies$Rank < 11)
votes_10 <- votes_10[order(votes_10$Vote),]
votes <- votes_10$Vote
revenue <- votes_10$Revenue
max(votes)
## [1] 2011509
max(revenue)
## [1] 534.86
min(votes)
## [1] 1378253
min(revenue)
## [1] 28.34
#Grafico de linha
plot(votes, revenue, type="o", pch=3,
cex=0.5, col="red",
xlab="Nº de votos no IMDB",
ylab="Receita nos EUA (Milhões)",
main="Relação direta entre nº de votos e receita nos EUA",
cex.lab=0.8, cex.axis=0.8,
cex.main=1,
xlim=c(1378253,2011509),
ylim=c(28,700))
100 filmes mais votados:
#Pego o subset dos 100 filmes mais votados
votes_100 <- subset(movies, movies$Rank < 101)
votes_100 <- votes_100[order(votes_100$Vote),]
votes_2 <- votes_100$Vote
revenue_2 <- votes_100$Revenue
max(votes_2)
## [1] 2011509
max(revenue_2)
## [1] 936.66
min(votes_2)
## [1] 619601
min(revenue_2)
## [1] 0
#Grafico de linha
plot(votes_2, revenue_2, type="o", pch=2,
cex=0.5, col="blue",
xlab="Nº de votos no IMDB",
ylab="Receita nos EUA (Milhões)",
main="Relação direta entre nº de votos e receita nos EUA",
cex.lab=0.8, cex.axis=0.8,
cex.main=1,
xlim=c(619601,2011509),
ylim=c(0,1200))
1000 filmes mais votados:
#Pego o subset dos 1000 filmes mais votados
votes_1000 <- subset(movies, movies$Rank < 1001)
votes_1000 <- votes_1000[order(votes_1000$Vote),]
votes_3 <- votes_1000$Vote
revenue_3 <- votes_1000$Revenue
max(votes_3)
## [1] 2011509
max(revenue_3)
## [1] 936.66
min(votes_3)
## [1] 160657
min(revenue_3)
## [1] 0
#Grafico de linha
plot(votes_3, revenue_3, type="o", pch=1,
cex=0.5, col="green",
xlab="Nº de votos no IMDB",
ylab="Receita nos EUA (Milhões)",
main="Relação direta entre nº de votos e receita nos EUA",
cex.lab=0.8, cex.axis=0.8,
cex.main=1,
xlim=c(160657,2020000),
ylim=c(0,1200))
Pode-se observar que a quantidade de votos não cresce de forma dependente da receita dos cinemas, não existe uma tendência direta entre as duas variáveis em nenhum dos 3 gráficos exibidos acima.
Em seguida, foi analisada a tendência de valores de pontuação (scores), gerada pela avaliação dos usuários.
# Análise da tendência de valores de pontuação
Pontuação <- movies$Score
hist(Pontuação, col="purple",
probability= T)
densityPont<-density(Pontuação)
lines(densityPont)
Percebe-se que a maior tendência de valores de pontuação varia entre 5 e 8.
Dessa forma, foi possível ilustrar a porcentagem total de variação dos valores de pontuação presentes nesses dados.
# Pego os subsets dos intervalos das pontuações
zero_quatro <- subset(movies, movies$Score < 5)
cinco_oito <- subset(movies, movies$Score > 4 & movies$Score < 9)
nove_dez <- subset(movies, movies$Score > 8)
# Porcentagem dos valores de pontuação
x<-c(sum(zero_quatro$Score), sum(cinco_oito$Score), sum(nove_dez$Score))
labels<-c("0 - 4", "5 - 8",
"9 - 10")
pct<-round(x/sum(x)*100)
lbls<-paste(pct,"%",sep="")
pie(x,labels=lbls, main="Porcentagem da tendência de Score", col=c("orange", "grey", "cyan"), radius = 1)
legend("topright",
legend=c("Score entre 0 - 4", "Score entre 5 - 8",
"Score entre 9 - 10"),
cex=0.8, fill=c("orange", "grey", "cyan"))
Em seguida, optei por investigar como ocorre a distribuição por décadas dos anos de lançamento dos 100 filmes mais votados.
# Ano dos 100 filmes mais votados
Anos <- votes_100$Year
Anos <- sort(Anos)
hist(Anos, col="magenta",
probability= T)
densityPont<-density(Anos)
lines(densityPont)
Percebe-se que entre os 100 filmes mais avaliados, a tendência é que eles pertençam as décadas de 1990, 2000, e da metade da década de 2010, a curva decresce bastante próxima a data da disponibilização desses dados na Kaggle.
No dataset “movies”, a coluna score representa os cálculos estatísticos das avaliações populares, enquanto a coluna metascore mostra as pontuações fornecidas pela crítica especializada. Neste ponto, optei por analisar a correlação entre essas duas variáveis para os 100 filmes mais votados.
# Correlação entre score e metascore
plot(votes_100$Score,
votes_100$Metascore,
main="Movies Data",
col= c("magenta"),
pch=17,cex=2,
xlab= "Score",
ylab= "Metascore")
Existe uma correlação forte entre as pontuações score e metascore dos 100 filmes mais votados, mostrando que não há uma grande discrepância entre as duas medidas de avaliação. Infelizmente alguns poucos filmes ainda não possuem informação de Metascore.
Por fim, foi feita uma busca pelos 10 diretores com mais obras avaliadas no IMDB. Aqui, foi criado um dataset ranqueado pelos diretores com o maior volume de obras sujeitas as avaliações nessa base.
# Crio e ordeno em ordem descrescente um dataset ranqueado pelos diretores que possuem mais obras sendo avaliadas
diretores <- data.frame(Diretor= rownames(cbind(summary.factor(movies$Director))), Obras= cbind(summary.factor(movies$Director)))
diretores <- diretores[order(diretores$Obras, decreasing = TRUE),]
obras <- diretores[1:10,2]
labels <- diretores[1:10,1]
labels_table <- labels
labels <- str_sub(labels, end = 8)
labels <- paste(labels, "." , sep = "")
# Gráfico de barras com os 10 diretores com mais filmes avaliados
barplot(obras, main= "10 diretores com mais obras a serem avaliadas", las=2,
col= c("brown", "orange"), names.arg= labels, ylim=c(0,50))
diretores_table <- data.frame(Diretor= labels_table, Obras= obras)
datatable(diretores_table[1:10,], caption = "Tabela 2: Tabela dos 10 diretores com mais obras a serem avaliadas")
Como se pode ver, a análise fornecida contém visões interessantes de como funciona o engajamento dos usuários que fazem suas análises no IMDB, além de informações individuais sobre as produções. Certamente foi importante para alguns entender como as variáveis desse dataset podem nos mostrar as relaçoes entre o volume de votos com os gêneros e subgêneros presentes nos filmes; além disso foi possível saber quais gêneros costumam obter maiores receitas.
Também foi esclarecedor observar que, para os 10, 100 e 1000 filmes mais votados, a quantidade de votos dos filmes não tem necessariamente a ver com a receita dos cinemas, não existe uma tendência de crescimento entre as duas variáveis, o que pode ser devido ao fato de boa parte dos usuários terem outras maneiras de adquirir e assistir aos filmes. Outra coisa importante foi visualizar como varia os valores dos scores obtidos pelos votos populares de forma geral e qual a porcentagem desses valores, a fim de se observar e garantir a honestidade das avaliações.
Outro insight interessante, foi a descoberta de que entre os 100 filmes mais avaliados, a maior parte são das décadas de 1990, 2000, e da metade da década de 2010, o que leva a conclusão de que a estas décadas pertencem os filmes mais assistidos dentro dessa amostra de 100.
Além do score, também há o metascore, que mostra as pontuações fornecidas pela crítica especializada. Foi necessário então avaliar a correlação entre os dois tipos de pontuação. A conclusão foi de que existe uma correlação forte entre as duas variáveis, reforçando a validade da opnião popular e também a confiabilidade da base de dados.
Por fim, foi levantado um gráfico exibindo em ordem descrescente um dataset ranqueado pelos 10 diretores que possuem mais obras sendo avaliadas. Espera-se que essas análise sejam relevantes para os investidores, profissionais do cinema e/ou amantes da sétima arte em geral.