library(stringr)
library(htmlwidgets)
string1 <- "Esta es una cadena de caracteres"
string2 <- 'Si quiero incluir "comillas" dentro de la cadena, uso comillas simples'
Cuando se nos olvida cerrar comillas quedamos atrapados en la consola, el símbolo cambia de > a +
"Esta es una cadena de caracteres sin comillas de cierre
+
+
+PRESIONA ESCAPE PARA SALIR"
Para incluir comillas sencillas o dobles en una cadena de texto debes escaparlas
comilla_doble <- "\"" # o '"'
comilla_simple <- '\'' # o "'"
Ten cuidado con el hecho de que la representación impresa de una cadena no es equivalente a la cadena misma, ya que la representación muestra las barras utilizadas para “escapar” caracteres,
x <- c('\'', '\\')
x
## [1] "'" "\\"
Para imprimir la cadena en sí misma utiliza la siguiente función:
writeLines(x)
## '
## \
Ver la longitud de un string
str_length(c("hola","como estas", "buenas tardes"))
## [1] 4 10 13
Concatenar strings
str_c("a","b","c", sep = ", ")
## [1] "a, b, c"
Puedes utilizar un vector para agregar el mismo prefijo o sufijo a varias cadenas
str_c("prefix-", c("a","b","c"), "-suffix")
## [1] "prefix-a-suffix" "prefix-b-suffix" "prefix-c-suffix"
La concatenación de cadenas se va a saltar los valores perdidos (NA)
x <- c("abc", NA)
str_c("hola", x, "adios", sep = " ")
## [1] "hola abc adios" NA
Observa el comportamiento cuando concatenas vectores de la misma longitud
x <- c("abc", "de")
str_c(c(1,2), x, c(3,4), sep = " ")
## [1] "1 abc 3" "2 de 4"
La concatenación puede depender de condicionales
name <- "Alejandro Magno"
momento_del_dia <- "tarde"
birthday <- FALSE
str_c(
"Buena ", momento_del_dia," ", name,
if(birthday) " y FELIZ CUMPLEA?OS",
"."
)
## [1] "Buena tarde Alejandro Magno."
Colapsando vectores
Si queremos colapsar un vector de strings en un solo string, usaremos la función collapse():
str_c(c("a", "b", "c"), collapse = ",")
## [1] "a,b,c"
Extraer subconjuntos de un string
x <- c("Manzanas", "Peras", "Limones", "Platanos")
Tomando las posiciones a partir del inicio
str_sub(x, 1,3)
## [1] "Man" "Per" "Lim" "Pla"
Tomando las posiciones a partir del final
str_sub(x, -3, -1)
## [1] "nas" "ras" "nes" "nos"
Transformando un string
Cambiando a minúscula la primer letra
str_sub(x, 1, 1) <- str_to_lower(str_sub(x, 1, 1))
Cambiando a mayúsculas el string completo
str_to_upper(x)
## [1] "MANZANAS" "PERAS" "LIMONES" "PLATANOS"
Cambiando el string completo a formato de título
str_to_title(x)
## [1] "Manzanas" "Peras" "Limones" "Platanos"
Ordenando un string
Para la función de ordenamiento importa el idioma
str_sort(x, locale = "es")
## [1] "limones" "manzanas" "peras" "platanos"
En hawaiano las vocales van primero
str_sort(x, locale = "haw") # Hawaiano
## [1] "limones" "manzanas" "peras" "platanos"
Una expresión regular nos permite buscar un patrón en una cadena de texto.
La función str_view nos ayuda a visualizar las ocurrencias del patrón
x <- c("manzana", "banana", "pera", "pomelo", "mango")
str_view(x,"an") # buscando el patrón an
## [1] │ m<an>z<an>a
## [2] │ b<an><an>a
## [5] │ m<an>go
Existen caracteres con significado especial. Por ejemplo, el punto significa cualquier caracter. La siguiente expresión regular busca una o entre cualesquiera dos caracteres excluyendo el inicio de la palabra y el final de la palabra
str_view(x, ".o.")
## [4] │ <pom>elo
Entonces,¿cómo busco un punto? Para esto debo “escapar” el caracter especial para que pueda ser utilizado su significado literal. Para escapar un caracter uso dos diagonales invertidas (\)
dot <- "\\."
str_view(c("abc", "a.c", "bc"), dot)
## [2] │ a<.>c
Otros caracteres con significado especial:
El siguiente patrón busca todo lo que empiece con p
str_view(x, "^p")
## [3] │ <p>era
## [4] │ <p>omelo
Ahora busquemos todo lo que termine en a
(str_view(x, "a$"))
## [1] │ manzan<a>
## [2] │ banan<a>
## [3] │ per<a>
Existen otros símbolos que nos ayudan a hacer búsquedas:
\d –> Cualquier digito
\s –> Cualquier espacio
[abc] –> a o b o c
[^abc] –> Cualquier cosa excepto a o b o c
* –> Coincide cero o más veces.
+ –> Coincide una o más veces.
? –> Coincide cero o una vez.
{n} –> Coincide exactamente n veces.
{n,} –> Coincide al menos n veces.
{,m} –> Coincide a lo más m veces.
{n,m} –> Coincide de n a m veces.
x <- "MDCCCLXXXVIII"
str_view(x, "CC+") # Una C seguida de una o más C
## [1] │ MD<CCC>LXXXVIII
str_view(x, "C[LX]+") # Una C seguida de una o más L o X
## [1] │ MDCC<CLXXX>VIII
str_view(x, "C{2}") # Exactamente dos C
## [1] │ MD<CC>CLXXXVIII
str_view(x, "C{2,3}") # Entre 2 y 3 C
## [1] │ MD<CCC>LXXXVIII
*¿Cómo sabemos si el patrón que buscamos existe en las cadenas de texto de nuestro vector? Utilicemos str_detect
fruits <- c("banana", "coco", "papaya", "manzana", "pera", "pepino")
str_detect(fruits, "a")
## [1] TRUE FALSE TRUE TRUE TRUE FALSE
Ahora utilicemos el conjunto de datos nativo de R: words
head(words)
## [1] "a" "able" "about" "absolute" "accept" "account"
length(words)
## [1] 980
¿Cuántas palabras empiezan por j?
sum(str_detect(words, "^j"))
## [1] 6
¿% de palabras que empiezan por vocal?
mean(str_detect(words, "^[aeiou]"))
## [1] 0.1785714
¿% de palabras que acaban por vocal?
mean(str_detect(words, "[aeiou]$"))
## [1] 0.2765306
¿Como encontraríamos todas las palabras que no contienen ni una vocal?
## [1] 6
Extrayendo las palabras que cumplen con el patrón
Todas las palabras que acaban en vocal:
head(str_subset(words, "[aeiou]$"))
## [1] "a" "able" "absolute" "achieve" "active" "advertise"
length(str_subset(words, "[aeiou]$"))
## [1] 271
Ahora aplicaremos algunas de funciones que hemos aprendido sobre un tibble
library(tidyverse)
df <- tibble(
words = words,
i = seq_along(words)
)
summary(df)
## words i
## Length:980 Min. : 1.0
## Class :character 1st Qu.:245.8
## Mode :character Median :490.5
## Mean :490.5
## 3rd Qu.:735.2
## Max. :980.0
df %>%
head
## # A tibble: 6 × 2
## words i
## <chr> <int>
## 1 a 1
## 2 able 2
## 3 about 3
## 4 absolute 4
## 5 accept 5
## 6 account 6
Mantener solo las palabras que acaban en x
df %>%
filter(str_detect(words, "x$"))
## # A tibble: 4 × 2
## words i
## <chr> <int>
## 1 box 108
## 2 sex 747
## 3 six 772
## 4 tax 841
Contando número de aparaciones
Podemos hacer uso de la función str_count() que en vez de dar una condición booleana de TRUE or FALSE como str_detect(), cuenta el número de veces que aparece un carácter dentro de un string
str_count(fruits, "a")
## [1] 3 0 3 3 1 0
Si combinamos la cuenta con otras funciones nativas o estadísticas podemos obtener calculos interesantes, por ejemplo, podemos obtener el promedio de las vocales por palabra
mean(str_count(words, "[aeiou]"))
## [1] 1.991837
Genera un tibble que contenga el número de consonantes y el número de vocales por palabra. Utiliza la función mutate que viste en las sesiones anteriores de este curso
## # A tibble: 980 × 4
## words i vowels consonants
## <chr> <int> <int> <int>
## 1 a 1 1 0
## 2 able 2 2 2
## 3 about 3 3 2
## 4 absolute 4 4 4
## 5 accept 5 2 4
## 6 account 6 3 4
## 7 achieve 7 4 3
## 8 across 8 2 4
## 9 act 9 1 2
## 10 active 10 3 3
## # ℹ 970 more rows
Extrayendo las secciones que son reconocidas por un patrón
library(datos)
sustantivo <- "(el|la|los|las|lo|un|una|unos|unas) ([^ ]+)"
tiene_sustantivo <- oraciones %>%
str_subset(sustantivo)
tiene_sustantivo %>%
str_extract(sustantivo) %>%
head
## [1] "los de" "el camión" "la mejor" "la cuenta" "las ruinas."
## [6] "la hoja"
str_extract() nos devuelve la coincidencia completa; str_match() nos entrega cada componente. Los componentes están delimitados por los paréntesis dentro de la expresión regular
tiene_sustantivo %>%
str_match(sustantivo) %>%
head
## [,1] [,2] [,3]
## [1,] "los de" "los" "de"
## [2,] "el camión" "el" "camión"
## [3,] "la mejor" "la" "mejor"
## [4,] "la cuenta" "la" "cuenta"
## [5,] "las ruinas." "las" "ruinas."
## [6,] "la hoja" "la" "hoja"
Si tus datos están en un tibble, suele ser más fácil utilizar tidyr::extract() el cual funciona como str_match(). Requieres asignarle un nombre a cada componente, debido a que cada uno de estos se asignará a una nueva columna
tibble(oracion = oraciones) %>%
tidyr::extract(
oracion, c("articulo", "sustantivo"), "(el|la|los|las|un|una|unos|unas) ([^ ]+)",
remove = FALSE
)
## # A tibble: 50 × 3
## oracion articulo sustantivo
## <chr> <chr> <chr>
## 1 Las casas están construidas de ladrillos de arcilla roja. los de
## 2 La caja fue arrojada al lado del camión estacionado. el camión
## 3 El domingo es la mejor parte de la semana. la mejor
## 4 Agrega a la cuenta de la tienda hasta el último centavo. la cuenta
## 5 Nueve hombres fueron contratados para excavar las ruinas. las ruinas.
## 6 Pega la hoja en el fondo azul oscuro. la hoja
## 7 Instalaron azulejos verdes en la cocina. la cocina.
## 8 Si arrojo la taza azul al suelo se romperá. la taza
## 9 Dos peces azules nadaban en el tanque. el tanque.
## 10 El ancho camino brillaba bajo el calor del sol. el calor
## # ℹ 40 more rows
Si te interesa extraer todas las coincidencias para cada cadena, tienes que utilizar str_match_all(), el cual regresará una lista.
tiene_sustantivo %>%
str_match_all(sustantivo) %>%
head
## [[1]]
## [,1] [,2] [,3]
## [1,] "los de" "los" "de"
## [2,] "la roja." "la" "roja."
##
## [[2]]
## [,1] [,2] [,3]
## [1,] "el camión" "el" "camión"
##
## [[3]]
## [,1] [,2] [,3]
## [1,] "la mejor" "la" "mejor"
## [2,] "la semana." "la" "semana."
##
## [[4]]
## [,1] [,2] [,3]
## [1,] "la cuenta" "la" "cuenta"
## [2,] "la tienda" "la" "tienda"
## [3,] "el último" "el" "último"
##
## [[5]]
## [,1] [,2] [,3]
## [1,] "las ruinas." "las" "ruinas."
##
## [[6]]
## [,1] [,2] [,3]
## [1,] "la hoja" "la" "hoja"
## [2,] "el fondo" "el" "fondo"
EJERCICIOS
## [,1] [,2] [,3]
## [1,] "dos para" "dos" "para"
## [2,] "dos pastillas." "dos" "pastillas."
## [3,] "una ave" "una" "ave"
## [4,] "una llama" "una" "llama"
## [5,] "un cartel" "un" "cartel"
## [6,] "tres gráficos." "tres" "gráficos."
## [,1] [,2] [,3]
## [,1] [,2] [,3]
## [1,] "teorico-practico" "teorico" "practico"
Ahora, ¿Cómo encontrar todas las frases que contengan un determinado color?
colors <- c("red", "orange", "yellow", "green", "blue", "purple")
color_match <- str_c(colors, collapse = "|")
color_match
## [1] "red|orange|yellow|green|blue|purple"
has_color <- str_subset(sentences, color_match)
head(has_color)
## [1] "Glue the sheet to the dark blue background."
## [2] "Two blue fish swam in the tank."
## [3] "The colt reared and threw the tall rider."
## [4] "The wide road shimmered in the hot sun."
## [5] "See the cat glaring at the scared mouse."
## [6] "A wisp of cloud hung in the blue air."
matches <- str_extract(has_color, color_match)
head(matches)
## [1] "blue" "blue" "red" "red" "red" "blue"
¿En cuáles oraciones aparece más de un color?
str_count(sentences, color_match) %>%
head
## [1] 0 1 0 0 0 0
more_than_one <- sentences[str_count(sentences, color_match) > 1]
str_view_all(more_than_one,color_match)
## Warning: `str_view_all()` was deprecated in stringr 1.5.0.
## ℹ Please use `str_view()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## [1] │ It is hard to erase <blue> or <red> ink.
## [2] │ The <green> light in the brown box flicke<red>.
## [3] │ The sky in the west is tinged with <orange> <red>.
str_extract_all(more_than_one, color_match) %>%
head
## [[1]]
## [1] "blue" "red"
##
## [[2]]
## [1] "green" "red"
##
## [[3]]
## [1] "orange" "red"
Reemplazando la primer vocal por guión bajo
str_replace(fruits, "[aeiou]", "_")
## [1] "b_nana" "c_co" "p_paya" "m_nzana" "p_ra" "p_pino"
Reemplazando todas las vocales por guión bajo
str_replace_all(fruits, "[aeiou]", "_")
## [1] "b_n_n_" "c_c_" "p_p_y_" "m_nz_n_" "p_r_" "p_p_n_"
Otras opciones de reemplazo haciendo uso de un vector entero:
str_replace_all(c("1 coche", "2 telefonos", "3 amigos"),
c("1" = "un", "2" = "dos", "3" = "tres")
)
## [1] "un coche" "dos telefonos" "tres amigos"
Incercambiar el orden de la segunda y la tercera palabra en una frase
sentences %>%
head(5)
## [1] "The birch canoe slid on the smooth planks."
## [2] "Glue the sheet to the dark blue background."
## [3] "It's easy to tell the depth of a well."
## [4] "These days a chicken leg is a rare dish."
## [5] "Rice is often served in round bowls."
sentences %>%
str_replace("([^ ]+) ([^ ]+) ([^ ]+)", "\\1 \\3 \\2") %>%
head(5)
## [1] "The canoe birch slid on the smooth planks."
## [2] "Glue sheet the to the dark blue background."
## [3] "It's to easy tell the depth of a well."
## [4] "These a days chicken leg is a rare dish."
## [5] "Rice often is served in round bowls."
Separando las palabras por espacio
sentences %>%
head(3) %>%
str_split(" ") %>%
.[[1]]
## [1] "The" "birch" "canoe" "slid" "on" "the" "smooth"
## [8] "planks."
Una forma de conocer las posiciones de inicio y de fin de cada palabra dentro de una frase:
sent <- "Frase de ejemplo para provar. Y esto es todo."
str_locate_all(sent, "[aeiou] ")
## [[1]]
## start end
## [1,] 5 6
## [2,] 8 9
## [3,] 16 17
## [4,] 21 22
## [5,] 36 37
str_view_all(sent, "[aeiou] ")
## [1] │ Fras<e >d<e >ejempl<o >par<a >provar. Y est<o >es todo.
str_sub(sent, 8, 9)
## [1] "e "
Ejemplo expresión regular para saber si es un teléfono:
phone <- regex("
\\(? # paréntesis de oportura opcionales
(\\d{3}) # código de área (ej: barcelona 34)
[)-]? # cierre de paréntesis, guión o espacio opcionales
(\\d{3}) # tres dígitos de teléfono
[ -]? # espacio o guión opcional
(\\d{3}) # tres digitos finales
", comments = TRUE)
str_detect("971-123-456", "\\(?(\\d{3})[)-]?(\\d{3})[ -]?(\\d{3})")
## [1] TRUE
str_match("971-123-456", phone)
## [,1] [,2] [,3] [,4]
## [1,] "971-123-456" "971" "123" "456"
stringr está construido sobre la base del paquete stringi. stringr es útil cuando estás aprendiendo, ya que presenta un set mínimo de funciones, que han sido elegidas cuidadosamente para inlcuir las funciones de manipulación de cadenas más comunes. stringi, por su parte, está diseñado para ser completo Contiene casi todas las funciones que podrías necesitar: stringi tiene 256 funciones, frente a las 49 de stringr.
Si en algún momento te encuentras en dificultades para hacer algo en stringr , vale la pena darle una mirada a stringi. Ambos paquetes funcionan de manera muy similar, por lo que deberías poder traducir tu conocimiento sobre stringr de manera natural. La principal diferencia es el prefijo: str_ vs. stri_.