DEV Community

Geazi Anc
Geazi Anc

Posted on • Updated on

PySpark: uma breve análise das palavras mais comuns em Drácula, por Bram Stoker

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
Enter fullscreen mode Exit fullscreen mode

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()
         )
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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.

with open("stop_words_english.txt", "r") as f:
    text = f.read()
    stopwords = text.splitlines()

len(stopwords), stopwords[:15]
Enter fullscreen mode Exit fullscreen mode

Output

(851,
 ['able',
  'about',
  'above',
  'abroad',
  'according',
  'accordingly',
  'across',
  'actually',
  'adj',
  'after',
  'afterwards',
  'again',
  'against',
  'ago',
  'ahead'])
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

Output:

+--------------------+
|                line|
+--------------------+
|[The, Project, Gu...|
|                  []|
|[This, eBook, is,...|
|[most, other, par...|
|[whatsoever., You...|
+--------------------+
only showing top 5 rows
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

Output

+---------+
|     word|
+---------+
|      The|
|  Project|
|Gutenberg|
|    eBook|
|       of|
| Dracula,|
|       by|
|     Bram|
|   Stoker|
|         |
|     This|
|    eBook|
|       is|
|      for|
|      the|
+---------+
only showing top 15 rows
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.filter(
    ~words_nonull.word.isin(stopwords))


words_count_before_removing = words_nonull.count()
words_count_after_removing = words_without_stopwords.count()

words_count_before_removing, words_count_after_removing
Enter fullscreen mode Exit fullscreen mode

Output

(163399, 50222)
Enter fullscreen mode Exit fullscreen mode

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)
               )
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
hackergaucho profile image
Hacker Gaucho

cara, maneiro, mas você só pegou as stopwords 🙃

Collapse
 
geazi_anc profile image
Geazi Anc

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 😉

Collapse
 
heryhelder profile image
Carlos Heryhelder

De fato. Acredito que uma limpeza das stopwords antes do passo 8 vai enriquecer ainda mais o conteúdo do texto!

Collapse
 
geazi_anc profile image
Geazi Anc

Ei, é uma boa sugestão. Acho que vou fazer isso mesmo ;) de qualquer maneira, espero que tenha gostado =)

Collapse
 
heryhelder profile image
Carlos Heryhelder

Cara, muito obrigado pelos seus textos. Eles me ajudaram a iniciar meus estudos em engenharia de dados com o PySpark e o Airflow.

Collapse
 
geazi_anc profile image
Geazi Anc

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 ;)