R: Processamento de strings em R

Última atualização: 2026-08-26

Em projetos reais, 80% do tempo dedicado à limpeza de dados é gasto no processamento de strings — limpar números de telefone, extrair endereços de e-mail, substituir palavras-chave, além de dividir e concatenar strings. O pacote stringr do R é oficialmente recomendado pelo tidyverse; ele é mais consistente e mais fácil de usar do que o pacote padrão do R, o grep/gsub.

Ao concluir esta lição, você será capaz de usar o R para lidar com qualquer tarefa de limpeza de texto: validação de números de telefone, extração de endereços de e-mail, segmentação de texto e análise de URLs.

1. O que você vai aprender



2. Uma história sobre limpeza de dados

(1) Problema: Dados incorretos

Depois de receber um conjunto de dados de clientes, Chen descobriu que:

TEXT 📖 Somente leitura
Name      Cell phone number            Email
Alice      138-0000-1234     zhangsan@163.COM
Bob      +86 139 0000 5678  lisi@example.com  
Charlie      (13900001111)    wangwu@gmail.com
Diana      138.0000.2222     zhaoliu@ qq.com
Eve      13900003333       

A ser limpo até:

TEXT 📖 Somente leitura
Name      Cell phone number       Email
Alice      13800001234  zhangsan@163.com
Bob      13900005678  lisi@example.com
Charlie      13900001111  wangwu@gmail.com
Diana      13800002222  zhaoliu@qq.com
Eve      13900003333  NA

Se você usar fórmulas do Excel e fizer ajustes manuais, isso leva meia hora; com o módulo re do Python, são necessárias 20 linhas de código; com o R stringr

(2) Solução usando R

R
library(stringr)

# 1. Delete a Phone Number(Remove spaces,-,.,+86,())
clean_phone <- str_replace_all(phones, "[\\s\\-\\.\\(\\)\\+86]", "")

# 2. Clean Up Your Inbox(Remove spaces,Convert to lowercase)
clean_email <- str_trim(emails) |> str_to_lower()

# 3. Verify the mobile phone number format
is_valid_phone <- str_detect(clean_phone, "^1[3-9]\\d{9}$")

5 tarefas de limpeza concluídas com apenas 3 linhas de código.

100%
graph LR
    A[Dirty Strings<br/>' 138-0000-1234 '] --> B[str_trim Remove spaces]
    B --> C[str_replace_all Remove special characters]
    C --> D[str_to_lower Use all lowercase letters]
    D --> E[str_detect Validation Format]
    E --> F[Clean String<br/>'13800001234']

    style A fill:#f8d7da
    style B fill:#fff3cd
    style C fill:#d4edda
    style D fill:#cce5ff
    style E fill:#e1d4ff
    style F fill:#d4edda

3. Noções básicas sobre strings

(1) Criação de strings

R
# 1. Single quotation mark
s1 <- 'Hello'

# 2. Double quotation marks
s2 <- "World"

# 3. Character vector
fruits <- c("Apple", "Banana", "Cherries")
class(fruits)
# [1] "character"

# 4. nchar Number of characters
nchar("Hello")
# [1] 5

nchar("Hello")  # UTF-8 One Chinese character 1 characters
# [1] 2

(2) Concatenação com paste() / paste0()

R
# paste Default sep = " "
paste("Hello", "World")
# [1] "Hello World"

# paste0 No separators
paste0("Hello", "World")
# [1] "HelloWorld"

# Vectorized Concatenation
paste("No.", 1:3, "Place")
# [1] "No. 1 Place" "No. 2 Place" "No. 3 Place"

# collapse Combine vectors into a single string
paste(c("A", "B", "C"), collapse = "-")
# [1] "A-B-C"


4. O pacote stringr: 5 funções principais

100%
mindmap
    root((stringr<br/>5 Major Core Functions))
        Concatenation
            str_c
            str_glue
        Substring
            str_sub
            str_length
        Testing
            str_detect
            str_count
        Replace
            str_replace
            str_replace_all
        Split
            str_split
        Support
            str_trim
            str_pad
            str_to_upper
            str_to_lower
        Advantages
            Automated Processing NA
            API Match
            Pipe-Friendly
            tidyverse Ecology

