13.5 O pacote stringr

library(stringr)
library(dplyr)
library(glue)

1. O CPF é um número de 11 dígitos, por exemplo: 54491651884. No entanto para facilitar a visualização costumamos mostrá-lo com separadores a cada 3 casas: 544.916.518-84. Crie uma função que transforma um número de 11 dígitos em uma string com as separações, como um CPF.

# Sem regex
formata_CPF <- function(num) {
  
  if(str_count(num) != 11) {
    stop("Número inválido!")
  }
  
  # Concatemos cada parte do número, interpolando
  # com os pontos e o traço.
  
  s <- str_c(
    str_sub(num, start = 1, end = 3),
    ".",
    str_sub(num, start = 4, end = 6),
    ".",
    str_sub(num, start = 7, end = 9),
    "-",
    str_sub(num, start = 10, end = 11)
  )
  
}
# Com regex
formata_CPF <- function(num) {
  
  if(str_count(num) != 11) {
    stop("Número inválido!")
  }
  
  str_replace(
    string = num, 
    pattern = "([0-9]{3})([0-9]{3})([0-9]{3})", 
    replacement = "\\1.\\2.\\3-"
  )
}

A função str_replace() faz o seguinte:

  • O pattern= procurará um padrão de 9 números:
    • O primeiro ([0-9]{3}) pega os três primeiros números.
    • O segundo ([0-9]{3}) pega os três próximos números (quarto ao sexto).
    • O terceiro ([0-9]{3}) pega os três números seguintes (sétimo ao nono).
  • O replacement= substituirá esses 9 números pela string formada por:
    • \\1, a expressão dada pelo primeiro parêntese do pattern=, isto é, os três primeiros números.
    • ., o primeiro ponto.
    • \\2, a expressão dada pelo segundo parêntese do pattern=, isto é, os três próximos números (quarto ao sexto).
    • ., o segundo ponto.
    • \\3, a expressão dada pelo terceiro parêntese do pattern=, isto é, os três números seguintes (sétimo ao nono).
    • -, o traço.

2. Transforme o vetor de strings abaixo em "01 - Alto" "02 - Médio" "03 - Baixo".

s <- c('Alto', 'Médio', 'Baixo')
# Usando str_c()
str_c("0", 1:length(s), " - ", s, sep = "")
## [1] "01 - Alto"  "02 - Médio" "03 - Baixo"

# Usando o pacote glue
glue("0{1:length(s)} - {s}")
## 01 - Alto
## 02 - Médio
## 03 - Baixo

Para mais informações sobre o pacote glue, confira este post.


3. Crie uma regex que capture múltiplas versões da palavra ‘casa’. Ela deve funcionar com as palavras ‘Casa’, ‘CASA’, ‘CaSa’, ‘CAsa’. Teste-a usando a função str_detect().

s <- c('Casa', 'CASA', 'CaSa', 'CAsa')
str_detect(s, "[CcAaSsAa]")
## [1] TRUE TRUE TRUE TRUE
str_detect(s, "[Cc][Aa][Ss][Aa]")
## [1] TRUE TRUE TRUE TRUE

4. Imagine que a seguinte string é a parte final de uma URL.

  • /ac/rio-branco/xpto-xyz-1-0-1fds2396-5

Transforme-a em “AC - Rio Branco” utilizando a função str_split().

url <- c('/ac/rio-branco/xpto-xyz-1-0-1fds2396-5')
UF <- url %>%
  str_split("[/]", simplify = TRUE) %>% 
  .[1,2] %>% 
  str_to_upper()
cidade <- url %>% 
  str_split("[/]", simplify = TRUE) %>% 
  .[1,3] %>% 
  str_replace("-", " ") %>% 
  str_to_title()
str_c(UF, " - ", cidade)
## [1] "AC - Rio Branco"

5. Crie uma função que retorna TRUE quando a string é um palíndromo e FALSO caso não seja.

# Solução 1: usando a função rev() para inverter uma string fragmentada
testa_palindromo <- function(s) {
  
  s %>%
    str_split("", simplify = T) %>% 
    rev %>% 
    str_c(collapse = "") %>% 
    str_detect(s)
  
}
testa_palindromo("ana")
## [1] TRUE
testa_palindromo("bananas")
## [1] FALSE
testa_palindromo("socorrammesubinoonibusemmarrocos")
## [1] TRUE

# Solução 2: usando a função str_reverse() do pacote stringi,
# que já inverte a string diretamente.
testa_palindromo <- function(s) {
  
  s %>% 
    stringi::stri_reverse() %>% 
    str_detect(s)
  
}

testa_palindromo("ana")
## [1] TRUE
testa_palindromo("bananas")
## [1] FALSE
testa_palindromo("socorrammesubinoonibusemmarrocos")
## [1] TRUE

6. De acordo com as regras da língua portuguesa, antes de “p” ou “b” devemos usar a letra “m”. Em outras palavras, com outras consoantes, usamos a letra “N”. Suponha que você tem o seguinte texto com erros gramaticais:

s <- 'Nós chamamos os bonbeiros quando começou o incêmdio.'

Crie uma função para corrigi-lo.

# Função que funciona para o exemplo
corrige_mn <- function(s) {
  
  s %>% 
    str_replace("nb", "mb") %>% 
    str_replace("md", "nd")
  
}
corrige_mn(s)
## [1] "Nós chamamos os bombeiros quando começou o incêndio."

# Função que funciona no caso geral
corrige_mn <- function(s) {
  
  s %>% 
    str_replace_all("m([^aeioubp[[:space:]]+])", "n\\1") %>%  
    str_replace_all("n([pb])", "m\\1")
  
}
corrige_mn(s)
## [1] "Nós chamamos os bombeiros quando começou o incêndio."

O padrão [^aeioubp[[:space:]]+] significa “tudo menos vogais, b, p ou espaços”. O \\1 devolve o padrão encontrado pelo primeiro parêntese do argumento patern=.


7. Considere o seguinte texto

s <- "A função mais importante para leitura de dados no `lubridate` é a `ymd`. Essa função serve para ler qualquer data de uma `string` no formato `YYYY-MM-DD`. Essa função é útil pois funciona com qualquer separador entre os elementos da data e também porque temos uma função para cada formato (`ymd`, `mdy`, `dmy`, `dym`, `myd`, `ydm`)."

Extraia todas as combinações da função ymd, sem repetições.

str_extract_all(s, "[ymd]{3}") %>% 
  unlist() %>% 
  unique
## [1] "ymd" "mdy" "dmy" "dym" "myd" "ydm"

8. Considere as frases abaixo

s <- c(
  'O produto é bom.',
  'O produto não é bom.',
  'O produto não é muito bom.',
  'O produto é muito bom',
  'O produto não é ruim.',
  'O produto não é não ruim.',
  'O produto não é não bom.'
)

Crie uma regra para identificar se o texto refere-se a um feedback positivo ou negativo sobre o produto (considere não bom = ruim e não ruim = bom). Retorne um vetor lógico que vale TRUE se o feedback for positivo e FALSE caso contrário.

feedback <- function(s) {
  
  s %>% 
    str_replace("não bom", "ruim") %>%
    str_replace("não ruim", "bom") %>% 
    str_replace("muito ", "") %>% 
    str_detect("(.*) produto é bom|(.*) não é ruim")
  
}
feedback(s)
## [1]  TRUE FALSE FALSE  TRUE  TRUE FALSE  TRUE

Curso-R