Note: dis article is also available in english 🌎.
Considerado como um marco da literatura gótica, o icônico livro Drácula, escrito em 1897 por Bram Stoker, desperta até hoje o fascínio das pessoas por todo o mundo. Hoje, a fim de introduzir novos conceitos e funcionalidades do Apache Spark, vamos desenvolver uma breve análise das palavras mais comuns encontradas neste clássico livro 🧛🏼♂️.
Para isso, vamos desenvolver um notebook no Google Colab, um serviço de nuvem gratuito criado pelo Google para incentivar pesquisas na área de machine learning e inteligência artificial.
Caso não saiba como usar o Google Colab, confira este excelente artigo da Alura escrito pelo Thiago Santos que ensina, de forma muito didática, como usar o Colab e criar seus primeiros códigos!
O notebook deste artigo também está disponível em meu GitHub 😉.
A obra em questão foi obtida por meio do Projeto Gutenberg, um acervo digital que reúne livros de todo o mundo que já se encontram em domínio público. A versão plaintext de Drácula pode ser baixada gratuitamente aqui.
Antes de começar
Antes de iniciarmos o desenvolvimento de nosso notebook, é necessário fazer a instalação da biblioteca PySpark.
A biblioteca PySpark é a API oficial do Python para o Apache Spark. É com ela que vamos realizar nossa análise de dados 🎲.
Crie uma nova célula de código no Colab e execute a seguinte linha:
!pip install pyspark
Passo um: inicialização do Apache Spark
Logo após a instalação, precisamos inicializar o Apache Spark. Para isso, crie uma nova célula de código no Colab e adicione o seguinte bloco:
from pyspark.sql import SparkSession
spark = (SparkSession.builder
.appName("The top most common words in Dracula, by Bram Stoker")
.getOrCreate()
)
Passo dois: download e leitura de Drácula, por Bram Stoker
Agora sim podemos começar! Nesta etapa iremos fazer o download do livro Drácula do projeto Gutenberg e, logo em seguida, fazer a leitura do arquivo através do PySpark.
O download do livro consiste, basicamente, no uso do utilitário wget, informando a URL que direciona para o livro Drácula no projeto Gutenberg. Depois, salva-se o conteúdo da solicitação, isto é, o próprio livro, no diretório atual, com o nome de Dracula – Bram Stoker.txt.
Crie uma nova célula no colab e adicione o seguinte bloco de código:
!wget https: // www.gutenberg.org/cache/epub/345/pg345.txt -O "Dracula - Bram Stoker.txt"
Passo três: download das stopwords em inglês
A seguir, iremos fazer o download de uma lista das stopwords que são frequentemente usadas no idioma inglês. Essas stopwords normalmente incluem preposições, partículas, interjeições, uniões, advérbios, pronomes, palavras introdutórias, números de 0 a 9 ( inequívocos ), outras partes oficiais da fala, símbolos, pontuação. Recentemente, essa lista foi complementada por sequências de símbolos comumente usadas na Internet como www, com, http, etc.
Essa lista foi adquirida através do site CountWordsFree, um site que, dentre outros utillitários, reúne as stopwords encontradas em diversos idiomas, incluindo o nosso querido português.
Mãos a obra! Crie uma nova célula de código e adicione o seguinte bloco:
!wget https://countwordsfree.com/stopwords/english/txt -O "stop_words_english.txt"
Feito esses downloads, podemos fazer a leitura do livro através do PySpark. Crie uma nova célula no Colab e adicione o seguinte bloco de código:
book = spark.read.text("Dracula - Bram Stoker.txt")
E também vamos fazer a leitura das stopwords que acabamos de baixar. As stopwords serão armazenadas em uma lista, na variável stopwords.
raw_stopwords = spark.read.text("stop_words_english.txt")
stopwords = raw_stopwords.selectExpr("value as stopwords")
stopwords.show()
Output
| stopwords|
+-----------+
| able|
| about|
| above|
| abroad|
| according|
|accordingly|
| across|
| actually|
| adj|
| after|
| afterwards|
| again|
| against|
| ago|
| ahead|
| ain't|
| all|
| allow|
| allows|
| almost|
+-----------+
only showing top 20 rows
Passo quatro: Extração individual das palavras
Após a leitura do livro, é necessário que transformemos cada uma das palavras em uma coluna no DataFrame.
Para isso, utiliza-se o método split, o qual, para cada uma das linhas, irá separar cada uma das palavras através do espaço em branco entre elas. O resultado será uma lista de palavras.
from pyspark.sql.functions import split
lines = book.select(split(book.value, " ").alias("line"))
lines.show(5)
Output:
+--------------------+
| line|
+--------------------+
|[The, Project, Gu...|
| []|
|[This, eBook, is,...|
|[most, other, par...|
|[whatsoever., You...|
+--------------------+
only showing top 5 rows
Passo cinco: explodindo a lista de palavras em colunas no DataFrame
Depois das palavras terem sido separadas, é necessário que se faça a conversão desta lista de palavras em colunas no DataFrame.
Para tal, usa-se o método explode presente no Apache Spark.
from pyspark.sql.functions import explode, col
words = lines.select(explode(col("line")).alias("word"))
words.show(15)
Output
+---------+
| word|
+---------+
| The|
| Project|
|Gutenberg|
| eBook|
| of|
| Dracula,|
| by|
| Bram|
| Stoker|
| |
| This|
| eBook|
| is|
| for|
| the|
+---------+
only showing top 15 rows
Passo seis: transformando todas as palavras em minúsculas
Esta é uma etapa bem simples. Para que não haja distinção da mesma palavra por conta de letras maiúsculas, vamos transformar todas as palavras no DataFrame para letras minúsculas, fazendo o uso da função lower.
from pyspark.sql.functions import lower
words_lower = words.select(lower(col("word")).alias("word_lower"))
words_lower.show()
Output
+----------+
|word_lower|
+----------+
| the|
| project|
| gutenberg|
| ebook|
| of|
| dracula,|
| by|
| bram|
| stoker|
| |
| this|
| ebook|
| is|
| for|
| the|
| use|
| of|
| anyone|
| anywhere|
| in|
+----------+
only showing top 20 rows
Passo sete: eliminação de pontuação
Para que também não haja distinção da mesma palavra por conta da pontuação presente no final delas, é preciso removê-las.
Isso é feito através do método regexp_extract, o qual extrai palavras de uma string por meio de uma expressão regular.
Calma, não precisa se assustar! A expressão é bem simples. Ela consiste em um conjunto contendo todos os símbolos de A a Z, uma ou mais vezes. Viu, eu te disse que era bem simples 👏🏼.
from pyspark.sql.functions import regexp_extract
words_clean = words_lower.select(
regexp_extract(col("word_lower"), "[a-z]+", 0).alias("word")
)
words_clean.show()
Output
+---------+
| word|
+---------+
| the|
| project|
|gutenberg|
| ebook|
| of|
| dracula|
| by|
| bram|
| stoker|
| |
| this|
| ebook|
| is|
| for|
| the|
| use|
| of|
| anyone|
| anywhere|
| in|
+---------+
only showing top 20 rows
Passo oito: remoção de valores nulos
Como visto, mesmo após a remoção das pontuações ainda há colunas com valores nulos, ou seja, espaços em branco.
Para que esses espaços em branco não sejam considerados na análise da frequência de cada palavra presente no livro, é necessário removê-los.
words_nonull = words_clean.filter(col("word") != "")
words_nonull.show()
Output
+---------+
| word|
+---------+
| the|
| project|
|gutenberg|
| ebook|
| of|
| dracula|
| by|
| bram|
| stoker|
| this|
| ebook|
| is|
| for|
| the|
| use|
| of|
| anyone|
| anywhere|
| in|
| the|
+---------+
only showing top 20 rows
Passo nove: remoção das stopwords
Estamos quase lá! Antes de partirmos para a análise das palavras mais comuns propriamente dita, precisamos remover as stopwords de nosso dataframe, para que elas não sejam levadas em consideração durante a análise.
words_without_stopwords = (
words_nonull.join(stopwords, words_nonull["word"] == stopwords["stopwords"], how="left")
.filter("stopwords is null")
.select("word")
)
words_count_before_removing = words_nonull.count()
words_count_after_removing = words_without_stopwords.count()
words_count_before_removing, words_count_after_removing
Output
(163399, 50222)
Passo dez: análise das palavras mais comuns
E, finalmente, chegamos ao fim da limpesa de nossos dados. Agora sim podemos começar a análise das palavras mais comuns presentes no livro.
Primeiro, é realizado a contagem das palavras mais frequentes no dataframe. Para isso, vamos agrupar cada uma das palavras e depois vamos usar uma função de agregação, count, para determinar quantas vezes elas aparecem.
words_count = (words_without_stopwords.groupby("word")
.count()
.orderBy("count", ascending=False)
)
Depois, vamos exibir as 20 palavras mais comuns. O ranque pode ser ajustado através da variável rank. Sinta-se à vontade para ajustar a variável como preferir.
rank = 20
words_count.show(rank)
Output
+--------+-----+
| word|count|
+--------+-----+
| time| 381|
| helsing| 323|
| van| 322|
| lucy| 297|
| good| 256|
| man| 255|
| mina| 240|
| dear| 224|
| night| 224|
| hand| 209|
| room| 207|
| face| 206|
|jonathan| 206|
| count| 197|
| door| 197|
| sleep| 192|
| poor| 191|
| eyes| 188|
| work| 188|
| dr| 187|
+--------+-----+
only showing top 20 rows
Considerações finais
É isso por hoje, pessoal. Chegamos no fim de nossa breve análise.
Neste artigo, analisamos as palavras mais comuns do livro Drácula, por Bram Stoker. Para isso, foi necessário fazer uma limpesa nos dados, como dividir as palavras pelos espaços entre elas; explodir a lista de palavras em colunas no dataframe; transformar todas as letras em minúsculas; remover a pontuação de todo o texto através de uma expressão regular; e, por fim, remover as stopwords.
Espero que tenham gostado. Mantenham as estacas afiadas, cuidado com as sombras que andam pela noite, e até a próxima 🧛🏼♂️🍷.
Referências
RIOUX, Jonathan. Data Analysis with Python and PySpark.
STOKER, Bram. Dracula.
Top comments (6)
cara, maneiro, mas você só pegou as stopwords 🙃
Opa, amigo, valeu pelo comentário! De fato, como eu citei, as 20 palavras são as stopwords. Se você mudar a variável rank para 100, você vai conseguir visualizar melhor as outras palavras 😉
De fato. Acredito que uma limpeza das stopwords antes do passo 8 vai enriquecer ainda mais o conteúdo do texto!
Ei, é uma boa sugestão. Acho que vou fazer isso mesmo ;) de qualquer maneira, espero que tenha gostado =)
Cara, muito obrigado pelos seus textos. Eles me ajudaram a iniciar meus estudos em engenharia de dados com o PySpark e o Airflow.
Carlos, fico feliz demais em ouvir isso =). Obrigado mesmo pelo seu comentário. Me siga que logo logo posto mais artigos sobre engenharia de dados ;)