Introdução a dados textuais no Python

Essa é uma aula de introdução à manipulação de dados textuais, daqui em diante chamados de strings, com foco em expressões regulares (regex). Expressões regulares são úteis pois strings, geralmente, contêm informações não estruturadas e regex é uma linguagem concisa para descrever e manipular padrões em strings.

Para tratar strings utilizaremos as funções básicas do Python e as bibliotecas re e pandas:


import re
import pandas as pd

Você já aprendeu previamente a criar objetos que representam textos, vamos criar alguns:


texto1 = "Essa é uma string"
texto2 = 'Para incluir "aspas duplas" em uma string deve-se utilizar aspas simples'
print(texto1)

# Essa é uma string

print(texto2)

# Para incluir "aspas duplas" em uma string deve-se utilizar aspas simples

Escapando caracteres especiais

Para inserir outros caracateres especiais em uma string é necessário utilizar a contrabarra para "escapar" o caracter, assim o Python não gera um erro ou entende o caracter de maneira inesperada. Exemplos:

 
print("string com \"aspas\" dentro")

# string com "aspas" dentro

 
print("c:\users\fernando") # gera um erro pois a "\" é um caracter especial

# (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \uXXXX escape (<string>, line 1)

 
print("c:\\users\\fernando") # adicione uma contrabarra para escapar uma contrabarra

# c:\users\fernando

Pense nessa contrabarra como uma instrução interna do Python dizendo para — quando esse objeto for salvo em um arquivo de texto ou usado como uma legenda em um gráfico, por exemplo — incluir o caracter especial ao usar a string em um trecho de código adiante. Note também que a representação impressa da string não é a mesma que a própria string.

Como contar caracteres?

A função len() informa o número de caracteres em uma string e Series.str.len() em uma pandas Series:

 
len("c:\\Win") # contrabarra não conta

# 6

pd.Series(["c:\\Win", "Análise Macro", "Fernando"]).str.len()

 

# 0 6
# 1 13
# 2 8
# dtype: int64

Como combinar strings?

Para concatenar duas ou mais strings use o +:

txt1 = "Última atualização"
txt2 = pd.to_datetime("today").ctime()
txt1 + ": " + txt2

# 'Última atualização: Wed Sep 11 09:20:50 2024'

E para concatenar strings utilizando um separador use join(), seguindo a sintaxe "separador".join(["texto 1", "texto 2"]):
txt3 = ["a", "b", "c", "d", "e"]
", ".join(txt3)
# 'a, b, c, d, e'

Por fim, em um exemplo mais avançado, para concatenar duas listas de strings elemento a elemento, primeiro combine os elementos tal como [(lista_X[0], lista_Y[0]), (lista_X[1], lista_Y[1]), ..., (lista_X[n], lista_Y[n])] com a função zip() e em seguida itere join() sobre este resultado:
txt4 = ["1", "2", "3", "4", "5"]
list(map("-".join, zip(txt3, txt4)))

# ['a-1', 'b-2', 'c-3', 'd-4', 'e-5']
Este processo é muito mais simples ao trabalhar com pandas Series:

pd.Series(txt3) + "-" + pd.Series(txt4)

 

# 0 a-1
# 1 b-2
# 2 c-3
# 3 d-4
# 4 e-5
# dtype: object

Como filtrar strings?

Para extrair partes de uma string podemos utilizar o índice dos caracteres da mesma ("string"[indice]):

texto1[<span class="hljs-number">0</span>] <span class="hljs-comment"># 1º caracter</span>

# 'E'

texto1[0:6] # do 1º caracter até o 5º caracter, ou seja inicio:fim (fim não incluso)

# 'Essa é'

texto1[-1] # valores negativos contam de trás pra frente (último caracter)

# 'g'

texto1[-3:-1] # do antepenúltimo ao penúltimo

# 'in'

texto1[-3:] # do antepenúltimo ao último

# 'ing'

Em pandas Series o procedimento é semelhante com str.slice():

pd.Series([texto1, texto2]).str.slice(start = -1)

 

# 0 g
# 1 s
# dtype: object
pd.Series([texto1, texto2]).str.slice(stop = 5)
# 0 Essa
# 1 Para
# dtype: object

 

pd.Series([texto1, texto2]).str.slice(start = -3, stop = -1)
# 0 in
# 1 le
# dtype: object

Caixa alta, caixa baixa e sentença

A função lower() permite converter a string para letras minúsculas:

texto2.lower()

# 'para incluir "aspas duplas" em uma string deve-se utilizar aspas simples'

A função upper() permite converter a string para letras maiúsculas:

texto2.upper()

# 'PARA INCLUIR "ASPAS DUPLAS" EM UMA STRING DEVE-SE UTILIZAR ASPAS SIMPLES'
A função capitalize() permite converter a string para uma sentença (primeira letra maiúscula):

texto2.upper().capitalize()

# 'Para incluir "aspas duplas" em uma string deve-se utilizar aspas simples'

Padrões de correspondência com regex

