2 Aspectos básicos de R

Fecha última actualización: 2024-07-14

Instalación/carga librerías utilizadas

if (!require(utils)) install.packages('utils') 
library(utils)
if (!require(tidyverse)) install.packages('tidyverse') 
library(tidyverse)

2.1 Tipos y estructuras de datos

El operador de asignación en R es el símbolo = o más comúnmente <-. Por ejemplo a <- 5 asigna a a el valor 5. Los operadores = y <- producen en la mayoría de los casos el mismo resultado, pero no son idénticos y en ciertas ocasiones usar uno en lugar de otro puede producir un error.

Si se realiza mediante código cualquier operación o llamada a una función y no se asigna a ninguna variable, el resultado se imprime y no se almacena.

Tipos de datos

Tipo Ejemplos
character
  • "mi texto"
factor
  • as.factor("Europe")
numeric
  • 5
  • as.numeric("5")
logical
  • TRUE
  • FALSE
dato no disponible
  • NA
date
  • as.Date("2022-12-31")

La coerción nos permite cambiar los tipos de los datos. Por ejemplo as.Date("2022-12-31") pasa el campo de texto “2022-12-31” a un dato tipo fecha. Otros ejemplos de funciones de coerción son as.numeric(), o as.character().

Cuando leemos los datos de una tabla, debemos prestar especial atención a examinar los tipos asignados a los campos y comprobar, en particular, que los campos con números y fechas se han identificado como tales. En caso contrario, lo primero que hay que hacer es resolver esa incidencia.

El tipo factor se utiliza para clasificar, y se asocia, a las denominadas variables categóricas. Por ejemplo, en una tabla con información de países, la información sobre continentes es típicamente una variable categórica tipo factor. Para acelerar su gestión, las variables tipo factor se almacenan internamente como una mezcla entre caracteres y números, y por tanto no son lo mismo que las variables tipo character y esto puede ocasionar algún problema al comparar ambos tipos de variables.

Manipulación de strings

Un caso especialmente importante de tipo de datos son los strings de caracteres que con frecuencia tenemos que manipular para obtener los resultados que necesitamos. Por ello vamos a ver a continuación algunos procesos básicos en la manipulación de strings.

Función paste y paste0

La función paste permite combinar texto y variables para construir un string

a <- 5   
paste("la velocidad es",a, "km2")
## [1] "la velocidad es 5 km2"

La función paste inserta espacios blancos entre los strings o variables que combina. paste0 hace lo mismo que paste pero sin insertar espacios en blanco.

Extraer un trozo de un string

s <- "esto es un string"  
# extraemos las posiciones de la 3 a 14
substr(s,3,14)
## [1] "to es un str"

Extraer una palabra de un string

Cuando nuestro string es una frase con palabras separadas por espacios en blanco, la función word de la librería tidyverse nos permite extraer la palabra que ocupa una posición determinada en la frase. Por ejemplo, el siguiente código extrae la tercera palabra del string s declarado antes.

word(s,3)
## [1] "un"

Comparación de strings

s1 <- "ABC"  
s2 <- "abc"
#comparación literal
s1==s2
## [1] FALSE
#comparación pasando todo a minúsculas
tolower(s1)==tolower(s2)
## [1] TRUE
#detectar si un string es parte de otro 
str_detect("UNITED NATIONS","NAT")
## [1] TRUE

Distancia entre strings con adist()

En ocasiones, tenemos que comparar strings que son parecidos pero no idénticos. Por ejemplo, podemos querer que se reconozcan como similares los strings “Antonio”, “San antonio” y “S. Antonio”. La función adist de la librería utils nos permite calcular una distancia entre dos strings que vale cero cuando son idénticos y que va siendo mayor cuanto más difieran. Esta función tiene diversos parámetros para ajustar como queremos comparar los strings. Utilizaremos en el futuro esta función para obtener, dado un string, el más cercano a él en un vector de strings.

# comparación literal
adist("Antonio","San antonio")
##      [,1]
## [1,]    5
adist("S. Antonio","San antonio")
##      [,1]
## [1,]    3
# comparación ignorando minúsculas/mayúsculas
adist("Antonio","San antonio",ignore.case=TRUE)
##      [,1]
## [1,]    4
# comparación del primer string con un trozo del segundo
adist("Antonio","S. antonio",ignore.case=TRUE,partial=TRUE)
##      [,1]
## [1,]    0
# con la opción partial=TRUE, el orden de los strings afecta al resultado
adist("S. antonio","Antonio",ignore.case=TRUE,partial=TRUE)
##      [,1]
## [1,]    3

