7  Manejo de strings

En esta sección, aprenderemos cómo crear strings y vectores de caracteres. Luego, veremos cómo crear strings a partir de datos y, lo contrario, cómo extraer strings de los datos. Finalmente, discutiremos funciones que trabajan con letras individuales y trataremos algunos desafíos que pueden surgir cuando se trabaja con otros idiomas.

En este capítulo utilizaremos funciones del paquete stringr, que forma parte del core del tidyverse. También utilizaremos el dataset babynames ya que proporciona strings interesantes para manipular.

library(tidyverse)
library(babynames)

7.1 Creación de un string

Ya hemos creado strings anteriormente, pero sin entrar en detalles. Puedes crear un string usando comillas simples (') o dobles ("). No hay diferencia en el comportamiento entre ambos, aunque la guía de estilo del tidyverse recomienda usar ", a menos que el string contenga múltiples ".

string1 <- "Esto es un string"
string2 <- 'Si quiero incluir una "cita" dentro de un string, uso comillas simples'

Si olvidas cerrar una comilla, verás +, el prompt de continuación:

> "Este es un string sin cerrar la comilla
+ 
+ 
+ AYUDA ESTOY ATASCADO EN UN STRING

7.1.1 Escapes

Para incluir comillas simples o dobles dentro de un string, usa \ para “escaparlas”:

comilla_doble <- "\"" # o '"'
comilla_simple <- '\'' # o "'"

Para incluir una barra invertida literal en un string, necesitarás escapar también: "\\":

barra_invertida <- "\\"

Para ver el contenido en bruto del string, usa str_view() o la función base writeLines():

x <- c(comilla_simple, comilla_doble, barra_invertida)
x
[1] "'"  "\"" "\\"
str_view(x)
[1] │ '
[2] │ "
[3] │ \

7.1.2 Strings en crudo

Si tienes un string con muchas barras invertidas, puedes usar r antes de las comillas para que R lo interprete como un string en crudo:

dificil <- "double_quote <- \"\\\"\" # or '\"'
single_quote <- '\\'' # or \"'\""
str_view(dificil)
[1] │ double_quote <- "\"" # or '"'
    │ single_quote <- '\'' # or "'"

Pero puedes usar r para que R lo interprete como un string en crudo:

dificil <- r"(double_quote <- "\"" # or '"'
single_quote <- '\'' # or "'")"
str_view(dificil)
[1] │ double_quote <- "\"" # or '"'
    │ single_quote <- '\'' # or "'"

7.1.3 Otros caracteres especiales

Además de las comillas y las barras invertidas, hay otros caracteres especiales que puedes incluir en un string:

  • \n para nueva línea
  • \t para tabulación
  • \u seguido de cuatro dígitos hexadecimales para un carácter Unicode(Lista de caracteres Unicode)
x <- c("uno\ndos", "uno\tdos", "\u00A1Hola!")
x
[1] "uno\ndos" "uno\tdos" "¡Hola!"  
str_view(x)
[1] │ uno
    │ dos
[2] │ uno{\t}dos
[3] │ ¡Hola!

7.2 Creación de varios strings a partir de datos

7.2.1 paste()

La función más común para crear strings a partir de datos es paste(). Puedes usarla para concatenar múltiples strings:

paste("Hola", "Mundo")
[1] "Hola Mundo"

También puedes especificar un separador:

paste("Hola", "Mundo", sep = ", ")
[1] "Hola, Mundo"

Si tienes un vector de strings, puedes concatenarlos todos con collapse:

paste(c("Hola", "Mundo", "como", "estás!"), collapse = " ")
[1] "Hola Mundo como estás!"

7.2.2 str_c()

En tidyverse puedes usar funciones como str_c() y str_glue() de la forma siguiente:

str_c("Hola", " ", "Mundo")
[1] "Hola Mundo"

La ventaja de estas funciones es que funcionan con la gramática del tidyverse:

df <- tibble(
  nombre = c("Ana", "Luis", "María"),
  edad = c(20, 30, 40), puesto = c("Analista", "Gerente", "Director(a)")
)
df |> mutate(saludo = str_c(
  "Hola ",
  nombre, "!",
  " Tienes ",
  edad,
  " años y eres ",
  puesto
))
# A tibble: 3 × 4
  nombre  edad puesto      saludo                                       
  <chr>  <dbl> <chr>       <chr>                                        
1 Ana       20 Analista    Hola Ana! Tienes 20 años y eres Analista     
2 Luis      30 Gerente     Hola Luis! Tienes 30 años y eres Gerente     
3 María     40 Director(a) Hola María! Tienes 40 años y eres Director(a)

7.2.3 str_glue()

str_glue() es una función más avanzada que permite incluir expresiones R dentro de un string:

df |> mutate(saludo = str_glue("Hola {nombre}! Tienes {edad} años y eres {puesto}"))
# A tibble: 3 × 4
  nombre  edad puesto      saludo                                       
  <chr>  <dbl> <chr>       <glue>                                       
1 Ana       20 Analista    Hola Ana! Tienes 20 años y eres Analista     
2 Luis      30 Gerente     Hola Luis! Tienes 30 años y eres Gerente     
3 María     40 Director(a) Hola María! Tienes 40 años y eres Director(a)

7.3 Extracción de datos de strings

Un problema común es que los datos que necesitas están ocultos dentro de un string.

Hay cuatro funciones para extraer esos datos:

  • separate_longer_delim(col, delim)
  • separate_longer_position(col, width)
  • separate_wider_delim(col, delim)
  • separate_wider_position(col, width)

Funcionan como el pivot_longer() y pivot_wider() que ya conoces, pero para strings. Las dos más comunes son separate_longer_delim() y separate_wider_delim().

7.3.1 Separación por filas

df1 <- tibble(x = c("a,b,c", "d,e", "f"))
df1
# A tibble: 3 × 1
  x    
  <chr>
1 a,b,c
2 d,e  
3 f    
df1 |> 
  separate_longer_delim(x, delim = ",")
# A tibble: 6 × 1
  x    
  <chr>
1 a    
2 b    
3 c    
4 d    
5 e    
6 f    

7.3.2 Separación por columnas

df3 <- tibble(x = c("a10.1.2022", "b10.2.2011", "e15.1.2015"))
df3
# A tibble: 3 × 1
  x         
  <chr>     
1 a10.1.2022
2 b10.2.2011
3 e15.1.2015
df3 |> 
  separate_wider_delim(
    x,
    delim = ".",
    names = c("code", "edition", "year")
  )
# A tibble: 3 × 3
  code  edition year 
  <chr> <chr>   <chr>
1 a10   1       2022 
2 b10   2       2011 
3 e15   1       2015 

7.4 Letras individuales

7.4.1 Longitud del string

babynames |>
  count(length = str_length(name), wt = n)
# A tibble: 14 × 2
   length        n
    <int>    <int>
 1      2   338150
 2      3  8589596
 3      4 48506739
 4      5 87011607
 5      6 90749404
 6      7 72120767
 7      8 25404066
 8      9 11926551
 9     10  1306159
10     11  2135827
11     12    16295
12     13    10845
13     14     3681
14     15      830
babynames |> 
  filter(str_length(name) == 15) |> 
  count(name, wt = n, sort = TRUE)
# A tibble: 34 × 2
   name                n
   <chr>           <int>
 1 Franciscojavier   123
 2 Christopherjohn   118
 3 Johnchristopher   118
 4 Christopherjame   108
 5 Christophermich    52
 6 Ryanchristopher    45
 7 Mariadelosangel    28
 8 Jonathanmichael    25
 9 Christianjoseph    22
10 Christopherjose    22
# ℹ 24 more rows