(1) Comparação entre stringr e o R básico

R Básico stringr Vantagens
nchar() str_length() O stringr lida automaticamente com valores NA
paste() str_c() Consistência + Vetorização
substr() str_sub() Suporta índices negativos
Mais intuitivo
gsub() str_replace_all() Mais simples
strsplit() str_split() Mais fácil de usar

(2) Concatenação com str_c()

R
library(stringr)

# 1. Basic Splicing
str_c("Hello", "World", sep = " ")
# [1] "Hello World"

# 2. Multi-Parameter Concatenation
str_c("a", "b", "c", sep = "-")
# [1] "a-b-c"

# 3. Vectorized Concatenation
str_c("No.", 1:3, "Place", sep = "")
# [1] "No.1Place" "No.2Place" "No.3Place"

# 4. collapse Merge Vectors
str_c(c("A", "B", "C"), collapse = " | ")
# [1] "A | B | C"

# 5. Processing NA
str_c("Hello", NA, "World")
# [1] NA
str_c("Hello", NA, "World", na.rm = TRUE)
# [1] "HelloWorld"

(3) str_length() Comprimento

R
# Number of characters(Not the number of bytes)
str_length("Hello")
# [1] 5

str_length("Hello")
# [1] 2

# String Vectors
str_length(c("abc", "Hello", "Hello World"))
# [1]  3  2 12

# NA Processing
str_length(NA)
# [1] NA  ← stringr Explicit Return NA

(4) str_sub() – Subsequência

R
# 1. Extract a Substring(1-based,Including both ends)
str_sub("Hello World", 1, 5)
# [1] "Hello"

# 2. Negative Index(From the last digit)
str_sub("Hello World", -5)  # Finally 5 ea
# [1] "World"

# 3. Modify a Substring
s <- "Hello World"
str_sub(s, 1, 5) <- "Hi"
s
# [1] "Hi World"

# 4. Vectorization
str_sub(c("apple", "banana", "cherry"), 1, 3)
# [1] "app" "ban" "che"

(5) Detecção com str_detect()

R
# 1. Does it contain a substring?
str_detect("Hello World", "World")
# [1] TRUE

# 2. Using regular expressions
str_detect(c("apple", "banana", "cherry"), "^a")  # Starting with a
# [1]  TRUE FALSE FALSE

# 3. Count(Includes several times)
str_count("ababab", "ab")
# [1] 3

(6) Substituição com str_replace() / str_replace_all()

R
# 1. Replace the first match
str_replace("Hello World World", "World", "R")
# [1] "Hello R World"

# 2. Replace all matches
str_replace_all("Hello World World", "World", "R")
# [1] "Hello R R"

# 3. Using regular expressions
str_replace_all("abc 123 def 456", "\\d+", "X")
# [1] "abc X def X"


5. Tratamento de espaços e formatação

(1) A função str_trim() remove os espaços em branco

R
# 1. Remove leading and trailing spaces
str_trim("  Hello World  ")
# [1] "Hello World"

# 2. Left edge
str_trim("  Hello", side = "left")
# [1] "Hello"

# 3. Go to the right end
str_trim("Hello  ", side = "right")
# [1] "Hello"

(2) str_pad() – Preenchimento

R
# 1. Left-aligned
str_pad("42", width = 5, side = "left", pad = "0")
# [1] "00042"

# 2. Right-aligned
str_pad("Hi", width = 5, side = "right", pad = "-")
# [1] "Hi---"

# 3. Filled on both sides
str_pad("Hi", width = 6, side = "both", pad = "-")
# [1] "--Hi--"

(3) str_to_*: distinção entre maiúsculas e minúsculas

R
# 1. All Caps
str_to_upper("Hello World")
# [1] "HELLO WORLD"

# 2. All lowercase
str_to_lower("Hello World")
# [1] "hello world"

# 3. Capitalize the first letter
str_to_title("hello world")
# [1] "Hello World"