Manejo de fechas

Dado que, con frecuencia, los datos tienen asociadas fechas, mostraremos a continuación algunos ejemplos de manejo de formato de fechas:

as.Date("2022-12-25") # Coerción a fecha usando el formato de fecha estándar
## [1] "2022-12-25"
as.Date("25/12/2022",format = "%d/%m/%Y") # lectura formato fecha no estándar
## [1] "2022-12-25"
# extraer información fecha
format(as.Date("2022-12-25"),"%A, %B, %d, %y") 
## [1] "domingo, diciembre, 25, 22"
format(as.Date("2022-12-25"),"%a, %b, %d, %Y, día dentro de la semana: %u") 
## [1] "do., dic., 25, 2022, día dentro de la semana: 7"
format(as.Date("2022-12-25"),"Nº semana del año: %W, día del año : %j") 
## [1] "Nº semana del año: 51, día del año : 359"

Para más información sobre los formatos de fecha ejecutar en la consola ??strptim y elegir la opción base::format.POSIXct.

Hay programas que codifican las fechas como números a partir de una fecha de referencia (Por ejemplo en EXCEL la fecha de referencia es “1899-12-30”). Podemos pasar esta codificación numérica al formato fecha con la instrucción:

# convertir el número 0 en fecha
as.Date(0, origin = "1899-12-30")
## [1] "1899-12-30"
# convertir el número 45000 en fecha
as.Date(45000, origin = "1899-12-30")
## [1] "2023-03-15"

En ocasiones, las fechas asociadas a los datos vienen dadas por meses, por ejemplo “2008-02” o por trimestres, por ejemplo “2008 Q2”. Para manejar fechas de esta manera la librería lubridate suministra algunas herramientas útiles. Veamos algunos ejemplos:

ym("2008-02") # la función ym() devuelve como fecha el primer día del mes del string "2008-02" 
## [1] "2008-02-01"
ceiling_date(ym("2008-02"),"month")-1 # último día del mes 
## [1] "2008-02-29"
ym("2008/02") #el argumento de ym() admite  varios formatos
## [1] "2008-02-01"
ym("200802") #el argumento de ym() admite  varios formatos
## [1] "2008-02-01"
my("02/2008") #si el mes va delante del año podemos usar my()
## [1] "2008-02-01"
yq("2008 Q2") # la función yq() devuelve como fecha el primer día del trimestre "2008 Q2" 
## [1] "2008-04-01"
ceiling_date(yq("2008 Q2"),"quarter")-1 # último día del trimestre 
## [1] "2008-06-30"
yq("2008Q2") # el argumento de yq() admite varios formatos
## [1] "2008-04-01"

Vectores

Creación de un vector concatenando valores

v <- c(1,7,9)   
paste("el segundo elemento de v es : ",v[2]) 
## [1] "el segundo elemento de v es :  7"

Creación de un vector repitiendo valores

v <- rep(1,6)
v
## [1] 1 1 1 1 1 1
paste("la longitud del vector es : ",length(v)) 
## [1] "la longitud del vector es :  6"

Creación de un vector usando números consecutivos

3:7
## [1] 3 4 5 6 7

Creación de un vector con valores descendentes

seq(7, 3, by = -1)
## [1] 7 6 5 4 3

Creación de un vector con tamaño asignado pero sin rellenar

numeric(5)  # vector de números de tamaño 5
## [1] 0 0 0 0 0
character(5)  # vector de strings de tamaño 5
## [1] "" "" "" "" ""

Creación de un vector usando fechas consecutivas

as.Date("2022-12-31")+0:3
## [1] "2022-12-31" "2023-01-01" "2023-01-02" "2023-01-03"

Con frecuencia es necesario crear un vector de fechas espaciadas por meses, semanas, etc.. Esto lo podemos conseguir con la función seq. Por ejemplo, veamos como se construye un vector con los primeros seis meses del año 2023

seq(as.Date("2023-01-01"), as.Date("2023-06-01"), by = "months")
## [1] "2023-01-01" "2023-02-01" "2023-03-01" "2023-04-01" "2023-05-01"
## [6] "2023-06-01"

Eliminar elementos de un vector

x <- c(2,3,2,3,5)
x[-2] # eliminamos la segunda posición 
## [1] 2 2 3 5
x[-(2:3)] # eliminamos la segunda y tercera posición 
## [1] 2 3 5
x[! x %in% c(2,5)]  #eliminamos todos los 2 y 5 existentes
## [1] 3 3

