O Sensacionalista e Text Mining: Análise de sentimento usando o lexiconPT
Posted on September 23, 2017
De volta à ativa no blog!
Recentemente, quando precisei fazer pela primeira vez algum tipo de análise em cima de textos (o chamado Text Mining ou Mineração de Texto) em Português, senti falta de ter um acesso fácil a um léxico na linguagem. O R já tem a sua disposição vários recursos para quem quer fazer Text Mining em inglês, como os pacotes tokenizer, tidytext, tm e lexicon, além de vários blog posts sobre Sentiment Analysis que você encontra no R-bloggers. Contudo, existe uma séria escassez de material de referência na língua portuguesa.
O pacote lexiconPT, que eu lancei em 20/09/2017 no Github (e em breve no CRAN também) nasceu para resolver parte desse problema. Até o momento, o lexiconPT possui três datasets de léxicos: o OpLexicon (versões 2.1 e 3.0) e o SentiLex-PT02. Não pretendo (nem tenho competência para tal, pois sou iniciante em Text Mining - sem falsa modéstia) destrinchar como cada um deles funciona e em quê eles diferem. Para isso, sugiro ler as referências citadas na documentação dos próprios datasets (ex.: help("oplexicon_v2.1")).
Mas ter o léxico em mãos só resolve parte dos problemas: ainda faltam os textos em si para serem analisados. Algumas ideias de datasets poderiam ser notícias, letras de músicas, livros (tem vários em Domínio Público), tweets, etc. Para demonstrar um simples uso do pacote, eu decidi por analisar comentários feitos por usuários na página do Sensacionalista, uma das mais populares do Facebook. A coleta dos dados foi relativamente fácil graças ao pacote Rfacebook.
Com o pacote lexiconPT, podemos responder a perguntas como:
Os comentários no Sensacionalista são mais negativos ou positivos?
Qual termo está mais associado a comentários negativos? PT ou PSDB? Temer ou Dilma? Bolsonaro ou Lula?
Qual o comentário feito por um usuário mais negativo da história do Sensacionalista (dentro da amostra coletada)? E qual o mais positivo?
Vamos ao código.
Coleta dos dados
Este post só foi possível graças ao Rfacebook. Para aprender como ele funciona, leia a documentação presente em seu repo no Github. Para este primeiro, primeiro usei a função getPage() para extrair as últimas 5000 publicações do Sensacionalista.
É necessário corrigir o encoding do corpo da publicação para o R parar de reclamar sobre isso:
Só esse dataset por si só já renderia (e renderá) análises interessantes, mas vou as deixar para um futuro post para não deixar este aqui grande demais.
A coluna id é a que usaremos como referência como input na função getPost() para extrair os comentários dos usuários na publicação. Infelizmente, a API do Facebook apresenta uma certa instabilidade para requests de dados muito grandes. Em várias tentativas que fiz, o máximo de dados que consegui extrair foram 200 comentários de 500 publicações da página. Portanto, vou usar esses parâmetros:
A função getPost() fornece o seguinte output:
Para extrair os dataframes relativos aos comentários e aos metadados das publicações, o purrr é uma mão na roda:
Só pode ser trollagem da API do Facebook retornar aquela mensagem logo no topo do dataframe, mas enfim.
O dataframe df_comments, o objeto da nossa análise, não possui alguns dados que serão valiosos para a análise, como o link para o artigo no site do Sensacionalista. Por isso, vamos um left_join com o df_posts.
Percebeu que nas colunas df_comments$id e df_posts$id existe um traço separando dois conjuntos numéricos? Por alguma razão que beira a imbecilidade, não é possível combinar imediatamente essas duas colunas para formatar um dataframe só com o left_join. A sintaxe de identificação do Facebook funciona assim: O post é identificado IDPAGINA_IDPUBLICAÇÃO e o comentário na publicação é identificado como IDPUBLICAÇÃO_IDCOMENTÁRIO. Ou seja, para poder juntar os dois dataframes, vamos ter que combinar a sequência númerica à esquerda do underline (acho que esse traço tem algum outro nome, mas não me lembro no momento) em df_comments$id e à direita em df_posts$id.
Uso do lexiconPT
Agora temos o dataset em mãos para usar o lexiconPT. Acho muito importante ressaltar que Text Mining é uma atividade razoavelmente complexa que envolve uma extensa etapa de limpeza e tratamento de dados, como remover (ou não) acentos e corrigir palavras com letras duplicadas (tristee) ou erros gramaticais (infelismente). Para fins de simplicidade, não vou me ater muito a esses detalhes e pular direto para a utilização dos léxicos portugueses e apresentação dos resultados.
Ambos os datasets possuem colunas de polaridade de sentimento, que é a que usaremos para quantificar o quão negativo ou positivo é um comentário.
*De novo esse comentário… *
Enfim, veja que foi criada uma linha para cada palavra presetnte no comentário. Será essa nova coluna term que usaremos como referência para quantificar o sentimento de um comentário.
A amostra acima mostra que nem toads as palavras possuem uma polaridade registrada nos léxicos. Não só isso, mas algumas palavras (como faltar, ligar e levar) estão presentes no OpLexicon mas não no SentiLex. A polaridade 1 em faltar significa que, de acordo com esse léxico, a palavra está associada a comentários positivos. Saber essa diferença é fundamental, pois a escolha do léxico pode ter uma grande influência nos resultados da análise.
Vamos então manter no dataframe apenas as palavras que possuem polaridade tanto no OpLexicon como no SentiLex:
Apresentação dos resultados
O gráfico de pontos abaixo mostra a distribuição de polaridade para cada léxico:
Existem pelo menos três outliers nos dados, todos causados pela grande quantidade de palavras do comentário, o que pode ser um indício de que simplesmente somar a polaridade de cada palavra do comentário pode não ser um bom método. Outra informação revelada pelo gráfico é que existem palavras que possuem sentimentos diferentes de acordo com o léxico usado. Ter isso em mente é fundamental para a análise.
Após remover os outliers, já é possível descobrir quais os comentários mais positivos e mais negativos da amostra coletada:
Por incrível que pareça, tanto o comentário mais positivo quanto o mais negativo falam sobre a esquerda.
Para prosseguir com a análise, usaremos o léxico OpLexicon para a análise de sentimento:
Agora sim podemos demonstrar uma visualização de uma análise básica de sentimento: Como tem sido o sentimento geral dos comentários no Sensacionalista ao longo do tempo?
Por exemplo, o primeiro link coletado na amostra, uma foto, teve 9 palavras contadas como negativas e 13 como positivas. O score geral dos comentários nessa publicação foi 13 - 9 = 4.
Qual a publicação do Sensacionalista com maior nível de “positividade”? E o de “negatividade”?
A publicação que mais recebeu comentários negativos (não tenho certeza se é essa a interpretação mais correta dos resultados, mas enfim) é um link sobre o MBL, enquanto o mais positivo é sobre o famoso caso do “E se der errado”.
O gráfico abaixo mostra a evolução do sentimento dos comentários nas publicações do Sensacionalista ao longo do tempo:
Uma possível interpretação do gráfico é que a série temporal não possui uma clara tendência, apesar de os picos de negatividade serem bem mais frequentes que os de positividade.
Outra análise que dá para fazer é investigar o nível de sentimento de comentários associados a determinadas palavras. Por exemplo, o quão negativo costuma ser um comentário quando ele menciona a palavra bolsonaro?
Temer e Dilma, os dois presidentes com os piores níveis de popularidade de República, estarem associados a comentários positivos é bem surpreendente. Na verdade, isso ocorre porque a própria palavra temer possui polaridade positiva. Para consultar a polaridade de uma palavra nos datasets presentes no lexiconPT, use a função lexiconPT::get_word_sentiment().
Conclusão e chamada para futuros trabalhos
O pacote lexiconPT, apesar de simples, tem um enorme potencial para enriquecer o conteúdo de Text Mining em Português na comunidade brasileira de R. O exemplo dado nesse post pode ser considerado deveras simplório. Muitas etapas foram puladas ou desconsideradas com o intuito de fornecer a você uma rápida introdução às possibilidades criadas pelo pacote. Espero que o leitor deste post tenha se sentido motivado a fazer suas próprias análises de sentimento. As possibilidade são incontáveis.