Un string (una cadena) es un fragmento de texto entre comillas. Cualquier versión de R con soporte en la actualidad codifica los strings en UTF-8, así que se puede dar soporte a la mayoría de los idiomas del mundo.
mystring <- "some text"
mystring
#> [1] "some text"
typeof(mystring)
#> [1] "character"
Lamentablemente, la terminología puede resultar confusa para quienes ya conocen otros lenguajes.
Aunque el type es character, R no distingue entre una sola letra (a la que en varios otros lenguajes se le llama char, pero no en R) y un string largo.
Ambas son un solo elemento y pueden ir entre comillas simples ' ' o dobles " " de manera intercambiable.
La guía de estilo recomienda usar comillas dobles, salvo cuando quieras usar comillas dobles dentro del string sin escaparlas.
str2 <- 'String with "quotes"' # convenience format
str2
#> [1] "String with \"quotes\"" # standard format
Un character vector es, entonces, un vector de strings, donde cada string es un solo elemento.
s <- c("some", "strings")
s
#> [1] "some" "strings"
length(s)
#> [1] 2
length(s[1]) # the number of vector elements, not the string length
#> [1] 1
nchar(s[1]) # the number of characters in the string "some"
#> [1] 4
En el ejemplo anterior, length(s[1]) equivale a length("some"): la cantidad de elementos del vector, no la longitud del string.
Manipular un string individual es, por supuesto, posible, como con nchar() en el ejemplo anterior, pero requiere funciones concretas que veremos más abajo.
Casi todo es posible en R base, pero a muchas personas que programan les parece que el soporte para manipular strings es más bien limitado y confuso.
Por suerte, existen paquetes de tidyverse mucho más intuitivos, flexibles y coherentes entre sí.
Todavía hay mucho código heredado que usa funciones de strings del estilo antiguo. Esto incluye la mayoría de las soluciones de la comunidad en Exercism.
Además, para tareas pequeñas puede resultar útil usar funciones integradas en lugar de importar una biblioteca grande. Quienes mantienen el track de R suelen adoptar este enfoque cuando escriben soluciones de ejemplo para validar los ejercicios.
Por lo tanto, todavía vale la pena aprender algo sobre los enfoques antiguos.
ncharDevuelve la cantidad de caracteres de un string.
nchar("string")
#> [1] 6
nchar("Hrōðgār") # a person in Beowulf, written in Old English
#> [1] 7
El tema (¡complicado!) de qué significa «carácter» queda fuera del alcance de esta introducción. Solo fíjate en un par de puntos de los ejemplos anteriores:
\0 (lo que sumaría 1 a la longitud).paste y paste0
Combina una cantidad arbitraria de strings en un solo string.
De forma opcional, se puede indicar un separador para paste: el valor por defecto es un espacio.
paste0(v) equivale a paste(v, sep = "").
paste("bits", "of", "a", "string")
#> [1] "bits of a string"
paste0("bits", "of", "a", "string")
#> [1] "bitsofastring"
sprintfPara un control más fino del ensamblado de strings, R copia la función sprintf de C (y de varios lenguajes posteriores: Wikipedia enumera alrededor de 30).
r <- 5.3
pi <- 3.14159
sprintf("A circle of radius %.1f has area %.2f", r, pi * r^2)
#> [1] "A circle of radius 5.3 has area 88.25"
trimwsLos espacios en blanco al principio o al final se pueden eliminar con trimws():
s <- " messy string "
trimws(s)
#> [1] "messy string"
Existe un parámetro which = "left" (o "right") para evitar recortar ambos extremos.
substrOpera sobre un solo string y devuelve un substring entre dos límites (ambos incluidos).
substr("Exercism", 5, 7)
#> [1] "cis"
strsplitDivide un string en una lista de R, a partir de un string separador. El separador es obligatorio (no tiene valor por defecto), pero puede ser un string vacío.
strsplit("R, Python, Julia", ", ")
[[1]]
#> [1] "R" "Python" "Julia"
strsplit("Exercism", "")
[[1]]
#> [1] "E" "x" "e" "r" "c" "i" "s" "m"
Las listas se tratan en otro concepto.
Si todavía no has llegado a esa parte del temario, por ahora basta con saber que la función unlist() (en este caso) convierte una lista en un vector.
unlist(strsplit("Exercism", ""))
#> [1] "E" "x" "e" "r" "c" "i" "s" "m"
Siendo generosos, podríamos decir que las funciones de strings del estilo antiguo no son lo mejor que R tiene para ofrecer (hay opiniones menos generosas).
Para mejorar la situación, la biblioteca stringr está en desarrollo desde 2009 y hoy es una parte clave de la colección Tidyverse.
Impórtala en tu espacio de nombres con library(stringr) o library(tidyverse).
Algunas de sus características principales son:
str_ e intentan dejar claro para qué sirven.Como todos los paquetes de Tidyverse, stringr tiene buena documentación, normalmente escrita por quienes crearon el paquete.
El uso de los pipes |> para conectar funciones se trata con más detalle en otras partes del temario.
Por ahora, es útil saber que:
El ejemplo de abajo ilustra la sintaxis. Las funciones individuales se tratan más adelante.
library(stringr)
"Monday-25-February" |>
str_split("-") |>
unlist() |> # [1] "Monday" "25" "February"
str_sub(1, 3) |> # [1] "Mon" "25" "Feb"
str_to_upper() |> # [1] "MON" "25" "FEB"
str_flatten(collapse = ", ")
#> [1] "MON, 25, FEB"
str_length cuenta puntos de código (similar a nchars).
Otras funciones manipulan los espacios en blanco, como str_trim() y str_squish().
A menudo esta es una tarea de limpieza esencial al inicio de cualquier proyecto de ciencia de datos.
# The first 3 kernels in JuPyteR notebooks:
str_length(c("Julia", "Python", "R")) #> [1] 1 6 5
#> [1] 5 6 1
str_pad(c("Julia", "Python", "R"), 8, "right") # add spaces if necessary
#> [1] "Julia " "Python " "R "
str_trim("Julia Python R ") # remove leading & trailing whitespace
#> [1] "Julia Python R"
str_squish("Julia Python R ") # trim, collapse multiple spaces
#> [1] "Julia Python R"
La función str_sub(string, start, end) devuelve el substring desde start hasta end (ambos incluidos), mientras que str_sub_all() puede operar sobre varios strings.
Hay mucha flexibilidad.
start y end toman por defecto el primer y el último carácter, respectivamente.
Pueden ser vectores de índices.
A diferencia de la indexación de vectores (algo que se agradece), los valores negativos cuentan desde el final del string, al estilo de Python.
s <- "abcdefgh"
str_sub(s, 2, 4)
#> [1] "bcd"
str_sub(s, 5)
#> [1] "efgh"
str_sub(s, -3, -2)
#> [1] "fg"
str_sub(s, c(1, 4), c(2, 5))
#> [1] "ab" "de"
str_sub(s, c(1, 4, 6), c(2, 5, -1))
#> [1] "ab" "de" "fgh"
s |> str_sub(2, 4) # these functions are designed for pipes
#> [1] "bcd"
str_flatten convierte un character vector en un solo string.
El argumento collapse se inserta entre cada elemento y su valor por defecto es "".
c("R", "Julia", "Python") |> str_flatten()
#> [1] "RJuliaPython"
c("R", "Julia", "Python") |> str_flatten(collapse = " - ")
#> [1] "R - Julia - Python"
str_c convierte varios character vectors en un solo character vector, con reciclaje cuando sea necesario.
str_c(LETTERS[1:8], 1:8, sep = ":")
#> [1] "A:1" "B:2" "C:3" "D:4" "E:5" "F:6" "G:7" "H:8"
str_glue trae a R una interpolación de strings sencilla.
Las expresiones dentro de llaves { } se interpretan y se sustituye su representación como texto.
r <- 5.3
pi <- 3.14159
str_glue("A circle of radius {r} has area {pi * r^2}")
A circle of radius 5.3 has area 88.2472631
Un uso muy común de R es acomodar datos desordenados en un formato consistente para analizarlos. Para ayudar con esto, hay varias maneras de dividir texto en substrings. La mayoría quedan fuera del alcance de esta introducción.
str_split_1 es la más simple: convierte un solo string en un vector de partes, divididas según un patrón especificado (no hay patrón por defecto).
s <- "R Julia Python"
str_split_1(s, " ")
#> [1] "R" "Julia" "Python"
Algunos lenguajes (sobre todo europeos) distinguen entre letras MAYÚSCULAS y minúsculas.
Hay un conjunto de funciones de stringr para convertir entre ambas, de manera adecuada según la configuración regional:
str_to_lower()str_to_upper()str_to_title() : la primera letra de cada palabra a mayúsculastr_to_sentence() : la primera letra de la oración a mayúsculastr_to_upper("elixir") # defaults to locale = "en"
#> [1] "ELIXIR"
str_to_upper("ελληνικά") # infers Greek
#> [1] "ΕΛΛΗΝΙΚΆ"
str_to_title("the cat sat on the mat")
#> [1] "The Cat Sat On The Mat"
str_to_sentence("the cat sat on the mat")
#> [1] "The cat sat on the mat"
Para reemplazar substrings según coincidencias de patrones, str_replace() cambia la primera aparición del patrón y str_replace_all() cambia todas las apariciones.
Para reemplazar substrings según el índice de caracteres, existe una forma de asignación de str_sub().
s <- "abcde"
str_sub(s, 3, 4) <- "yz"
s
#> [1] "abyze"
En este ejercicio vas a procesar líneas de log.
Cada línea de log es un string con el siguiente formato: "[<LEVEL>]: <MESSAGE>".
Hay tres niveles de log diferentes:
INFOWARNINGERRORTienes tres tareas, y cada una recibe una línea de log y te pide hacer algo con ella.
Puedes usar las funciones heredadas de R base o la librería stringr, y ambas pueden darte soluciones cortas y viables.
Implementa la función message para que devuelva el mensaje de una línea de log:
message("[ERROR]: Invalid operation")
#> "Invalid operation"
Cualquier espacio en blanco al principio o al final debe eliminarse:
message("[WARNING]: Disk almost full\r\n")
#> "Disk almost full"
Implementa la función log_level para que devuelva el nivel de log de una línea de log, que debe devolverse en minúsculas:
log_level("[ERROR]: Invalid operation")
#> "error"
Implementa la función reformat, que reformatea la línea de log: primero pone el mensaje y después el nivel de log entre paréntesis:
reformat("[INFO]: Operation completed")
#> "Operation completed (info)"
Regístrate en Exercism para aprender y dominar R con 21 conceptos111 ejercicios y mentoría humana real, todo gratis.