Reemplazar elementos de un vector

Vamos a usar la función gsub para reemplazar elementos de un vector.

x <- c("my book", "my car","your car")
gsub('my','your',x)
## [1] "your book" "your car"  "your car"
gsub('car','tree',x)
## [1] "my book"   "my tree"   "your tree"

Encontrar la posición de un valor en un vector

Vamos a usar la función which para encontrar la posición de un elemento en un vector

x <- c("my book", "my car","your car")
which(x=='my car')
## [1] 2

Extraer los elementos sin repetir de un vector

Con frecuencia, cuando leemos una tabla con factores, necesitamos saber que factores se usan. Para ello usamos la función levels que nos devuelve los elementos sin repetir de un vector de factores

levels(as.factor(c("rojo","rojo","rojo","azul","azul")))
## [1] "azul" "rojo"

Dataframes y Tibbles

Un dataframe es una matriz que puede combinar diferentes tipos de datos, por ejemplo fechas y valores numéricos. La estructura tibble es una versión mejorada de dataframe que se encuentra en la librería tidyverse. En este curso utilizaremos principalmente esta estructura de datos para manejar tablas. De hecho, salvo indicación de lo contrario, cuando hablemos en el curso de tablas, nos estaremos refiriendo a estructuras tibbles. Cuando hablemos de campos o variables nos estaremos refiriendo a las columnas (col) de la tabla y cuando hablemos de registros, nos estaremos refiriendo a las filas (row) de la tabla.

2.1.0.1 Creación manual de un tibble

tb <- tibble(
  date=as.Date("2022-12-31")+0:5,
  value=c(9,6,1,7,5,8))
tb # impresión por consola de tb
## # A tibble: 6 × 2
##   date       value
##   <date>     <dbl>
## 1 2022-12-31     9
## 2 2023-01-01     6
## 3 2023-01-02     1
## 4 2023-01-03     7
## 5 2023-01-04     5
## 6 2023-01-05     8
paste("El segundo valor del campo date del tibble es ",tb$date[2])
## [1] "El segundo valor del campo date del tibble es  2023-01-01"
paste("El tercer valor del campo value del tibble es ",tb$value[3])
## [1] "El tercer valor del campo value del tibble es  1"
paste("El tercer valor del campo value del tibble es ",tb[3,2])
## [1] "El tercer valor del campo value del tibble es  1"

2.1.0.2 Acceso primeros y últimos valores deltibble

head(tb,3) # primeras 3 filas de tb
## # A tibble: 3 × 2
##   date       value
##   <date>     <dbl>
## 1 2022-12-31     9
## 2 2023-01-01     6
## 3 2023-01-02     1
tail(tb,4) # últimas 4 filas de tb
## # A tibble: 4 × 2
##   date       value
##   <date>     <dbl>
## 1 2023-01-02     1
## 2 2023-01-03     7
## 3 2023-01-04     5
## 4 2023-01-05     8

Manejo básico de filas y columnas

nrow(tb)    # número de filas
## [1] 6
ncol(tb)    # número de columnas
## [1] 2
tb[1:3,] # selección de las 3 primeras filas
## # A tibble: 3 × 2
##   date       value
##   <date>     <dbl>
## 1 2022-12-31     9
## 2 2023-01-01     6
## 3 2023-01-02     1
tb[,2:2] # selección de la segunda columna
## # A tibble: 6 × 1
##   value
##   <dbl>
## 1     9
## 2     6
## 3     1
## 4     7
## 5     5
## 6     8
tb[1:3,2:2] # selección combinada
## # A tibble: 3 × 1
##   value
##   <dbl>
## 1     9
## 2     6
## 3     1
colnames(tb) # nombres de las columnas  
## [1] "date"  "value"
tb2 <- set_names(tb,c("date_new","value_new")) # cambiamos los nombres de las columnas  
tb2
## # A tibble: 6 × 2
##   date_new   value_new
##   <date>         <dbl>
## 1 2022-12-31         9
## 2 2023-01-01         6
## 3 2023-01-02         1
## 4 2023-01-03         7
## 5 2023-01-04         5
## 6 2023-01-05         8

2.1.0.3 Añadir un registro (fila) a un tibble

add_row(tb,date = as.Date("2023-01-25"),value=11)
## # A tibble: 7 × 2
##   date       value
##   <date>     <dbl>
## 1 2022-12-31     9
## 2 2023-01-01     6
## 3 2023-01-02     1
## 4 2023-01-03     7
## 5 2023-01-04     5
## 6 2023-01-05     8
## 7 2023-01-25    11

