Estructuras
Estructuras
1.1. Vectores 3
1.1.1. Acceder y extraer los elementos 5
1.1.2. Operaciones matemáticas 7
1.1.3. Reciclado 13
1.2. Atributos 14
1.2.1. Ejemplos 14
1.3. Matrices 15
1.3.1. matrix() 15
1.3.2. cbind(), rbind() 15
1.3.3. Acceder y extraer elementos 16
1.3.4. Operaciones matemáticas 16
1.4. Arrays 18
1.4.2. Operaciones con arrays 20
CAPÍTULO 2 22
2.1. Listas 22
2.1.1. Acceder y extraer elementos 23
2.1.2. Operaciones con listas 24
CAPÍTULO 3 30
3.1. Factores 30
3.1.1. Ejemplo con tipos ordinales 30
3.1.2. Ejemplo con tipos categóricos 30
3.2. Funciones 32
3.2.1. Argumentos por defecto 32
3.2.2. Crear funciones 34
González Bonorino ii
Parte II Estructuras de datos
Programación en R
R opera con estructuras de datos que sirven para agrupar, almacenar y procesar
múltiples elementos. Las principales estructuras de datos en R son: vector, matriz,
array, lista, marco de datos, factor y función. Una estructura de datos es un objeto en
R. Los objetos tienen atributos, por ejemplo: names, dimensions, dimnames y
classes. El uso de estos atributos se irá viendo a medida que avance el curso.
Conviene ponerse de acuerdo sobre qué se llama dato. Hay dos tipos de datos:
cuantitativo y categórico. Un dato cuantitativo responde a preguntas como
¿Cuánto hay? y resulta de una medida o un conteo, que se representa con
números enteros, o sea una secuencia discreta, o un número real, es decir una
secuencia continua. Un valor cuantitativo puede corresponder a dos escalas
numéricas, de intervalo y racional. La escala de temperatura es cuantitativa de
intervalo, pues define un orden y también la separación entre unidades, pero
carece de un nivel de referencia 0. En cambio, la escala cuantitativa racional
incluye un nivel de referencia 0, lo cual permite establecer cocientes. Un dato
cuantitativo se puede manipular con técnicas matemáticas.
Por su parte, un dato categórico, también conocido como cualitativo, representa
una categoría, un grupo claramente distinguible de otros grupos. Un dato
categórico puede corresponder a las escalas ordinal y nominal. La escala nominal
se representa con etiquetas, o nombres; varón-mujer, alto-bajo. No representan un
ordenamiento y tampoco indican una diferencia específica en valor. La escala
ordinal tambien se representa con etiquetas o nombres, pero incluye un
ordenamiento; por ejemplo, baja velocidad, velocidad moderada, velocidad
elevada, o un ranking de aceptación: 1 2 3 4 5. Pero la separación entre 1 y 2 y
entre 3 y 4 no son necesariamente iguales. R clasifica las variables categóricas
como factores y brinda técnicas especiales para manipularlas.
R opera con seis tipos de datos: character, numeric, integer, logical y complex.
character incluye una letra aislada o un conjunto de letras, que en este curso se
denomina cadena. El tipo numeric abarca los números reales; integer los
números enteros, que en R se distinguen por el sufijo L (2L difiere de 2; aunque
no se coloque un punto R interpreta el 2 como real); logical resuelve en TRUE o
FALSE; complex refiere a números complejos. Más adelante se ve cómo reconocer
los tipos de datos.
González Bonorino 2
Capítulo 1 Estructuras
atómicas
En muchos casos es necesario trabajar con más de un tipo de dato. Quizá lo más
frecuente es que se manipulen datos de tipo numérico, apto para cálculos
matemáticos, pero muchos conjuntos de datos incluyen caracteres y cadenas de
caracteres, por ejemplo, y es conveniente tener a disposición modos de operar
con ellos. R ofrece esta prestación pero con condiciones. Hay estructuras que
solamente aceptan albergar datos de un mismo tipo. Estas estructuras se
denominan atómicas en referencia a que los tipos de datos que contiene no son
subdivisibles, y son las que se ven en este capítulo. Vectores, matrices y arrays
pertenecen a esta categoría.
1.1. Vectores
Un vector se puede visualizar como una serie de celdas contiguas conteniendo
datos. Hay cinco tipos básicos de vectores: lógico, entero, real, complejo y
cadena, designados en base al tipo de elemento que lo conforma. Un vector debe
necesariamente estar compuesto por un único tipo de elemento. Así, un vector
puede incluir sólo letras, o sólo números reales, pero no letras y números reales. En
R este tipo de estructura se denomina atómica. Los vectores son la piedra
fundamental de las estructuras de datos en R. El diagrama esquematiza la
organización de los vectores.
Un vector se caracteriza por el tipo de dato que contiene, por el número de
elementos que lo componen y por los atributos que lo caracterizan. R ofrece
cuatro opciones para crear vectores: el operador ’:’ y las funciones ’c()’, ’seq()’
Programación en R
González Bonorino
Programación en R
González Bonorino 5
Programación en R
> a[2]
para seleccionar un elemento. Y para ejecutar una operación matemática hacer
> a[2] * a[3].
Se remarca que en R no es válido un índice 0; se parte de 1.
R incluye algunas constantes ya definidas con estructura de vector.
> letters contiene las 26 letras del alfabeto en minúsculas y
> LETTERS las devuelve en mayúsculas.
> LETTERS[5] devuelve la quinta letra, E.
> LETTERS[1:5] devuelve las cinco primeras letras.
González Bonorino
Programación en R
Ejecutar las siguientes operaciones sobre el vector v. Los ‘;’ permiten colocar
varias operaciones en un mismo renglón
> max(v); min(v); mean(v); sd(v); length(v)
Estos comandos devuelven números únicos: los valores extremos, el promedio y la
desviación típica y el número de elementos que contiene.
En cambio
> cumsum(v) devuelve la suma acumulativa de los elementos en v
Un ejemplo que puede sorprender. Se trata de determinar cuales elementos del
vector v = mtcars$mpg son mayores que 20
> v > 20
Probablemente se espera que devuelva números, pero el resultado en un vector
lógico que indica con TRUE la posición de aquellos elementos que cumplen con
la condición y con FALSE los que no la cumplen. Para recuperar los elementos
numéricos hay que usar los elementos lógicos como índices
> v2 <- v[v>20]
Se tiene ahora los elementos numéricos pero sin ordenar. Hacer
> sort(v2) para ordenarlos.
Otras operaciones con vectores se ven a lo largo del curso.
González Bonorino 7
Programación en R
CiudadXY X Y
Santiago 3667285 6924138
Tucuman 3581403 7031878
La Rioja 3417762 6751041
Salta 3562763 7256922
Jujuy 3575588 7325100
Catamarca 3518297 6850478
Tabla 1.2
González Bonorino
Programación en R
González Bonorino 9
Programación en R
˙ u̇ v̇
||v̇||2
La ecuación involucra el producto escalar, o producto punto (’dot product’) u x
v, dividido por el módulo al cuadrado, y finalmente multiplicado por el vector
sobre el cual se hace la proyección.
Nota:
En la ejecución de este ejercicio se emplean las funciones dot() y Norm(), del
paquete pracma. El numerador se calcula con dot(u,v), el producto escalar o
producto punto. La ecuación expandida es:
dot(a,b) <- a1b1 + a2b2 + a3b3
Otro modo de expresarlo:
producto punto u̇ x v̇ <- modulo u̇ x modulo v̇ x cos(ángulo entre u y v). Algunas
equivalencias:
dot(a,b) <- a dot() opera sobre vectores o columnas de una matriz, y devuelve un
escalar.
La sintaxis de Norm(x, p = 2), p = 2 por defecto y devuelve un escalar que representa la
magnitud, o el largo euclidiano, del vector x. Por ejemplo, Norm(c(3,4)) devuelve 5, por
Pitagoras. Norm() tiene equivalencias:
González Bonorino
Programación en R
González Bonorino 11
Programación en R
El cálculo del volumen involucra un producto escalar seguido por uno vectorial
> abs(dot(a,(cross(b,c))))
se toma el valor absoluto pues puede dar negativo.
González Bonorino
Programación en R
Fz <- 118 N
f <- c(0,157,118)
y se aplica a una distancia de 0,4 metros de la bisagra.
1.1.3. Reciclado
Las operaciones entre vectores exigen que tengan igual número de elementos.
Pero ¿qué ocurre si esta condición no se da? Para explorar una respuesta crear los
vectores A = c(1,2,3) y B = c(4,5,6,7,8) y sumarlos. Se obtiene la respuesta 5 7 9
8 10 pero acompañada por un mensaje explicando que el número de elementos
en ambos no son múltiplos. Pero veamos qué hizo R para obtener un resultado.
Los elementos del vector A se sumaron uno a uno a los tres primeros elementos
del vector B. Para cubrir los restantes dos dígitos en B R repitió los primeros dos
dígitos en A, dando 8 y 10. Es como transformar A en A = c(1,2,3,1,2). Es decir,
los elementos del vector más corto se reutilizan afin de completar la operación
demandada. Este comportamiento se denomina reciclado. Prueben agregando un
número a B para que sea múltiplo de A.
González Bonorino 13
Programación en R
1.2. Atributos
Al describir propiedades de vectores se mencionó que poseen atributos, como, por
ejemplo, name. Más aun, al inicio del capítulo se dijo que todos los objetos en R
poseen atributos, los cuales ayudan a caracterizar los objetos. Es conveniente,
entonces, presentar los atributos formalmente.
Los tres atributos más importantes son los que describen los nombres de los
elementos: names, la dimensión de la estructura: dim, y la clase de la estructura,
class. names contiene etiquetas para los elementos de un vector o una lista; dim se
emplea en la creación de matrices y arrays. De hecho, como se ve enseguida,
matrices y arrays son vectores con atributo dim. El atributo class devuelve un
vector con cadenas de caracteres que identifica las clases que un objeto hereda.
Para recuperar un listado de atributos de un objeto se recurre a attributes(objeto).
Escribir
> attributes(mtcars)
devuelve el contenido de los atributos names, [Link] y class.
Si se desea revisar solamente uno de los atributos se usa attr. Escribir
> attr(mtcars, ’names’)
devuelve los nombres de las columnas.
Los atributos no son estáticos. Es posible modificar atributos y también
asignarlos si faltasen. Por ejemplo, la sentencia names <- nombre, permite
asignar un nombre de atributo. Más adelante se verá cómo recurriendo a los
atributos colnames y names se puede modificar estructuras.
1.2.1. Ejemplos
Dado
b <- c(1, 2, 3), names(b) devuelve NULL, pero si se asignan nombres a las
variables
> b <- c(’uno’ = 1,’dos’ = 2,’tres’ = 3) names(b) devuelve los nombres.
Además de rescatar nombres dados previamente, names permite asignar
nombres. Hacer
> f <- c(4, 5, 6) y names(f) <- c(’cuatro’, ’cinco’, ’seis’)
Verificar que se incorporaron los nombres al vector.
> dim(mtcars) devuelve 32 11, o sea, 32 filas y 11 columnas
> dimnames(mtcars) devuelve los nombres de las columnas.
Un último ejemplo
González Bonorino
Programación en R
1.3. Matrices
Una matriz es un arreglo bidimensional de valores dispuestos en filas y en
columnas. Una matriz hereda la propiedad atómica de los vectores, por lo cual
sólo puede contener elementos de idéntica clase. Una matriz se puede crear
empleando tres funciones: matrix, cbind y rbind.
1.3.1. matrix()
La función matrix() crea una matriz a partir de un único vector definiendo las
dimensiones. La función matrix() tiene la sintaxis por defecto: matrix(data = NA,
nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL) creando una matriz de un
elemento NA, ordenada por columnas y sin nombres de filas ni columnas.
De estos parámetros data y nrow o ncol, son obligatorios; dado nrow, por
ejemplo, R deduce ncol. Los siguientes ejemplos muestran el uso de matrix()
generando matrices con 10 elementos numéricos. Por defecto matrix() organiza los
datos en columnas, o sea, completa una columna antes de pasar a a otra. Escribir
> matrix(1:10, nrow = 5) y comparar con
> matrix(1:10, nrow = 2)
Pero se puede exigir que lo haga por filas
> matrix(1:10, nrow = 2, byrow = TRUE)
En una matriz, los números entre [ ] encabezando las filas y las columnas
indican la posición de cada elemento en la matriz [fila,columna]; [,2] indica
todas las filas de la columna 2, y [2,] indica todas las columnas de la fila 2.
El número de elementos en una matriz se obtiene con
length(matriz)
Una matriz creada con matrix() carece de encabezamientos de columnas o
índices de filas. Pero se puede asignar ambos empleando las funciones
rownames() y colnamens().
rownames(matriz) <- c(‘col1’, ‘col2’)
colnames(matriz) <- c(‘ind1’,’ind2’)
González Bonorino 15
Programación en R
mat_fila <- rbind(1:5, c(1.7, 1.8, 1.9, 1.5, 1.1), c(55, 66, 44, 34, 59))
Notar que en ambos casos se operó con los mismos vectores.
Las columnas de una matriz pueden tener nombres dados por el usuario. Crear
los vectores
> Edad <- c(28, 30, 33, 29, 23) y
> Peso <- c(55, 58, 57, 60,63)
Escribir
> matriz_nombre <- cbind(Edad, Peso)
Los nombres de las columnas se pueden agregar con posterioridad a la creación de la
matriz, y también se pueden modificar, mediante la función colnames().
> colnames(matriz_nombre) <- c(‘Edades’, ‘Pesos’)
De modo similar se opera con rownames() para asignar nombres a las filas.
González Bonorino
Programación en R
En un comercio hay que limpiar baños, pisos y ventanas. La tabla resume las tareas
y el personal a asignar a ellas, indicando el precio que cada persona desea cobrar
por ejecutarla (Tabla1.3). El gerente debe asignar el personal de modo que las
tareas se ejecuten con menor costo. Se aplica el algoritmo de optimización
conocido como método húngaro. La tabla se encuentra en la carpeta Datos como
[Link].
En este ejemplo se utiliza la función [Link]() incluida en el paquete lpSolve, un
conjunto de algoritmos para programación lineal. [Link]() opera sobre una
matriz donde las filas representan las restricciones y las columnas las variables, y
determina el costo de asignar una fuente a un destino. Incorporar [Link]() con
> [Link](’lpSolve’)
> library(lpSolve), o desde el GUI de RStudio.
Ingresar la tabla [Link] en RStudio con
File>Import Dataset>From Text (readr).
La función de asignación de recursos [Link]() requiere una matriz numérica, por
lo cual hay que eliminar las cadenas de caracteres en la columna Sujeto. Una
manera de hacerlo es reescribiendo la tabla sin esa columna
> asig <- Asigna[,2:4]
Seguidamente se convierte la tabla en una matriz con
> mat_asig <- [Link](asig). Verificar que se tiene una matriz numérica
con
> mat_asig
Ahora sí se puede ejecutar
> [Link](mat_asig) que devuelve $60 como el menor costo posible para
ejecutar las tareas con ese personal.
González Bonorino 17
Programación en R
x1 + 3x2 = 7
2x1 + 4x2 = 10
En forma matricial
En forma compacta: A−1b = x donde A−1 es la inversa de A. Para invertir una matriz se usa
la función solve(), del paquete base.
Los datos son:
A <- matrix(c(1,2,3,4), ncol = 2)
b <- c(7, 10)
1.4. Arrays
Si el arreglo de vectores tiene tres o más dimensiones constituye un array. Un
array hereda la propiedad atómica de vector. La sintaxis por defecto es:
array(data = NA, dim = length(data), dimnames = NULL).
Los dos primeros parámetros son obligatorios. En tres dimensiones la estructura
es: número de filas, número de columnas, número de capas o de matrices. Las dos
primeras dimensiones configuran una matriz y la tercera corresponde al número de
matrices. dimnames = refiere a una lista con los nombres de cada dimensión; por
defecto R asigna números enteros a filas y columnas, como se muestra en los
ejemplos que siguen y en el script [Link] en scripts Estructuras.
González Bonorino
Programación en R
Ejemplo A
Hacer
> array(1:18, dim = c(3, 3, 2)).
La salida se presenta como dos matrices, una por cada capa representada por los
índices [, , 1] y [, , 2]. Verificar que los valores se distribuyen llenando primero
las columnas.
Ejemplo B
Dados los vectores vect1 <- c(10, 20, 30, 40) y vect2 <- c(50, 60, 70, 80, 90,
100) el array B con dimensiones 3 3 2 se crea con
> B <- array(c(vect1, vect2), dim = c(3, 3, 2))
Ejemplo C
Asignar nombres a las dimensiones del vector B
<- array(c(vect1, vect2), dim = c(3, 3, 2)) Los
nombres son:
> r <- c(’f1’,’f2’,’f3’)
> c <- c(’c1’,’c2’,’c3’)
> m <- c(’m1’,’m2’)
> B_nom <- array(B, dim = c(3,3,2), dimnames = list(r,c,m))
> B_nom
Ejemplo D
La tarea consiste en crear un array a partir de vectores con datos del re-
levamiento de contaminación por botellas de plástico y latas de aluminio
inicialmente presentado en el acápite 1.1.2. Abajo se dan los vectores con datos
para botellas y latas por año y por sitio.
> a17_bot = c(5,14,0,30,0)
> a18_bot = c(15,24,0,32,8)
> a19_bot = c(18,22,0,33,9)
> a17_lat = c(3,3,5,1,2)
> a18_lat = c(5,6,2,7,3)
> a19_lat = c(8,9,6,11,13)
Se muestra la matriz para el Año 2017 (Tabla1.4).
González Bonorino 19
Programación en R
Botellas Latas
5 3
14 3
0 5
30 1
0 2
Tabla 1.4
Ejemplo E
Ejemplo F
González Bonorino
Programación en R
González Bonorino 21
Capítulo 2
Estructuras no atómicas
Una característica común a muchos conjuntos de datos es que contienen datos de
más de un tipo. Un informe con resultados de pruebas toxicológicas puede tener el
nombre de los pacientes, un carácter identificador de la prueba y números reales
con los resultados. Es decir, conforma una estructura no atómica. ¿Cómo operar
con datos de tipos diferentes? R ofrece dos estructuras de datos especialmente útiles
para estos casos. En este capítulo se introducen las listas y los marcos de datos,
estructuras que permiten combinar tipos de datos.
2.1. Listas
Las listas son estructuras semejantes a vectores pero que no son atómicas, es decir,
pueden combinar tipos de datos. Una lista se crea con la función list() y tiene la
siguiente estructura:
list(objeto1, objeto2, ...) donde objeto puede ser cualquier tipo de dato, inclu-
yendo otra lista. Escribir
> Mi_lista <- list(pi, c(TRUE, FALSE), ’Mi lista’, 2:10)
Esta lista comprende cuatro componentes, el número pi, un vector con ele-
mentos lógicos, una cadena de caracteres y un vector numérico.
Se puede asignar nombres a los componentes de una lista.
> Mi_Lista <- list(num_pi = pi, Bool = c(TRUE, FALSE), cadena = ’Mi
lista’, vector = 2:10).
Otro ejemplo
> Otra_lista <- list(c(’Ene’,’Feb’,’Mar’), matrix(c(1,2,3,4,-1,9), nrow =
2),list(’Rojo’,12.3))
Ver script ListasRmd en scripts Estructuras.
22
Programación en R
González Bonorino 23
Programación en R
$a
[1] 5
$b
[1] 8
$c
[1] "yo"
$d
[1] 20
González Bonorino 24
Programación en R
> lista1 <- list(1,2,3,4,5)
> lista_unida <- list(lista2,lista1)
> lista_unida
González Bonorino 25
Programación en R
Ejercicios optativos
1 - Crear una lista que incluya su nombre, su edad, su peso con decimales, su
sexo y un valor lógico indicando si su pelo es rubio. 2 - Crear una lista que
incluya dos listas. 3 – Dada la lista lista_unida, creada arriba. Escribir el
comando que devuelve el elemento 3. 4 – Reunir los componentes de lista1 y
lista2 en una nueva lista asignándoles nombres dias y num. La nueva estructura
debe responder al comando
> lista$ devolviendo un panel con las opciones dias y num.
González Bonorino 26
Programación en R
> L3 <- LETTERS[1:3]
> num <- c(2, 3, 6)
> log <- c(TRUE, FALSE, TRUE)
Combinarlos en un dataframe
> [Link](L3, num, log)
Resultado
> [Link](L3,num,log)
L3 num log
1 A 2 TRUE
2 B 3 FALSE
3 C 6 TRUE
[Link] devuelve tres vectores con los nombres de las columnas, y por defecto
números enteros designando las filas en una primera columna; esta columna no forma
parte de los datos, es decir, no se puede operar con sus valores.
Noten, pues, que un tibble hereda de un dataframe. De hecho tbl_df es una subclase de
dataframe creada para agregar otras propiedades. En este curso trabajaremos mayormente
con tibbles, puntualizando conflictos con los tradicionales dataframes donde sea
necesario. Hacemos esta elección conscientes de que pueda generar alguna confusión
cuando ustedes revisen textos y códigos algo antiguos, y también cuando recurran a
conjuntos de datos preinstalados, como mtcars, que es un dataframe. En contraprestación,
tidyverse, y los tibbles, son el futuro de la programación en R y es mejor incorporar este
ecosistema al tiempo de aprender a programar en R. Al inicializar variables con
dataframes les asignaremos el sufijo_df y a tibbles _tb.
González Bonorino 27
Programación en R
Cargamos el conjunto de datos mtcars y lo abrimos en pantalla
> mtcars_df <- mtcars
> mtcars_df
Imprime los identificadores de filas y las columnas con datos. Imprime todas las
columnas apilando las salidas.
Seguidamente lo convertimos a tibble.
> mtcars_tb <- as_tibble(mtcars)
> mtcars_tb
omite los identificadores de filas. Noten que no imprime en pantalla todas las columnas y
al pie indica cuales se excluyeron.
********************************************************
Nota:
En el módulo 1 presentamos el operador %>%, o tubo (‘pipe’), Tubo
concatena comandos pasando el resultado de uno al siguiente, y hace
un código más legible. El siguiente ejemplo muestra porqué. Se tiene
el vector x <- c(1, 4, 6, 8) y se trata de obtener el promedio de la raíz
cuadrada de x redondeada a dos decimales. Tradicionalmente el
comando es
> y <- round(mean(sqrt(log(x))), 2)
La sucesión de operaciones es a la inversa de como está escrito el
comando; la primera está en el núcleo. Empleando tubos el comando
queda así
> y <- x %>% log() %>% sqrt() %>% mean() %>% round(2)
González Bonorino 29
Programación en R
Capítulo 3
Factores y funciones
Quedan dos importantes estructuras sin presentar: factor y function. Son
estructuras compuestas que suelen incluir diversos tipos de datos y cumplen
funciones muy relevantes.
3.1. Factores
La estructura factor es la más peculiar en R y está particularmente adaptada para el
trabajo con datos ordinales y categóricos, particularmente con conjuntos que
resultan de la repetición de un número limitado de elementos. Los datos
ordinales representan un orden cualitativo, como alto – mediano – bajo, mientras
que los categóricos no lo hacen, por ejemplo, azul – verde – rojo.
Supongamos un experimento que registra el color de ojo de 50 individuos como azul,
marrón y verde. El vector contendrá 50 elementos que son reiteración de tres
elementos base, los tres colores registrados. Al crear una estructura factor, R
convierte los nombres de colores en números enteros al tiempo que registra los
elementos que se repiten como cadenas, asignándolos al atributo levels. El
ejemplo resultaría en 50 dígitos y tres levels: ’azul’, ’verde’, ’marron’.
La función factor() convierte un vector en un factor, como se muestra en el
siguiente ejemplo.
El acceso a los elementos de un factor sigue reglas similares que para vectores.
> md_tb_fact[3]
devuelve mujer.
Una ventaja de los factores se da en el almacenaje. Cada elemento único se
guarda una sola vez y el número de veces que se repite se guarda como un
González Bonorino 31
Programación en R
número entero. Pero la mayor aplicabilidad es en el trabajo con modelos
estadísticos, debido a que las variables continuas son procesadas en R de modo
diferente de las categóricas, como se verá más adelante al presentar modelos de
regresión lineal.
3.2. Funciones
Una función es un conjunto de sentencias, claramente segregadas del resto del
script, cuya ejecución da un resultado que puede ser utilizado por el script. Una
función se compone de un nombre, de la palabra reservada function que asigna a
ese nombre el carácter de función, de cero o más argumentos requeridos por la
función, entre paréntesis, y de una o más sentencias que determinan el
comportamiento de la función y el resultado de la ejecución, entre llaves.
La sintaxis es:
nombre_de_funcion <- function(listado de argumentos)
{
Código que ejecuta una acción
}
Al invocar una función se le pasan valores a los argumentos, siempre y cuando la
función lo requiera. Ejemplo:
suma <- function(x, y) x + y
Invocar con:
suma(4, 6)
suma(x 4, y = 6)
suma( y = 6, x = 4)
Es decir, los valores se pueden pasar por posición o por nombre.
El resultado de la ejecución del código se almacena en nombre_de_funcion. Las
funciones son objetos de la clase function.
Una virtud importante de las funciones es que son autocontenidas y por lo tanto
pueden ser reutilizadas en otros scripts.
González Bonorino 32
Programación en R
> ls()
se obtiene un resultado a pesar de no llevar un argumento. Los argumentos
pueden ser números, vectores, matrices o cadenas de caracteres.
Asimismo, una función puede tener un único argumento o varios, y más aun,
uno de los argumentos puede estar predefinido, como se muestra en el siguiente
ejemplo.
La función f tiene como argumentos un número real y un vector numérico que
ya tiene asignado valores
f <- function(x, y = c(2,3,4))
{
xˆy
}
> f(3) devuelve 9 27 81.
El vector y establece los exponentes que afectan a x = 3.
Aprovechemos esta sencilla función para comprender el comportamiento.
Variante 1 - Se pasan valores a x pero también a y
> f(3,5)
de modo que y toma el valor 5. El resultado da 243 = 3 ˆ 5. Ocurre que el
argumento predefinido y <- c(2,3,4) es una variable de alcance (’scope’) local, es
decir, interno a la función, mientras que 5 es un valor global y tiene
preeminencia. Las variables definidas dentro de una función tienen alcance
limitado a dicha función.
Variante 2 - Se modifica f() asignando el resultado a una variable
f <- function(x, y = c(2,3,4))
{
a <- xˆy
}
Invocación con f(3), como inicialmente, no arroja resultado. Escribiendo con a
tampoco, debido a que a tiene alcance local y el script no la puede ver. Es
necesario escribir print(f(3)), o asignar la función a una variable
> var_temp <- f(3)
> var_temp
La Variante 2 indica que si el último comando en una función es de asignación el
resultado no se imprime automáticamente en pantalla.
Una función puede devolver un único número (un vector unitario) o un vector con
varios elementos Por ejemplo, dado x = c(2,-2,0,5), sum(x) devuelve 5 y
cumsum(x) devuelve 2 0 0 5.
Nota:
Para ejecutar una función escribirla en el editor de RStudio, seleccionarla
entera y pulsar Run para cargarla en memoria. Luego, en la Consola, escribir el
comando de ejecución.
González Bonorino 33
Programación en R
floor(), ceiling(), round(), signif()
Con frecuencia será conveniente reducir el número de dígitos decimales a la
derecha de la coma en un número real. La modificación puede eliminarlos por
completo dejando un número real o convirtiéndolo en uno entero. Se ejemplifica
sucintamente con pi = 3.14.
floor(pi) da 3
ceiling(pi) da 4
trunc(pi) da 3
round(pi)
y por último,
signif(pi, 2) da 3.1, es decir, determina cuantos dígitos quedan.
args()
Claramente, es importante conocer cuales argumentos exige, o acepta una
función para ejecutarla correctamente. Cuando uno mismo crea una función sabe
que argumentos necesita. Con una función importada la naturaleza y cantidad de
los argumentos puede no ser evidente. La función args() se usa para este fin
> args(sqrt) devuelve el argumento principal, x, y NULL, indicando que no
requiere ni acepta otros argumentos. En cambio
> args(round) devuelve x pero también digits = 0, indicando que por defecto
redondea sin decimales pero que eso se puede cambiar. Probar con round(pi,
digits = 2)
Ejemplo A
González Bonorino 34
Programación en R
> formals(pot) devuelve $x $y
> environment(pot)
devuelve Global Environment porque fue creada globalmente.
Ejemplo B
Escribir una función que calcule los promedios de cada columna de la matriz mz
> mz <- matrix(1:32, c(4,8))
En una primera aproximación se crea la función
> f_prom <- function(x) mean(x) que realiza el cálculo en cada columna
> a <- f_prom(mz[,1]) !pero no se gana casi nada ya que hay que escribir la
función ocho veces! Para evitar esto R ofrece una eficiente alternativa con la
familia de funciones apply()
> tot_prom <- apply(mz,2,f_prom)
apply() es una función que llama a otra función, en este caso f_prom(), y la
aplica reiteradamente sobre el objeto mz. El segundo argumento, margin, es un
número entero, 1 o 2, que indica si la operación se hace sobre las filas, margin =
1, sobre las columnas, margin = 2, o sobre filas y columnas, margin
= c(1,2). apply() es la más básica de varias funciones similares que se verán al
presentar operaciones de iteración.
Ejemplo C
La función bisiesto(), cuyo código se da abajo, determina si un año es
bisiesto. Transcribirla al editor de scripts. Seleccionarla completa y pulsar en
Run. Notarán que se reproduce en la consola. En la consola llamarla con
bisiesto(1222), por ejemplo.
bisiesto = function(anio){
if((anio %% 4) == 0) {
if((anio %% 100) == 0) {
if((anio %% 400) == 0) {
print(paste(anio,"es bisiesto"))
} else {
print(paste(anio,"no es bisiesto"))
}
} else {
print(paste(anio," es bisiesto"))
}
} else {
print(paste(anio,"no es bisiesto"))
}
}
González Bonorino 35
Programación en R
Nota:
Modo de ejecución. Pegar la función en el editor de RStudio. Seleccionarla con
Ctrl-A. Pulsar Run. Luego pasar a la Consola y escribir
> bisiesto(2105)
return()
En ocasiones encontrarán funciones que incluyen el comando return(). La tarea
de este comando es devolver el resultado al código para que sea utilizado. Los
ejemplos dados muestran que la acción de retorno del valor calculado por la
función se cumple sin necesidad de return(). Con ciertas funciones algo más
complejas, sin embargo, return() es necesario. Un caso se da cuando la función
devuelve varios resultados.
> fun <- function(x, y) z1 <- x + y z2 <- x* y
return(list(z1, z2))
Si se omite return() R no muestra el resultado. Notar que return() devuelve una
lista con los resultados.
Ver scripts [Link], [Link], [Link] y
[Link] en scripts Estructuras.
González Bonorino 36