# 4. Capitalize the first word of a sentence
str_to_sentence("hello world")
# [1] "Hello world"

(4) str_trunc() Truncar

R
# Truncate excessively long strings(add ...)
str_trunc("This is a very long sentence.", width = 10)
# [1] "This is..."


6. str_split() — Divisão

R
# 1. Basic Division
str_split("a,b,c", ",")
# [[1]]
# [1] "a" "b" "c"

# 2. Limit on the Number of Partitions
str_split("a,b,c", ",", n = 2)
# [[1]]
# [1] "a"     "b,c"

# 3. Simplify the result(Vectors, Not Lists)
str_split("a,b,c", ",", simplify = TRUE)
#      [,1] [,2] [,3]
# [1,] "a"  "b"  "c"


7. Prática: Limpeza dos dados dos clientes

A seguir, apresentamos um exemplo de um fluxo de trabalho completo que reúne todos os conceitos relacionados a strings abordados nesta aula.

▶ Exemplo: Limpeza aprofundada dos dados dos clientes

R 📖 Somente leitura
# ============================================
# In-Depth Cleaning of Customer Data
# Features:Delete a Phone Number,Email,Name,Address
# ============================================

library(stringr)
library(dplyr)

# 1. Preparing Raw Data
customers <- tibble(
  name = c("  Alice  ", "Bob", "wangwu", "ZHAO liu", "Eve"),
  phone = c("138-0000-1234", "+86 139 0000 5678", "(13900001111)",
            "138.0000.2222", "13900003333"),
  email = c("zhangsan@163.COM", " lisi@example.com  ",
            "wangwu@gmail.com", "zhaoliu@ qq.com", NA)
)

cat("=== Raw Data ===\n")
print(customers)

# 2. Clean Name
customers <- customers |>
  mutate(
    # Remove spaces + Capitalize the first letter(English Name)
    name_clean = str_trim(name) |>
      str_to_title() |>
      str_replace_all("\\s+", " ")  # Replace multiple spaces with a single space
  )

# 3. Delete a Phone Number(Remove spaces,-,.,+86,())
customers <- customers |>
  mutate(
    phone_clean = str_replace_all(phone, "[\\s\\-\\.\\(\\)\\+86]", ""),
    # Verification 11 Mobile phone number
    phone_valid = str_detect(phone_clean, "^1[3-9]\\d{9}$")
  )

# 4. Clean Up Your Inbox
customers <- customers |>
  mutate(
    email_clean = str_trim(email) |> str_to_lower(),
    # Verify the email address format
    email_valid = str_detect(email_clean, "^[\\w.+-]+@[\\w.-]+\\.[a-z]{2,}$")
  )

# 5. Output the cleaning results
cat("\n=== Data After Cleaning ===\n")
print(customers |> select(name_clean, phone_clean, phone_valid,
                          email_clean, email_valid))

# 6. Extracting Data Features
customers <- customers |>
  mutate(
    # Identify the mobile carrier based on a phone number
    operator = case_when(
      str_detect(phone_clean, "^1(3[0-9]|4[5-9]|5[0-35-9]|66|7[2-35-8]|8[0-9]|9[0-35-9])\\d{8}$") ~ "China Mobile",
      str_detect(phone_clean, "^1(3[0-2]|4[5-7]|5[3-5-7]|6[2567]|7[0-3]|8[0-3])\\d{8}$") ~ "China Unicom",
      str_detect(phone_clean, "^1(33|34|49|53|7[37]|8[0-2])\\d{8}$") ~ "China Telecom",
      TRUE ~ "Unknown"
    ),
    # Email Domain
    email_domain = str_extract(email_clean, "@[a-z0-9.]+"),
    # Before the phone number 3 bit
    phone_prefix = str_sub(phone_clean, 1, 3)
  )

cat("\n=== Data Characteristics ===\n")
print(customers |> select(name_clean, operator, phone_prefix, email_domain))

# 7. Text Statistics
cat("\n=== Distribution of Email Domain Names ===\n")
print(table(customers$email_domain))

cat("\n=== Distribution of Carriers ===\n")
print(table(customers$operator))