Concatenar los registros de varios tibbles

La función rbind() nos permite concatenar los registros de varios tibbles que tengan los mismos campos. Veamos un ejemplo:

tb1 <- tibble(
  date=as.Date("2022-12-31")+0:2,
  value=c(9,6,1))
tb2 <- tibble(
  date=as.Date("2022-12-31")+3:5,
  value=c(7,5,8))
rbind(tb1,tb2)
## # A tibble: 6 × 2
##   date       value
##   <date>     <dbl>
## 1 2022-12-31     9
## 2 2023-01-01     6
## 3 2023-01-02     1
## 4 2023-01-03     7
## 5 2023-01-04     5
## 6 2023-01-05     8

2.1.0.4 Añadir un campo (columna) a un tibble

Para añadir un campo a untibblebasta crear un vector del tamaño del numero de filas deltibbley añadir el campo altibble

tb$new_value <- 1:nrow(tb)
tb
## # A tibble: 6 × 3
##   date       value new_value
##   <date>     <dbl>     <int>
## 1 2022-12-31     9         1
## 2 2023-01-01     6         2
## 3 2023-01-02     1         3
## 4 2023-01-03     7         4
## 5 2023-01-04     5         5
## 6 2023-01-05     8         6

Cambiar un valor en todo el tibble

tb[tb==5] <- NA
tb
## # A tibble: 6 × 3
##   date       value new_value
##   <date>     <dbl>     <int>
## 1 2022-12-31     9         1
## 2 2023-01-01     6         2
## 3 2023-01-02     1         3
## 4 2023-01-03     7         4
## 5 2023-01-04    NA        NA
## 6 2023-01-05     8         6

2.1.0.5 Seleccionar registros usando slice

slice(tb,2:4)
## # A tibble: 3 × 3
##   date       value new_value
##   <date>     <dbl>     <int>
## 1 2023-01-01     6         2
## 2 2023-01-02     1         3
## 3 2023-01-03     7         4

Hacer una operación en todos los elementos de campos seleccionados

Vamos a convertir en tipo character todos los valores de los campos valuey new_value

tb %>% mutate(across(value:new_value,as.character)) 
## # A tibble: 6 × 3
##   date       value new_value
##   <date>     <chr> <chr>    
## 1 2022-12-31 9     1        
## 2 2023-01-01 6     2        
## 3 2023-01-02 1     3        
## 4 2023-01-03 7     4        
## 5 2023-01-04 <NA>  <NA>     
## 6 2023-01-05 8     6

la función mutate pertenece a la librería dplyr y se verá en detalle más adelante

Eliminar un registro de un tibble

# Eliminación segundo registro del tibble
tb %>%
   filter( row_number()!=2)
## # A tibble: 5 × 3
##   date       value new_value
##   <date>     <dbl>     <int>
## 1 2022-12-31     9         1
## 2 2023-01-02     1         3
## 3 2023-01-03     7         4
## 4 2023-01-04    NA        NA
## 5 2023-01-05     8         6

2.1.0.6 Imprimir información de un tibble

Además de ejecutar el nombre del tibble en la consola, otras formas de obtener información sobre el tibble por consola son:

print(tb,n=3) # imprime las 3 primeras filas
## # A tibble: 6 × 3
##   date       value new_value
##   <date>     <dbl>     <int>
## 1 2022-12-31     9         1
## 2 2023-01-01     6         2
## 3 2023-01-02     1         3
## # ℹ 3 more rows
str(tb) # imprime la estructura del tibble
## tibble [6 × 3] (S3: tbl_df/tbl/data.frame)
##  $ date     : Date[1:6], format: "2022-12-31" "2023-01-01" ...
##  $ value    : num [1:6] 9 6 1 7 NA 8
##  $ new_value: int [1:6] 1 2 3 4 NA 6
summary(tb) # presenta un resumen de valores estadísticos del tibble
##       date                value       new_value  
##  Min.   :2022-12-31   Min.   :1.0   Min.   :1.0  
##  1st Qu.:2023-01-01   1st Qu.:6.0   1st Qu.:2.0  
##  Median :2023-01-02   Median :7.0   Median :3.0  
##  Mean   :2023-01-02   Mean   :6.2   Mean   :3.2  
##  3rd Qu.:2023-01-03   3rd Qu.:8.0   3rd Qu.:4.0  
##  Max.   :2023-01-05   Max.   :9.0   Max.   :6.0  
##                       NA's   :1     NA's   :1