Regex é uma linguagem que permite descrever padrões em strings. É difícil e demorado para entender (não é uma linguagem humana), mas depois de algum treinamento notamos que é um recurso extremamente útil. Vamos aprender sobre regex de uma forma intuitiva e didática primeiro, depois avançamos para exemplos práticos.

Para essa primeira parte definimos uma função para visualizar um padrão de uma regex em um texto (você já aprendeu a definir funções, a única novidade aqui é a função re.finditer(), sobre a qual abordaremos adiante):

# Função para visualizar padrão em um texto
def str_view(texto, regex):
padroes = list(re.finditer(regex, texto))
if padroes:
for p in reversed(padroes):
inicio = p.start()
fim = p.end()
texto = texto[:inicio] + "<" + texto[inicio:fim] + ">" + texto[fim:]
else: 
texto = ""
return texto

O padrão mais simples é a busca por um padrão exato em uma string, por exemplo:

txt5 = ["maça", "banana", "ameixa"]
str_view(txt5[2], "am")

# '<am>eixa'

str_view() é uma função apenas didática que serve para visualizar um padrão em uma string. Aqui procuramos pelo padrão "am" e a função destaca este padrão nos elementos (se encontrado) com os símbolos <>.

Tornando o padrão procurado um pouco mais complexo, podemos usar o "." para procurar por qualquer caracter (antes e depois do "a"):

str_view(txt5[<span class="hljs-number">0</span>], <span class="hljs-string">".a."</span>)

# '<maç>a'

list(map(lambda x: str_view(x, ".a."), txt5)) # iterando para todos os items da lista

# ['<maç>a', '<ban>ana', '']

Para procurar por um padrão no começo ou no final de uma string utilize as âncoras:

  • ^ procura por padrão no começo da string;
  • $ procura por padrão no final da string.

Exemplos:

list(map(<span class="hljs-keyword">lambda</span> x: str_view(x, <span class="hljs-string">"^a"</span>), txt5))

# ['', '', '<a>meixa']

list(map(<span class="hljs-keyword">lambda</span> x: str_view(x, <span class="hljs-string">"a$"</span>), txt5))

# ['maç<a>', 'banan<a>', 'ameix<a>']

Conforme a documentação da biblioteca re, existem diversos caracteres especiais úteis para encontrar padrões:

# Para encontrar números, usamos:
str_view("Python é 10!", "\d")

# 'Python é <1><0>!'

str_view("Python é 10!", "\w") # alfanuméricos

# '<P><y><t><h><o><n> <é> <1><0>!'

str_view("Python é 10!", "\s") # espaços

# 'Python< >é< >10!'

str_view("Python é 10!", "[^\w\s]") # pontuações: [^] significa qualquer caracter exceto a regex em seguida

# 'Python é 10<!>'

Aplicando regex

Agora que você aprendeu o básico de expressões regulares, vamos explorar algumas funções úteis que a biblioteca pandas oferece para manipular strings. Em resumo:

  • pd.Series.str.contains() para verificar se um padrão é encontrado em uma string;
  • pd.Series.str.extract() para extrair um grupo de padrão encontrado de uma string;
  • pandas.Series.str.replace() para substituir um padrão encontrado em uma string.

Vamos aos exemplos (consulte a documentação para detalhes):

# pandas Series de exemplo
txt6 = pd.Series(["Python é 10!", "python é 10", "Pythoné10!"])
# Verificando se há números seguidos de uma pontuação no final da string
txt6.str.contains(pat = "[\d]!$")
# 0 True
# 1 False
# 2 True
# dtype: bool
# Extraindo letras maiúsculas do início da string
txt6.str.extract(pat = "(^[A-Z])", expand = False)
# 0 P
# 1 NaN
# 2 P
# dtype: object
# Substituindo espaços por quebras de linha na string
txt6.str.replace(pat = "\s", repl = "\n", regex = True)
# 0 Python\né\n10!
# 1 python\né\n10
# 2 Pythoné10!
# dtype: object

Tenha acesso ao código e suporte desse e de mais 500 exercícios no Clube AM!

Quer o código desse e de mais de 500 exercícios de análise de dados com ideias validadas por nossos especialistas em problemas reais de análise de dados do seu dia a dia? Além de acesso a vídeos, materiais extras e todo o suporte necessário para você reproduzir esses exercícios? Então, fale com a gente no Whatsapp e veja como fazer parte do Clube AM, clicando aqui.

Compartilhe esse artigo

Facebook
Twitter
LinkedIn
WhatsApp
Telegram
Email
Print

Comente o que achou desse artigo

Outros artigos relacionados

Técnicas de extração de informação com text mining

Como quantificar sobre o que se trata um texto? Que tipo de informação podemos obter a partir destes dados? Como identificar a relevância das palavras? Neste artigo exploramos técnicas estatísticas de frequência de tokens para extrair informação de dados textuais.

como podemos ajudar?

Preencha os seus dados abaixo e fale conosco no WhatsApp

Boletim AM

Preencha o formulário abaixo para receber nossos boletins semanais diretamente em seu e-mail.