# 8. Identify invalid data
cat("\n=== Invalid data ===\n")
invalid <- customers |> filter(!phone_valid | !email_valid)
print(invalid |> select(name_clean, phone_clean, phone_valid,
                        email_clean, email_valid))
51 linhas de lógica (limite de 40, somente leitura)

Resultado esperado (trecho):

TEXT 📖 Somente leitura
=== Data After Cleaning ===
# A tibble: 5 × 6
  name_clean phone_clean   phone_valid email_clean         email_valid
  <chr>      <chr>         <lgl>       <chr>               <lgl>      
1 Alice       13800001234   TRUE        zhangsan@163.com    TRUE       
2 Bob       13900005678   TRUE        lisi@example.com    TRUE       
3 Wangwu     13900001111   TRUE        wangwu@gmail.com    TRUE       
4 Zhao Liu   13800002222   TRUE        zhaoliu@qq.com      TRUE       
5 Eve       13900003333   TRUE        <NA>                FALSE      

=== Distribution of Carriers ===
  China Telecom China Unicom China Mobile 
        1        2        2

❓ Perguntas Frequentes

P: Como faço para escolher entre stringr e as funções básicas de strings do R? R: Use stringr para novos projetos — API consistente, tratamento automático de NA, suporte a piping e o ecossistema tidyverse. Para códigos existentes, substitua paste e gsub por str_c e str_replace.

P: Como se usa índices negativos com str_sub()? R: Os números negativos começam pelo fim. str_sub(x, -3) recupera os últimos 3 caracteres; str_sub(x, 1, -2) recupera tudo, do início até o penúltimo caractere.

P: Qual é a diferença entre str_replace() e str_replace_all()? R: str_replace substitui apenas a primeira ocorrência, enquanto str_replace_all substitui todas as ocorrências. Na maioria dos casos, use str_replace_all.

P: Como faço para extrair números? R: str_extract_all(x, "\\d+") Extrai todas as sequências numéricas (lista). str_extract(x, "\\d+") Extrai o primeiro número (vetor).

P: O que devo fazer se os caracteres chineses aparecerem como texto ilegível? R: O R 4.x usa UTF-8 por padrão, portanto não deveria haver texto ilegível. Se você encontrar texto ilegível, use stringi::stri_encode() para converter a codificação ou use locale = locale(encoding = "GBK") ao ler o arquivo.

P: Qual é a diferença entre str_c() e paste()? R: Eles são essencialmente equivalentes. No entanto, str_c() oferece melhor consistência (propaga valores NA por padrão) e é mais legível quando usado com pipes.


📖 Resumo


📝 Exercícios

  1. Problema básico: Use str_c() para concatenar os vetores c("Apple", "Banana", "Cherry") e c(1, 2, 3) e gerar as saídas “Maçãs 1 yuan”, “Bananas 2 yuan” e “Cerejas 3 yuan”.

  2. Problemas básicos: Use str_length() para calcular o número de caracteres em "Hello World", "Hello World" e "". Use str_sub() para extrair os caracteres do 7º ao 11º de “Hello World”.

  3. Problema básico: Use str_detect() para determinar quais elementos em c("apple", "banana", "cherry") terminam com “a” e gere um vetor lógico.

  4. Exercício avançado: Limpe os seguintes dados incorretos: ① Remova os espaços dos endereços de e-mail e converta-os para letras minúsculas; ② Extraia o domínio do e-mail; ③ Valide o formato do e-mail (@ + domínio + . + pelo menos 2 letras). Use mutate() para adicionar 3 novas colunas de dados.

  5. Desafio: Simule 100 linhas de dados de clientes (incluindo vários números de telefone, endereços de e-mail e nomes inválidos) e conclua o seguinte processo de limpeza de dados: ① Limpar nomes ② Limpar números de telefone ③ Verificar números de telefone ④ Limpar endereços de e-mail ⑤ Extrair informações sobre operadoras ⑥ Calcular a porcentagem de dados inválidos. Imprima os dataframes antes e depois da limpeza e salve capturas de tela deles.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%