Listas

Una lista es una colección de objetos que pueden tener estructuras y tamaños distintos. Nosotros haremos poco uso de las listas en este curso dado que nuestra principal fuente de información van a ser tablas de datos que vamos a manejar con tibbles.

list("date"=as.Date("2022-12-25"), "value1"= 1:3,"value2"=1:4) # creación lista
## $date
## [1] "2022-12-25"
## 
## $value1
## [1] 1 2 3
## 
## $value2
## [1] 1 2 3 4

2.2 Funciones en R

Las funciones permiten simplificar y organizar el desarrollo de software empaquetando código para ser utilizado posteriormente de forma compacta y sencilla. En R, las funciones se suelen escribir en ficheros con extensión .R. Para poder usar las funciones creadas en un fichero .R desde cualquier código R hay que poner al principio de dicho código R la instrucción

source("NombreFichero.R")

En general, las funciones poseen unos parámetros de entrada, realizan algún tipo de operación y devuelven algo. La forma general de definir una función es

NombreFuncion <- function(parámetro 1, parámetro 2, ...){
  lineas código 
  .....
  return(resultado)
}

A continuación crearemos una función para sumar 2 números y la utilizaremos para calcular 2+3

suma <- function(x,y){
  z <- x+y  
  return(z)
}
suma(2,3)
## [1] 5

La mayor parte de las funciones de las librerías estándar como paste, as.Date, etc.., cuando reciben como argumento un vector, devuelven otro vector aplicando la función a cada elemento del vector. Por ejemplo:

d <- c("2008-01","2014-10","2023-12")
paste("la función ym() convierte",d,"en",ym(d))
## [1] "la función ym() convierte 2008-01 en 2008-01-01"
## [2] "la función ym() convierte 2014-10 en 2014-10-01"
## [3] "la función ym() convierte 2023-12 en 2023-12-01"

De la misma manera, cuando la función recibe 2 argumentos, si estos argumentos son vectores, entonces la función puede devolver un dataframecon el resultado de aplicar la función a cada combinación de los elementos de ambos vectores. Veamos un ejemplo con la función adist para comparar strings:

adist(c("Teror","Galdar"),c("Telde","Arucas","San Mateo"))
##      [,1] [,2] [,3]
## [1,]    3    6    9
## [2,]    4    5    7

Esta capacidad de las funciones para actuar en función del tipo de argumento que recibe depende de como se haya implementado la función.

Estructuras de control

Las siguientes estructuras de control permiten controlar el flujo de ejecución de un código:

  • if - else permite control el flujo a través de una condición.

  • for genera un bucle con un iterador

  • while genera un bucle con una condición de parada

  • break fuerza la terminación de un bucle

  • next fuerza el paso a la siguiente iteración de un bucle.

Operadores lógicos

  • == idéntico

  • x | y x OR y

  • x & y x AND y

  • !x not x

  • isTRUE(x) comprueba si x es TRUE

  • is.na(x) comprueba si x es NA

Ejemplos de funciones

Vamos a implementar una función que calcule la media de un vector de números dejando fuera los posibles valores no disponibles NA

MiMedia <- function(V){
  suma=0
  Nvalores=0
  for(i in 1:length((V))){
    if(is.na(V[i])==TRUE) next
    suma=suma+V[i]
    Nvalores=Nvalores+1
  }
  return(suma/Nvalores)
}
V <- c(1.,NA,2.,3.)
MiMedia(V)
## [1] 2

Este mismo resultado se puede obtener llamando a la función mean pero previamente omitiendo los NA del cálculo.

mean(na.omit(V))
## [1] 2

La función na.omit se usa mucho cuando queremos hacer cálculos numéricos en vectores que pueden contener NA.

Vamos ahora a implementar una función para calcular la primera posición en un vector de strings, sV donde se encuentra el string s. Si no se encuentra el string se devuelve NA

FindString <- function(s,sV){
  i=1
  result<-NA
  while(i<=length(sV)){
    if(s==sV[i]){
      result <- i
      break
    }
    i=i+1
  }
  return(result)
}
sV <- c("abc","cde","efg")
FindString("cde",sV)
## [1] 2
FindString("cd",sV)
## [1] NA

Este mismo resultado se puede obtener directamente usando la función which, con la salvedad de que si no encuentra el string devuelve un cero en lugar de NA:

which(sV=="cde")
## [1] 2
which(sV=="cd")
## integer(0)

