O projeto tem como tema brevemente analisar e explorar dados sobre obras literárias e seus autores. O dados utilizados foram obtidos através da plataforma kaggle. Ao total foram utilizados dois datasets formados por dados extraídos da API fornecida pela rede social Goodreads. O primeiro dataset possui informações exclusivamente sobre os autores das obras e seus antecedentes, como nacionalidade, gênero, número de fãs na plataforma, data de nascimento e data de morte. O segundo dataset possui informações sobre obras a literárias, como nome dos autores, número de páginas da obra, data de publicação e média de avaliações.
Para analisar estes dados utilizaremos técnicas de mineração de texto, geração de nuvem de palavras e estatística básica.
library("dplyr") #Utilizado para a manipulação de estruturas de dados.
library(tidyr) #Utilizado para a limpeza e organização de dados.
library("tm") #Contem utilidades que facilitam a mineração de dados.
library("wordcloud") #Geração e visualização de nuvem de palavras.
library("RColorBrewer") #Paletas de cores para gráficos.
library("DT") #Melhor visualização de dataframes.
Segue agora descrições sobre os datasets utilizados:
“authorid” “name” “workcount” “fan_count” “gender”
“image_url” “about” “born” “died” “influence”
“average_rate” “rating_count” “review_count” “website” “twitter”
“genre” “original_hometown” “country” “latitude” “longitude”
Vários autores no dataset possuem entradas NA em colunas como gender e country, além de possuírem colunas que a princípio não possuem relevância para a pesquisa. Portanto será necessário limpar a base de dados antes de utilizá-la.
“Id” “Name” “RatingDist1” “pagesNumber” “RatingDist4” “RatingDistTotal” “PublishMonth” “PublishDay” “Publisher” “CountsOfReview” “PublishYear” “Language”
“Authors” “Rating” “RatingDist2” “RatingDist5” “ISBN” “RatingDist3”
Assim como no dataset de autores, este dataset possui entradas NA em várias colunas e precisa de limpeza.
authors <- read.csv(file = 'Authors/final_dataset.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8")
books1 <- read.csv(file = 'Books/book1-100k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8")
books1 <- rbind(books1, read.csv(file = 'Books/book100k-200k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books1 <- rbind(books1, read.csv(file = 'Books/book200k-300k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books1 <- rbind(books1, read.csv(file = 'Books/book300k-400k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books1 <- rbind(books1, read.csv(file = 'Books/book400k-500k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books1 <- rbind(books1, read.csv(file = 'Books/book500k-600k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books2 <- read.csv(file = 'Books/book600k-700k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8")
books3 <- read.csv(file = 'Books/book700k-800k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8")
books3 <- rbind(books3, read.csv(file = 'Books/book800k-900k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books3 <- rbind(books3, read.csv(file = 'Books/book900k-1000k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books3 <- rbind(books3, read.csv(file = 'Books/book1000k-1100k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books3 <- rbind(books3, read.csv(file = 'Books/book1100k-1200k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books3 <- rbind(books3, read.csv(file = 'Books/book1200k-1300k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books3 <- rbind(books3, read.csv(file = 'Books/book1300k-1400k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books3 <- rbind(books3, read.csv(file = 'Books/book1400k-1500k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books3 <- rbind(books3, read.csv(file = 'Books/book1500k-1600k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books3 <- rbind(books3, read.csv(file = 'Books/book1600k-1700k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8"))
books4 <- read.csv(file = 'Books/book1700k-1800k.csv',
header = T,
strip.white= T,
stringsAsFactors = F,
na.strings= "", encoding = "UTF-8")
Após carregar os arquivos obtivemos os seguintes dataframes:
summary(authors)
## authorid name workcount fan_count
## Min. : 4 Length:209517 Min. : 0.0 Min. : -18.0
## 1st Qu.: 309867 Class :character 1st Qu.: 3.0 1st Qu.: 1.0
## Median : 2892154 Mode :character Median : 8.0 Median : 6.0
## Mean : 4694173 Mean : 35.6 Mean : 166.4
## 3rd Qu.: 7074207 3rd Qu.: 21.0 3rd Qu.: 33.0
## Max. :20178817 Max. :1278643.0 Max. :709826.0
##
## gender image_url about born
## Length:209517 Length:209517 Length:209517 Length:209517
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
##
## died influence average_rate rating_count
## Length:209517 Length:209517 Min. :0.000 Min. : 0
## Class :character Class :character 1st Qu.:3.670 1st Qu.: 65
## Mode :character Mode :character Median :3.900 Median : 297
## Mean :3.862 Mean : 7236
## 3rd Qu.:4.110 3rd Qu.: 1308
## Max. :8.070 Max. :24511114
##
## review_count website twitter genre
## Min. : 0.0 Length:209517 Length:209517 Length:209517
## 1st Qu.: 8.0 Class :character Class :character Class :character
## Median : 37.0 Mode :character Mode :character Mode :character
## Mean : 514.6
## 3rd Qu.: 162.0
## Max. :579250.0
##
## original_hometown country latitude longitude
## Length:209517 Length:209517 Min. :-85.90 Min. :-176.64
## Class :character Class :character 1st Qu.: 34.27 1st Qu.: -83.00
## Mode :character Mode :character Median : 40.77 Median : -61.67
## Mean : 36.62 Mean : -29.87
## 3rd Qu.: 47.75 3rd Qu.: 10.93
## Max. : 80.68 Max. : 178.83
## NA's :165148 NA's :165148
summary(books1)
## Id Name RatingDist1 pagesNumber
## Min. : 1 Length:338120 Length:338120 Min. : 0.0
## 1st Qu.:145202 Class :character Class :character 1st Qu.: 158.0
## Median :295577 Mode :character Mode :character Median : 247.0
## Mean :296282 Mean : 285.3
## 3rd Qu.:444892 3rd Qu.: 351.0
## Max. :599999 Max. :2254246.0
## RatingDist4 RatingDistTotal PublishMonth PublishDay
## Length:338120 Length:338120 Min. : 1.000 Min. : 1.000
## Class :character Class :character 1st Qu.: 1.000 1st Qu.: 3.000
## Mode :character Mode :character Median : 5.000 Median : 6.000
## Mean : 9.854 Mean : 6.313
## 3rd Qu.:18.000 3rd Qu.:10.000
## Max. :31.000 Max. :12.000
## Publisher CountsOfReview PublishYear Language
## Length:338120 Min. : 0.00 Min. : 162 Length:338120
## Class :character 1st Qu.: 0.00 1st Qu.: 1996 Class :character
## Mode :character Median : 1.00 Median : 2001 Mode :character
## Mean : 43.63 Mean : 1999
## 3rd Qu.: 8.00 3rd Qu.: 2005
## Max. :94850.00 Max. :19769
## Authors Rating RatingDist2 RatingDist5
## Length:338120 Min. :0.000 Length:338120 Length:338120
## Class :character 1st Qu.:3.500 Class :character Class :character
## Mode :character Median :3.860 Mode :character Mode :character
## Mean :3.481
## 3rd Qu.:4.110
## Max. :5.000
## ISBN RatingDist3
## Length:338120 Length:338120
## Class :character Class :character
## Mode :character Mode :character
##
##
##
summary(books2)
## Id Name Authors ISBN
## Min. :600000 Length:55156 Length:55156 Length:55156
## 1st Qu.:624454 Class :character Class :character Class :character
## Median :649388 Mode :character Mode :character Mode :character
## Mean :649585
## 3rd Qu.:674524
## Max. :699999
## Rating PublishYear PublishMonth PublishDay
## Min. :0.000 Min. : 1852 Min. : 1.000 Min. : 1.000
## 1st Qu.:3.330 1st Qu.: 1995 1st Qu.: 1.000 1st Qu.: 3.000
## Median :3.810 Median : 2001 Median : 4.000 Median : 6.000
## Mean :3.357 Mean : 1999 Mean : 9.655 Mean : 6.283
## 3rd Qu.:4.090 3rd Qu.: 2005 3rd Qu.:18.000 3rd Qu.: 9.000
## Max. :5.000 Max. :20040 Max. :31.000 Max. :12.000
## Publisher RatingDist5 RatingDist4 RatingDist3
## Length:55156 Length:55156 Length:55156 Length:55156
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## RatingDist2 RatingDist1 RatingDistTotal CountsOfReview
## Length:55156 Length:55156 Length:55156 Min. : 0.000
## Class :character Class :character Class :character 1st Qu.: 0.000
## Mode :character Mode :character Mode :character Median : 1.000
## Mean : 9.809
## 3rd Qu.: 4.000
## Max. :20903.000
## Language pagesNumber Description
## Length:55156 Min. : 0.0 Length:55156
## Class :character 1st Qu.: 149.0 Class :character
## Mode :character Median : 240.0 Mode :character
## Mean : 269.6
## 3rd Qu.: 336.0
## Max. :37000.0
summary(books3)
## Id Name Authors ISBN
## Min. : 700000 Length:409697 Length:409697 Length:409697
## 1st Qu.: 896060 Class :character Class :character Class :character
## Median :1150386 Mode :character Mode :character Mode :character
## Mean :1158146
## 3rd Qu.:1396462
## Max. :1699999
## Rating PublishYear PublishMonth PublishDay
## Min. :0.000 Min. : 200 Min. : 1.000 Min. : 1.000
## 1st Qu.:3.330 1st Qu.: 1995 1st Qu.: 1.000 1st Qu.: 3.000
## Median :3.800 Median : 2001 Median : 4.000 Median : 6.000
## Mean :3.356 Mean : 1999 Mean : 9.743 Mean : 6.319
## 3rd Qu.:4.080 3rd Qu.: 2005 3rd Qu.:18.000 3rd Qu.: 9.000
## Max. :5.000 Max. :20099 Max. :31.000 Max. :12.000
## Publisher RatingDist5 RatingDist4 RatingDist3
## Length:409697 Length:409697 Length:409697 Length:409697
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## RatingDist2 RatingDist1 RatingDistTotal CountsOfReview
## Length:409697 Length:409697 Length:409697 Min. : 0.00
## Class :character Class :character Class :character 1st Qu.: 0.00
## Mode :character Mode :character Mode :character Median : 1.00
## Mean : 7.17
## 3rd Qu.: 3.00
## Max. :43652.00
## Language pagesNumber Description Count.of.text.reviews
## Length:409697 Min. : 0 Length:409697 Min. : 0.00
## Class :character 1st Qu.: 144 Class :character 1st Qu.: 0.00
## Mode :character Median : 240 Mode :character Median : 1.00
## Mean : 279 Mean : 7.17
## 3rd Qu.: 336 3rd Qu.: 3.00
## Max. :4517845 Max. :43652.00
summary(books4)
## Authors CountsOfReview Description ISBN
## Length:32105 Min. : 0.00 Length:32105 Length:32105
## Class :character 1st Qu.: 0.00 Class :character Class :character
## Mode :character Median : 0.00 Mode :character Mode :character
## Mean : 4.27
## 3rd Qu.: 2.00
## Max. :13164.00
## Id Language Name PublishDay
## Min. :1700000 Length:32105 Length:32105 Min. : 1.000
## 1st Qu.:1724504 Class :character Class :character 1st Qu.: 3.000
## Median :1749704 Mode :character Mode :character Median : 6.000
## Mean :1749568 Mean : 6.326
## 3rd Qu.:1773769 3rd Qu.: 9.000
## Max. :1799991 Max. :12.000
## PublishMonth PublishYear Publisher Rating
## Min. : 1.000 Min. : 1376 Length:32105 Min. :0.000
## 1st Qu.: 1.000 1st Qu.: 1995 Class :character 1st Qu.:3.040
## Median : 4.000 Median : 2001 Mode :character Median :3.750
## Mean : 9.723 Mean : 2001 Mean :3.199
## 3rd Qu.:18.000 3rd Qu.: 2005 3rd Qu.:4.050
## Max. :31.000 Max. :65535 Max. :5.000
## RatingDist1 RatingDist2 RatingDist3 RatingDist4
## Length:32105 Length:32105 Length:32105 Length:32105
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## RatingDist5 RatingDistTotal pagesNumber
## Length:32105 Length:32105 Min. : 0.0
## Class :character Class :character 1st Qu.: 144.0
## Mode :character Mode :character Median : 234.0
## Mean : 265.5
## 3rd Qu.: 330.0
## Max. :21191.0
Observando os resultados acima, é possível perceber que Os arquivos contendo os dados sobre livros possuem números de variáveis inconsistentes, portanto, a princípio foi necessário carregar os arquivos CSV em diferentes dataframes.
Antes de juntar esses dados em um único dataframe é preciso antes filtrar apenas as variáveis em comum que serão utilizadas na análise.
books1Filtered <- books1%>%select(Name, PublishDay, PublishMonth, PublishYear, Language, Authors, Rating, CountsOfReview)
books2Filtered <- books2%>%select(Name, PublishDay, PublishMonth, PublishYear, Language, Authors, Rating, CountsOfReview)
books3Filtered <- books3%>%select(Name, PublishDay, PublishMonth, PublishYear, Language, Authors, Rating, CountsOfReview)
books4Filtered <- books4%>%select(Name, PublishDay, PublishMonth, PublishYear, Language, Authors, Rating, CountsOfReview)
allBooks <- rbind(books1Filtered, books2Filtered)
allBooks <- rbind(allBooks, books3Filtered)
allBooks <- rbind(allBooks, books4Filtered)
Em relação ao dataframe contendo dados sobre autores, iremos apenas manter as colunas que podem apresentar alguma relevância à análise.
authorsFiltered <- authors%>%select(name, gender, born, average_rate, rating_count, genre, original_hometown, country)
Após a filtragem é possível fazer o merge entre os dataframes de livros e autores. Neste caso utilizaremos o atributo Authors do dataframe allBooks e o atributo name do dataframe authorsFiltered.
books.authors <- merge(allBooks, authorsFiltered, by.x = "Authors", by.y = "name", all = T)
Por agora serão filtradas as linhas do novo dataframe obtido que não possuem informação sobre título de livro, ano da publicação do livro e gênero do autor.
books.authors <- books.authors%>%filter(!is.na(Name))
books.authors <- books.authors%>%filter(!is.na(PublishYear))
books.authors <- books.authors%>%filter(!is.na(gender))
Segue agora uma breve visualização de como ficou o dataframe obtido após a limpeza.
datatable(books.authors[600:700,], options = list(searching = F, paging = T, scrollX = T))
aux <- books.authors%>%filter(PublishYear <= 2020 & PublishYear > 1800 & gender == "female")%>%group_by(PublishYear)%>%summarise(count = n())
plot(aux$PublishYear, aux$count, type = "b", main="Quantidade de livros regitrados por ano", col="pink", cex = 0.5, pch = 10, xlab="Ano", ylab="Quantidade por gênero do autor")
aux <- books.authors%>%filter(PublishYear <= 2020 & PublishYear > 1800 & gender == "male")%>%group_by(PublishYear)%>%summarise(count = n())
lines(aux$PublishYear, aux$count, type = "b", col="cyan", cex = 0.5)
aux <- books.authors%>%filter(PublishYear <= 2020 & PublishYear > 1800 & gender == "unknown")%>%group_by(PublishYear)%>%summarise(count = n())
lines(aux$PublishYear, aux$count, type = "b", col="green", cex = 0.5)
legend("topleft",legend = c("female", "male", "unknown"),lty=c(1,2,3),col=c("pink","cyan","green"),bg="white",lwd=2)
Ao observar o gráfico acima contendo o número de livros publicados por ano, percebe-se que a publicação de livros se popularizou drasticamente depois de 1950. Além disso, o número de autores explicitamente do gênero feminino demonstrou ser inferior ao número dos autores do gênero masculino e com gênero desconhecido.
aux <- aggregate(Rating ~ PublishYear, FUN = mean, books.authors%>%filter(PublishYear <= 2020 & PublishYear > 1800 & gender == "female"))
plot(aux$PublishYear, aux$Rating, type = "b", main="Média de avaliações por ano", col="pink", cex = 0.5, pch = 10, xlab="Ano", ylab="Avaliação")
aux <- aggregate(Rating ~ PublishYear, FUN = mean, books.authors%>%filter(PublishYear <= 2020 & PublishYear > 1800 & gender == "male"))
lines(aux$PublishYear, aux$Rating, type = "b", col="cyan", cex = 0.5)
aux <- aggregate(Rating ~ PublishYear, FUN = mean, books.authors%>%filter(PublishYear <= 2020 & PublishYear > 1800 & gender == "unknown"))
lines(aux$PublishYear, aux$Rating, type = "b", col="green", cex = 0.5)
legend("bottomright",legend = c("female", "male", "unknown"),lty=c(1,2,3),col=c("pink","cyan","green"),bg="white",lwd=2)
Podemos observar no gráfico acima que a média das avaliações de livros por ano tendeu a se tornar mais constante depois de 1950, justamente pela crescente quantidade de livros publicados em anos mais recentes. Também é possível perceber que a avaliação média de livros por autores de gênero desconhecido tendeu a ser menor que a de autores com gênero definido. Também não é possível perceber uma grande diferença na avaliação média de livros escritos por homens e mulheres.
corpus <- Corpus(VectorSource(books.authors%>%select(Name)))
corpus <- tm_map(corpus, tolower) #Casts every word to lower case.
## Warning in tm_map.SimpleCorpus(corpus, tolower): transformation drops documents
corpus <- tm_map(corpus, removePunctuation) #Removes punctuation from the text.
## Warning in tm_map.SimpleCorpus(corpus, removePunctuation): transformation drops
## documents
corpus <- tm_map(corpus, removeNumbers) #Removes numbers from the text.
## Warning in tm_map.SimpleCorpus(corpus, removeNumbers): transformation drops
## documents
corpus <- tm_map(corpus, stripWhitespace) #Strips the text from extra white spaces.
## Warning in tm_map.SimpleCorpus(corpus, stripWhitespace): transformation drops
## documents
corpus <- tm_map(corpus, removeWords, stopwords('english')) #Removes stop words in English.
## Warning in tm_map.SimpleCorpus(corpus, removeWords, stopwords("english")):
## transformation drops documents
tdm <- as.matrix(TermDocumentMatrix(corpus))
fre <- sort(rowSums(tdm), decreasing = T)
aux <- head(fre, 30)
barplot(aux, las = 2, col = rainbow(10))
wordcloud(corpus, min.freq = 1, max.words = 60, random.order = FALSE, rot.per = 0.35, colors=brewer.pal(8, "Dark2"), scale=c(2,.2))
Os gráficos acima mostram as palavras mais utilizadas em títulos de livros. Temáticas como “guia”, “vida”, “amor” e “guerra” aparentam ser predominantes.
#A coluna contendo os gêneros possui multiplas categorias separadas por virgula, portanto precisamos separa-las. Também iremos removes as entradas NA.
genres <- books.authors%>%filter(!is.na(genre))%>%separate_rows(genre, sep = ",")%>%select(genre)
genre.occurrences <- genres%>%group_by(genre)%>%summarise(count = n())%>%arrange(desc(count))%>%top_n(10) #Contagem da ocorrência de cada gênero.
pct <- round(genre.occurrences$count/sum(genre.occurrences$count) * 100)
lbls <- paste(genre.occurrences$genre, pct)
lbls <- paste(lbls, "%", sep = "")
pie(genre.occurrences$count, labels = lbls, main = "10 gêneros de literatura mais publicados", col = rainbow(10))
O gráfico acima mostra os 10 maiores temas literários obtidos. Livros de ficção e literatura infantil são os gêneros dominantes, seguidos por livros de história e relatos reais.
Com esta breve análise conseguimos observar certos aspectos sobre a publicação de livros em anos recentes. A dominância de autores explicitamente masculinos no mercado, as palavras e temas que predominam no momento da escolha do título de livros, e a explicita popularidade de livros de ficção e literatura infaltil.
Tratando-se de limitações, esta análise enquadrou apenas os dados obtidos através da rede social Goodreads, portanto a real quantidade e variedade de livros publicados nos últimos anos é evidentemente maior que as obtidas nestes datasets Sendo assim, os resultados obtidos só devem ser considerados no contexto da rede social.