El ámbito de las funciones

Las funciones en cualquier lenguaje son la base para compartir código y funcionalidades entre programas y usuarios. En un primer nivel las funciones en R se almacenan en ficheros con extensión .R. Por ejemplo nosotros hemos creado el fichero utilidades.R donde hemos implementado algunas funciones que necesitaremos usar. Para usar en mi código las funciones implementadas en utilidades.R pongo antes de usar las funciones la instrucción :

source("utilidades.R")

En un segundo nivel las funciones se empaquetan en librerías que podemos compartir con otros usuarios, habitualmente a través de un repositorio personal usando GitHub o del repositorio CRAN. Hay miles de librerías en R y un problema que surge con cierta frecuencia es que varias librerías que usamos al mismo tiempo tienen funciones que se llaman igual pero hacen cosas distintas. Normalmente, por defecto, la función que usa el código es la de la última librería que se ha cargado, pero a veces, la última que se cargó no es la que nos interesa utilizar en ese momento. Por ejemplo la librería dplyr tiene funciones como filter() o rename() que entran fácilmente en conflicto con funciones llamadas igual creadas por otras librerías. Estos conflictos generan fácilmente errores en la ejecución de los scripts. Cuando esto se produce, lo que hay que hacer es especificar en la llamada a la función la librería que queremos usar. Por ejemplo, cuando llamamos a la función dplyr::filter() estaremos especificando que queremos usar la función filter() de la librería dplyr. De esta forma evitamos estos posibles conflictos. Lo ideal sería en cualquier llamada a una función, especificar la librería usada, pero esto no se suele hacer porque alarga mucho la escritura de código. Pero si queremos publicar nuestro código en el repositorio CRAN nos obligarán a hacerlo para evitar conflictos entre las librerías. Lo normal es cargar las librerías en orden inverso a sus importancia. Por ejemplo tidyverse es muy importante y debe ser de las últimas en cargar.

Hay tanta gente que trabaja en R que, con frecuencia, nos encontramos que la misma funcionalidad está implementada en varias librerías. Para decidir que librería utilizar podemos combinar dos criterios: el primero es el número de descargas que ha tenido la librería en CRAN y el segundo es si la librería ha sido actualizada recientemente.

La forma más inmediata de obtener ayuda sobre el uso de una función es ejecutar en la consola el comando help(NombreFuncion)

La familia de funciones apply

Supongamos que tenemos 2 vectores de strings, sV1 y sV2 que queremos comparar. Usando la función FindString(s,sV) implementada anteriormente podríamos hacer un bucle y recorrer todos los elementos de sV1 y compararlos con sV2. Sin embargo hay una forma más eficiente de hacer esta comparación usando la funciones de la familia apply que permiten hacer bucles y otro tipo de operaciones anidadas de forma eficiente. Por ejemplo, las funciones sapply y lapply se pueden usar para hacer un bucle aplicando la función FindString(s,sV). La diferencia entre ellas es que lapply devuelve una lista y sapply un vector. Veamos como se aplica sapplypara aplicar, con una sola instrucción, la función FindString(s,sV) a todos los elementos de sV1

sV1 <- c("abc","cde","efg")
sV2 <- c("efg","abc","cde")
sapply(sV1,FindString,sV=sV2)
## abc cde efg 
##   2   3   1

Los parámetros de sapply() son : (1) el vector sV1, (2) la función FindString que actúa sobre los elementos de sV1 y (3) sV=sV2 el segundo argumento de la función FindString.

Las funciones de la familia apply permiten hacer operaciones más complejas que no vamos a estudiar en este curso.

El operador pipe %>% o |>

Algunos paquetes de R tienen implementado el operador pipe %>% (también denotado por |>) que permite concatenar las llamadas a funciones de forma más clara y sin necesidad de usar paréntesis anidados. Es decir, si normalmente escribimos la concatenación como

función2(función1(x)))

usando el operador pipe %>, la misma llamada se escribiría como:

` x %>% función1() %>% función2()`

Como veremos, en muchas ocasiones, esta forma de escribir la llamada a las funciones concatenando la salida de una operación con la entrada de la siguiente, resulta más práctica y natural que la forma habitual que presenta el problema de que lo último que hacemos (la llamada a la última función) es lo primero que tenemos que escribir, es decir, escribimos en el orden opuesto al que vamos haciendo las operaciones.

Referencias

[Bo] Juan Bosco Mendoza. R para principiantes.

[Pe15] Roger D. Peng. R Programming for Data Science, Lulu, 2015.