Introduccion A R
Introduccion A R
Introduccion A R
Optimización de Sistemas
4º Grado Ing. Software
Pedro L. Luque
Índice
1 Qué es R 4
1.1 El Proyecto R para Cálculo Estadístico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Características de R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Diseño del Sistema R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2 Instalación de R 6
2.1 Instalación de R paso a paso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
8 Tipos de Datos en R 30
8.1 El operador de asignación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
8.2 Clases o tipos de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
8.3 Números en R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
8.4 Atributos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
8.5 Creando vectores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
8.6 Objetos mixtos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
8.7 Conversión explícita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
8.8 Generando valores aleatorios en R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
8.9 Trabajando con caracteres con la función paste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
8.10 Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
8.11 Pegando por columnas y por filas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
8.12 Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
8.13 Factores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
8.14 Factores ordenados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
8.15 Valores faltantes (missing) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
8.16 La clase: data.frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
8.17 Asociando nombres (names) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
8.18 Listas y matrices con nombres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
9 Extracción de elementos en R 40
9.1 Subconjuntos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
9.2 Extrayendo elementos de vectores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
9.2.1 Funciones útiles en Estadística . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
9.3 Extrayendo elementos de una matriz (matrix) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
9.4 Extrayendo elementos de una lista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
9.5 Eliminando valores NA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
9.6 Operaciones vectorizadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
9.7 Operaciones vectorizadas sobre matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
9.7.1 Operaciones con Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
9.7.2 Funciones útiles en Estadística . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
9.8 Ordenación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
9.9 Filtrado de filas y columnas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
9.10 Muestreo sobre datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
9.11 Fusión de data.frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
10 Programación y Funciones en R 50
10.1 Estructuras de control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
10.2 Operadores de comparación y operadores lógicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
10.3 Estructuras de control: if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
10.4 Función ifelse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
10.5 Estructuras de control: for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
10.6 Bucles anidados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
10.7 Estructuras de control: while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
10.8 Estructuras de control: repeat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
10.9 next, return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
10.10 Estructuras de Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
10.11 Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
10.12 Ejemplos de funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
10.13 Argumentos de una función . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
10.14 Encontrando argumentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
10.15 Definir una función . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
12 Dibujando en R 65
12.1 Múltiples gráficos sobre una página . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
12.2 Añadiendo texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
12.3 Tamaño, color y elección del símbolo del gráfico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
1. Qué es R
R es un lenguaje y entorno de programación para análisis estadístico y gráfico. Se trata de un proyecto de software
libre, resultado de la implementación GNU del premiado lenguaje S (John Chambers).
R es uno de los lenguajes más utilizados en investigación por la comunidad estadística, siendo además muy popular
en el campo de la investigación biomédica, la bioinformática y las matemáticas financieras.
A esto contribuye la posibilidad de cargar diferentes bibliotecas o paquetes con finalidades específicas de cálculo o
representación gráfica.
R se puede descargar desde el CRAN (Comprehensive R Archive Network) https://cran.r-project.org, una red de
servidores ftp y web alrededor del mundo de contenido idéntico y actualizado de las distintas versiones del código y
documentación de R.
1.2. Características de R
Funciona sobre casi todos los sistemas operativos existentes: Windows, MacOsx, Linux, etc.
Se liberan nuevas versiones de forma frecuente (anuales más correcciones de errores), es decir tiene un
desarrollo activo.
Su funcionalidad está dividida en paquetes modulares.
Capacidades gráficas muy sofisticadas y mejor que la mayoría de los programas estadísticos.
Útil para el trabajo interactivo, pero contiene además un poderoso lenguaje de programación para
desarrollar nuevas herramientas.
Muy activa y dinámica la comunidad de usuarios; tanto las listas de correo (R-help y R-devel) y Stack
Overflow
2. Instalación de R
Instalación de R https://cran.r-project.org:
• Binarios: https://cran.r-project.org/bin/.
• Para windows: https://cran.r-project.org/bin/windows/base
Ver: http://destio.us.es/calvo/post/instalacion-de-r-rstudio-y-latex/
Al iniciar la aplicación RStudio por primera vez podemos ver su aspecto en la siguiente imagen. Se puede resaltar la
distribución en paneles de los distintos elementos disponibles en RStudio.
Con LaTeX se pueden crear documentos pdf con una calidad increíble, y además se puede integrar
código R para crear informes.
Las distribuciones recomendadas para su instalación (https://en.wikibooks.org/wiki/LaTeX/Installation) en cada
uno de los principales sistemas operativos son:
TeX Live: es la mayor distribución de LaTeX (y TeX) para *BSD, GNU/Linux, Mac OS X y Windows:
http://www.tug.org/texlive/.
MiKTeX es específica de Windows: http://www.miktex.org/.
MacTeX es específica de Mac y está basada en TeX Live: http://www.tug.org/mactex/.
Estas distribuciones, no necesariamente incluyen un editor de ficheros LaTeX, pero existen algunos gratuitos como:
TeXStudio (http://texstudio.sourceforge.net) y el propio RStudio se puede usar para ello.
MiKTeX para Windows se puede descargar en: https://miktex.org/download.
La versión actual de MiKTeX es: basic-miktex-2.9.6361-x64.exe (191.13 MB). Nota: en esta página también pueden
encontrarse los distintos modos de instalación de LaTeX sobre los distintos sistemas operativos.
Hay muchas formas de usar RStudio para interactuar con R. Algunas de las más habituales son:
1. Usarlo de forma interactiva, escribiendo código R directamente en la consola de R.
Este modo de trabajar está indicado cuando queremos realizar pequeños cálculos de forma rápida, los cuales
no repetiremos en un futuro.
2. Escribiendo código R en un fichero o varios ficheros de scripts.
Este modo de trabajar está indicado cuando queremos realizar cálculos que requieren de varias etapas, y
además queramos volver a realizarlo, aunque sea sobre otros datos.
3. Escribiendo código R en un fichero tipo informe, es decir, contendrá tanto los cálculos como los
comentarios a los resultados.
Este modo de trabajar está indicado cuando queremos realizar unos cálculos pero además producir un informe
en el que se describa todo el proceso completo. Se recomienda el uso del lenguaje de marcado: R Markdown.
RStudio nos facilita esta tarea, como puede verse en la siguiente imagen, con tan solo pulsar sobre el botón ‘Source’
(1). Se obtendrían todos los resultados asociados: la salida textual en la consola (2), los gráficos en el panel de
gráficos de RStudio (4), y también todos los objetos que contengan datos en el panel de datos de RStudio (3) para
una consulta rápida.
También es posible ejecutar ficheros con código R desde la línea de comandos del sistema operativo
$ Rscript micodigo.R
Nota: El $ representa el prompt del sistema operativo.
Alternativamente, podríamos ejecutar R por esta otra vía:
$ R --slave <micodigo.R >misalida.txt
Incluso podríamos pasarle argumentos a la línea de comandos. Consideramos el fichero ‘test.R’ como ejemplo:
## test.R
myarg <- commandArgs()
print(iris[1:myarg, ])
## devuelve las primeras filas del conjunto de datos 'iris'
Y para ejecutarlo en la línea de comandos del sistema operativo:
Rscript test.R 10
En RStudio se ha introducido el lenguaje de marcas RMarkdown (lenguaje de marcas para escribir texto e incluir
código y resultados del lenguaje R). Con este lenguaje de marcas se puede crear un informe estadístico de una forma
relativamente sencilla, que incluya tanto los análisis estadísticos como los comentarios sobre los resultados.
El informe resultante puede estar en formato: html, word y pdf (sin cambiar nada) al elegirlo en el icono (1) de
RStudio.
Desde RStudio se puede crear un fichero de texto para escribir RMarkdown, eligiendo en el menú ‘File -> New
File -> R Markdown’ o directamente seleccionando el icono ‘R Markdown’ que aparece en la siguiente imagen. Nos
aparecerá un ejemplo-plantilla de uso de RMarkdown con el que podemos empezar a trabajar (consultar el menú:
‘Help -> Markdown Quick Reference’ para un ver un resumen de las posibilidades de este lenguaje).
Al seleccionar ‘Crear un fichero R Markdown’, como puede verse en la siguiente imagen, se nos presenta una ventana
en la que se nos permite elegir entre los distintos tipos de informes que podemos crear:
Tipo Documento (en html, pdf, word).
Tipo Presentación (en html y pdf).
Tipo Shiny (en html). Este tipo de informe permite incluir elementos interactivos, o dicho de otro modo un
informe dinámico (se pueden ver si se tiene una instalación de R y RStudio).
Elegir una plantilla más personalizada del tipo de informe (existen paquetes en R que añaden plantillas para
informes).
3*56.2
## [1] 168.6
786/23
## [1] 34.17391
786%/%23
## [1] 34
2^8
## [1] 256
((3+23^3)*(98/4))*100
## [1] 29816500
sqrt(2)
## [1] 1.414214
sin(3.2)
## [1] -0.05837414
pi
## [1] 3.141593
cos(2*pi)
## [1] 1
log10(100)
## [1] 2
log(100)
## [1] 4.60517
sqrt(983)/5.37629827
## [1] 5.831676
round(sqrt(983)/5.37629827,3)
## [1] 5.832
Nota: si se aplican a vectores, matrices, etc, se efectúan sobre cada elemento.
5.4. Ejemplos
3==3
## [1] TRUE
pi==3.1416
## [1] FALSE
"Hola"=="hola"
## [1] FALSE
3<=7
## [1] TRUE
"avión"<="acta"
## [1] FALSE
"acta"<="avión"
## [1] TRUE
Localmente:
help("nombrefuncion") # búsqueda literal en documentación
help.search("cualquiercosasobreR") # búsqueda fuzzy en documentación
?nombrefuncion # búsqueda literal en documentación
??cualquiercosasobreR # búsqueda fuzzy en documentación
RSiteSearch("nombrefuncion") # usa ingeniería búsqueda de: http://search.r-project.org
# buscar objetos en la lista de búsquedas
apropos("objetosR")
Online:
Stackoverflow: http://stackoverflow.com/questions/tagged/r
R seek: http://rseek.org
Cuando se instala R por primera vez, trae un conjunto de paquetes preinstalados los cuales pueden invocarse
directamente desde la consola de R. Sin embargo, ya que R es lenguaje de código abierto, alguien puede contribuir a
sus capacidades escribiendo nuevos paquetes. Durante estos últimos años, esas constribuciones han resultado en una
lista en continuo crecimiento alcanzando actualmente unos 7500 paquetes.
Desde la consola de R se puede instalar un paquete con la siguiente función:
install.packages("car") # instala el paquete: car
El anterior código nos preguntará para que seleccionemos un mirror o espejo de CRAN (“The Comprehensive R
Archive Network”) a lo cual generalmente se responde seleccionando el más cercano (en RStudio selecciona el mirror
por defecto).
Una vez que el paquete está instalado, se necesitará inicializarlo antes de que se pueda llamar a las funciones y
conjuntos de datos (datasets) que vienen instaladas con el paquete instalado. Eso se hace de la siguiente manera:
library(car) # inicializa el paquete 'car'
require(car) # otro camino de inicializar
library() # abre una lista de todos los paquetes instalados
installed.packages() # devuelve una matrix de todos los paquetes instalados
library(help=car) # abre información sobre el paquete 'car'
search() # vector con paquetes actualmente cargados
.libPaths() # obtiene localización library
En el siguiente código R, se pueden ver otras formas más específicas de instalar un paquete en R:
install.packages("ggplot2",type="source") # descarga el fuente y lo compila
install.packages("radiant",
repos = "http://vnijs.github.io/radiant_miniCRAN/",
type = 'binary')
# descarga el binario de repositorio distinto
Avanzado: Hay algunos paquetes que se desarrollan en el servicio Github. En el paquete devtools existe la función
install_github que permite instalar paquetes ubicados en este servicio.
En el siguiente código se muestra a modo de ejemplo cómo sería el proceso de instalación de paquetes de este servicio.
Algunas veces conviven la versión del paquete que se encuentra en CRAN (más estable) y la versión en desarrollo en
Github (que presenta las novedades en las que trabajan).
# https://github.com/hadley/lubridate
install_github("hadley/lubridate")
# https://github.com/juba/rmdformats
install_github("juba/rmdformats")
install_github('rCharts', 'ramnathv')
devtools::source_gist("gist.github.com/skranz/fad6062e5462c9d0efe4")
install.rtutor(update.github=TRUE)
devtools::install_github(c("ramnathv/htmlwidgets",
"smartinsightsfromdata/rpivotTable"))
En RStudio es muy sencillo instalar y cargar paquetes. En la siguiente imagen podemos ver cómo hacerlo:
RStudio, si tenemos conexión a internet, nos informa de los paquetes que existen en CRAN que comienzan con el
texto que llevemos escrito (3).
Un directorio de trabajo es el directorio de referencia desde el cual R no necesita que indiquemos el camino para
localizar un fichero (o nos permite utilizar caminos relativos desde este directorio). Se pueden leer y escribir ficheros
directamente del directorio de trabajo sin tener que usar el camino (path) completo del fichero. Los nombres de
directorios deberían separarse por ‘/’ o doble ‘\\’ en lugar de una única ‘\’ aunque sea un ordenador con Windows.
getwd() # obtiene el directorio de trabajo actual
setwd("c:/docs") # define el directorio de trabajo actual en "c:\docs"
En la siguiente imagen podemos observar que hay dos formas para definir el directorio de trabajo en RStudio
(equivalente a setwd()), y también podemos saber el directorio de trabajo actual mirando la consola.
Cuando se crean nuevas variables, por defecto se almacenan en el llamado “Entorno Global” (Global Environment).
En las siguientes órdenes se ilustra cómo ver y borrar objetos en la consola de R:
a <- 10
b <- 20
ls() # lista todos los objetos en 'Global Environment'
rm(a) # borra el objeto 'a'
rm(list=ls()) # Atención: borra todos los objetos en 'Global Environment'
Se puede pensar que un entorno es un contenedor que guarda objetos (variables). El contenedor principal más externo
se llama global environment (globalenv()). Este es el lugar en el que R almacenará todos los objetos que creemos.
Se pueden colocar tantos objetos como permita la memoria de nuestro ordenador. Pero hay que observar que, ya
que los contenedores son también objetos, se puede poner cualquier número de contenedores dentro del contenedor
principal (globalenv()). Pero, se puede ver y acceder a los objetos dentro de esos contenedores, solamente si se lo
indicamos explícitamente a R (usando ls() y get()).
R llega con un conjunto de datos en formato de data.frames y se encuentran en el paquete ‘datasets’. Existen otros
paquetes que traen además de nuevas funciones, nuevos conjuntos de datos que también podrían usarse.
Para disponer de ellos, en primer lugar tendríamos que asegurarnos de tener instalados dichos paquetes, y a
continuación cargarlos con ayuda de la función library() (o require()). Para consultar los conjuntos de datos
disponibles, podríamos hacer una llamada o bien a la función data() o a la función library() como puede verse en
el siguiente código.
library(datasets) # inicializa el paquete 'datasets' que contiene datos
data(package="datasets") # muestra data.frame disponibles en el paquete
library(help="datasets") # equivalente a lo anterior
#
# Information on package ‘datasets’
#
# Description:
#
# Package: datasets
# Version: 3.2.0
# Priority: base
# Title: The R Datasets Package
# Author: R Core Team and contributors worldwide
# Maintainer: R Core Team <R-core@r-project.org>
# Description: Base R datasets.
# License: Part of R 3.2.0
# Built: R 3.2.0; ; 2015-04-20 18:47:38 UTC; unix
#
# Index:
#
# AirPassengers Monthly Airline Passenger Numbers 1949-1960
# BJsales Sales Data with Leading Indicator
# BOD Biochemical Oxygen Demand
# CO2 Carbon Dioxide Uptake in Grass Plants
# ChickWeight Weight versus age of chicks on different diets
# DNase Elisa assay of DNase
# EuStockMarkets Daily Closing Prices of Major European Stock
# Indices, 1991-1998
# Formaldehyde Determination of Formaldehyde
# HairEyeColor Hair and Eye Color of Statistics Students
# ......
# WorldPhones The World's Telephones
# ability.cov Ability and Intelligence Tests
# airmiles Passenger Miles on Commercial US Airlines,
# 1937-1960
# airquality New York Air Quality Measurements
# anscombe Anscombe's Quartet of 'Identical' Simple Linear
# Regressions
# attenu The Joyner-Boore Attenuation Data
# ...
Usaremos el data.frame airquality. Para cargar los datos en el espacio de trabajo global (‘Global Environment’)
tan solo es necesario usar la función data() y utilizando como argumento el nombre del conjunto de datos que
Con la ayuda de la función data() podemos ver todos los datos asociados a los paquetes que tenemos instalados
data(package = .packages(all.available = TRUE))
A continuación se pueden ver una serie de comandos usados habitualmente para trabajar con data.frames:
help("airquality") # nos muestra la descripción-ayuda del data.frame
class(airquality) # obtiene la clase
sapply(airquality, class) # obtiene la clase de todas las columnas
str(airquality) # estructura
summary(airquality) # sumario de airquality
head(airquality) # ver las primeras 6 observaciones
fix(airquality) # ver el data.frame en una ventana tipo grid
rownames(airquality) # nombres de filas
colnames(airquality) # nombres de columnas
nrow(airquality) # número de filas
ncol(airquality) # número de columnas
El modo más común y conveniente para obtener datos en R es a través de ficheros ‘.csv’. Hay paquetes R que
importan datos desde ficheros excel (‘.xlsx’) y de bases de datos.
La función read.table() nos ayuda a importar datos a un data.frame de R:
misDatos = read.table("c:/misdatosentrada.txt",header=FALSE,sep="|",
colClasses = c("integer","character","numeric"))
# importa ficheros .txt separados por '|'
R intuitivamente encuentra qué tipo de datos asignar a cada columna del data.frame. Pero si se quiere asignar
manualmente, puede hacerse con el argumento colClasses dentro de read.csv(), lo que se recomienda ya que
mejora la eficiencia del proceso de importación.
La función write.csv() nos permite guardar datos de R en un fichero con formato .csv.
write.csv(rdataframe,"c:/salida.csv") # exporta a fichero .csv
8. Tipos de Datos en R
No como en la mayoría de lenguajes, R usa el operador <- además del operador usual = para asignar valores.
a <- 10 # asigna 10 al objeto 'a'
a = 10 # igual que el anterior
10 -> a # asigna 10 al objeto 'a'
# 10 = a # Error!, esto intentaría asignar 'a' a 10
El carácter # (sostenido, fichero) indica un comentario. Cualquier cosa a la derecha del # (incluyéndolo a él mismo).
En el código anterior, habrás observado que no hay ningún paso para definir el tipo de variable. R intuitivamente
decide que clase asignar a la variable (u objeto).
class(a) # numeric (numérica)
## [1] "numeric"
Basado en el valor asignado a la variable a, R decide definir una clase de tipo numeric.
Si se quiere cambiar a tipo character (cadena de caracteres) ‘10’ en lugar de tipo numeric, se puede hacer lo
siguiente:
a <- as.character(a)
print(a) # muestra el valor de 'a'
## [1] "10"
class(a) # character
## [1] "character"
Se puede ver qué ocurre cuando se intenta convertir un character a numeric usando la función as.numeric().
La siguiente cuestión sería cuáles son los tipos de clases disponibles en R. La respuesta realmente es infinita, ya que
los usuarios pueden definir nuevas clases, pero las más comúnmente usadas son:
Tipos de variables:
character: cadenas de carácteres.
integer: enteros.
numeric: enteros más fracciones.
factor: variables categóricas donde cada nivel es una categoría.
logical: variables binarias o booleanas.
complex: números complejos.
Tipos de datos:
vector: una colección de elementos de la misma clase.
matrix: todas las columnas deben contener solo un tipo de variable, y ser de la misma longitud.
data.frame: las columnas pueden contener diferentes clases pero deben ser de la misma longitud.
list: pueden contener objetos de diferentes clases y longitudes.
El objeto más básico es un vector
Un vector puede contener únicamente objetos de la misma clase.
La única excepción es una lista (list), la cual se representa como un vector pero puede contener objetos de
diferentes clases.
Pueden crearse vectores vacíos con la función: vector().
8.3. Números en R
Los números en R son tratados de forma general como objetos numeric (es decir, números reales de precisión
doble).
Si queremos un entero de forma explícita, se añade el sufijo L, por ejemplo: 3L se refiere al número entero 3.
Hay un número especial Inf que representa al Infinito (∞); por ejemplo 1/0, o puede usarse como: 1/Inf que
es igual a 0.
El valor NaN representa un valor indefinido (“no es un número”), por ejemplo 0/0. No confundir NaN con un
valor NA (dato faltante).
8.4. Atributos
## [1] 0 0 0 0 0 0 0 0 0 0
Notación : y la función seq
1:5
## [1] 1 2 3 4 5
seq(1, 5, by=1)
## [1] 1 2 3 4 5
seq(1, 5, length=7)
## NULL
names(x) <- letters[1:length(x)]
#"letters" es un vector de cadenas que contiene las 26 letras en minúsculas
#"LETTERS" ídem para letras mayúsculas
x
## a b c d e f g h i j k l m n o
## -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4
## p q r s t u
## 0.5 0.6 0.7 0.8 0.9 1.0
La función rep
La función rep() repite un número o un vector. Observa los siguientes ejemplos de uso:
rep(1,10)
## [1] 1 1 1 1 1 1 1 1 1 1
rep(1:5,3) # rep(1:5,times=3)
## [1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
rep(1:5,each=3)
## [1] 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5
rep(1:5,each=3,times=2)
## [1] 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5
Los objetos pueden convertirse explícitamente en otra clase con las funciones: as.*
x = 0:6
class(x)
## [1] "integer"
as.numeric(x)
## [1] 0 1 2 3 4 5 6
as.logical(x)
## [1] 3 2 4 5 1
sample(6,3)
## [1] 2 6 5
sample(c(1,3,5),8,replace=TRUE)
## [1] 3 3 3 3 1 3 3 3
A continuación aparecen algunas de las funciones que nos permiten generar números aleatorios de las distintas
distribuciones estadísticas, todas ellas llevan una r delante.
rnorm(n, mean=0, sd=1) ##Gaussian (normal)
runif(n, min=0, max=1) ##Uniforme continua
rbinom(n, size, prob) ##Binomial
rgeom(n, prob) ##geometrica
rhyper(nn, m, n, k) ##hypergeometric
rpois(n, lambda) ##Poisson
rexp(n, rate=1) ##exponential
rt(n, df) ##t-Student (t)
rf(n, df1, df2) ##Fisher–Snedecor (F) (c2)
rchisq(n, df) ##Chi-Cuadrado de Pearson
Algunos ejemplos:
## [1] 78 98 61 71 77 88 62 26
Nota: Si cambiamos esa r por: d, p o q tendríamos la densidad, la función de distribución o la función inversa de la
función de distribución o cuantil de las distintas distribuciones (por ejemplo: rnorm, dnorm, pnorm, qnorm) con
argumentos casi idénticos.
paste() es una función que permite concadenar cadenas y personalizarla con los delimitadores que las unen. Será
fácil crear largas y complicadas cadenas-modelo que pueden modificarse dinámicamente.
Vemos algunos ejemplos de su uso en el siguiente código:
paste("a","b") # "a b"
paste0("a","b") # concadena sin espacios: "ab"
paste("a","b",sep="") # lo mismo que paste0
paste(c(1:4), c(5:8), sep="") # "15" "26" "37" "48"
paste(c(1:4), c(5:8), sep="",collapse="") # "15263748"
paste0(c("var"),c(1:5)) # "var1" "var2" "var3" "var4" "var5"
paste0(c("var","pred"),c(1:3)) # "var1" "pred2" "var3"
paste0(c("var","pred"), rep(1:3,each=2)) # "var1" "pred1" "var2" "pred2" "var3" "pred3"
## [1] "ol"
x = "Hola amigo"
substr(x,2,3) = "cara"
x
## [[1]]
## [1] "a" "b" "c" "d" "e" "f" "g"
toupper(x)
8.10. Matrices
## [1] 2 3
attributes(m)
## $dim
## [1] 2 3
m2 = matrix(1:3,nrow=3,ncol=2)
m2
## [,1] [,2]
## [1,] 1 1
## [2,] 2 2
## [3,] 3 3
m3 = matrix(c("a","b"),nrow=3,ncol=2)
m3
## [,1] [,2]
## [1,] "a" "b"
## [2,] "b" "a"
## [3,] "a" "b"
Las matrices pueden también crearse directamente desde vectores al añadirles el atributo dimensión.
m = 1:10
m
## [1] 1 2 3 4 5 6 7 8 9 10
dim(m) = c(2,5)
m
## x y
## [1,] 1 10
## [2,] 2 11
## [3,] 3 12
o pegando por filas con rbind()
rbind(x,y)
8.12. Listas
Las listas son un tipo especial de vector que puede contener elementos de diferentes clases. Las listas son un
tipo de dato muy importante en R por lo que deben conocerse muy bien.
x = list(1,"a",TRUE,1+4i)
x
## [[1]]
## [1] 1
##
## [[2]]
## [1] "a"
##
## [[3]]
## [1] TRUE
##
## [[4]]
## [1] 1+4i
l1 = list(1:3,c("a","b"),rep(TRUE,5),1+4i)
l1
## [[1]]
## [1] 1 2 3
##
## [[2]]
## [1] "a" "b"
##
## [[3]]
## [1] TRUE TRUE TRUE TRUE TRUE
##
## [[4]]
## [1] 1+4i
8.13. Factores
Los factores se usan para representar datos categóricos. Los factores pueden ser no ordenados u ordenados.
Podemos imaginar que un factor es como un vector de enteros donde cada entero tiene una etiqueta.
• Usar factores con etiquetas es mejor que usar enteros ya que los factores se autodescriben; tener una
variable que tienen los valores “hombre” y “mujer” es mejor que una variable que tiene los valores 1 y 2.
x <- factor(c("si","si","no","si","no"))
x
## [1] si si no si no
## Levels: no si
table(x)
## x
## no si
## 2 3
unclass(x)
## [1] 2 2 1 2 1
## attr(,"levels")
## [1] "no" "si"
Con la función gl, se puede crear un factor que siga un cierto modelo. A continuación se muestran algunos ejemplos
de uso:
gl(1,4)
## [1] 1 1 1 1
## Levels: 1
gl(2,4)
## [1] 1 1 1 1 2 2 2 2
## Levels: 1 2
gl(2,4, labels=c(T,F))
## [1] 1 2 1 2 1 2 1 2
## Levels: 1 2
gl(2,1,8, labels=c(T,F))
El orden de los niveles puede definirse usando el argumento levels de la función factor(). Esto podría ser
importante en modelos lineales ya que los primeros niveles se usan como niveles de referencia.
x <- factor(c("si","si","no","si","no"),
levels = c("si","no"))
x
## [1] si si no si no
## Levels: si no
y <- factor(c("si","si","no","si","no"),
ordered=T)
y
## [1] si si no si no
## Levels: no < si
z <- factor(c("si","si","no","si","no"),
levels = c("si","no"),ordered=T)
z
## [1] si si no si no
## Levels: si < no
Los valores missing se representan por NA, o NaN para operaciones matemáticas sin sentido.
• is.na() se usa para comprobar si los objetos son NA.
• is.nan() se usa para comprobar si los objetos son NaN.
• Los valores NA tienen también una clase, hay NA enteros, NA character, etc.
x <- c(1,2,NA,12,5)
is.na(x)
## caras barra
## 1 11 TRUE
## 2 12 TRUE
## 3 13 FALSE
## 4 14 FALSE
nrow(x)
## [1] 4
ncol(x)
## [1] 2
row.names(x)
Los objetos R también pueden tener nombres, lo que es muy útil para hacer el código legible y autodescrito.
x <- 1:3
names(x)
## NULL
names(x) = c("pri","seg","ter")
x
## $a
## [1] 1
##
## $b
## [1] 2
##
## $c
## [1] 3
m = matrix(1:4,nrow=2,ncol=2)
dimnames(m) = list(c("A","B"),c("C","D"))
m
## C D
## A 1 3
## B 2 4
9. Extracción de elementos en R
9.1. Subconjuntos
Existen varios operadores que pueden usarse para extraer subconjuntos de objetos R:
• [] siempre devuelve un objeto de la misma clase que el original; puede usarse para seleccionar más de un
elemento (hay una excepción).
• [[]] se usa para extraer elementos de una lista o de un data.frame; puede usarse para extraer un único
elemento y la clase del objeto devuelto no necesariamente será una lista o data.frame.
• $ se usa para extraer elementos de una lista o un data.frame por nombre; la semántica es similar a la de
[[]].
x = c("a","b","c","d","d","a")
x
## [1] "b"
x[1:3]
## [1] 8
sum(x1)
## [1] 50
mean(y1)
## [1] -0.6357157
prod(x1)
## [1] 446292
cumsum(x1)
## [1] 10 5 6 3 4 7 9 2 8 1
y1[order(y1)]
## [1] 10 8 4 5 2 3 6 9 7 1
Los subconjuntos sobre matrices se pueden hacer con índices del tipo (i,j):
x = matrix(1:6,2,3)
x
## [1] 3
x[2,1]
## [1] 2
Los índices también pueden estar vacíos:
x[1,]
## [1] 1 3 5
x[,2]
## [1] 3 4
## $pri
## [1] 1 2 3 4
x[[1]]
## [1] 1 2 3 4
x$seg
## [1] 0.6
x["seg"]
## $seg
## [1] 0.6
## $pri
## [1] 1 2 3 4
##
## $ter
## [1] "hola"
El operador [[]] puede usarse con índices calculados; $ solamente puede usarse con nombres literales.
x = list(pri=1:4, seg=0.6, ter="hola")
nombre = "pri"
x[[nombre]] # calculado
## [1] 1 2 3 4
x$nombre # elemento 'nombre' no existe
## NULL
x$pri
## [1] 1 2 3 4
El operador [[]] puede tomar una secuencia entera.
x = list(a = list(10,12,14), b=c(3.14, 2.81))
x[[c(1,3)]]
## [1] 14
x[[1]][[3]]
## [1] 14
x[[c(2,1)]]
## [1] 3.14
Se permiten las coincidencias parciales en los nombres con [[]] y $
x = list(abcd = 1:5)
x$a
## [1] 1 2 3 4 5
x[["a"]]
## NULL
x[["a",exact=FALSE]]
## [1] 1 2 3 4 5
## [1] 1 2 4 5
Si tenemos varios objetos y queremos elegir el subconjunto con ningún valor missing
x = c(1,2,NA,4,NA,5)
y = c("a","b",NA,"d","e",NA)
buenos = complete.cases(x,y)
buenos
## [1] 1 2 4
y[buenos]
Muchas operaciones en R son vectorizadas para hacer el código más eficiente, conciso, y más fácil de leer.
x = 1:4; y = 6:9
x+y
## [1] 7 9 11 13
x>2
## [1] 6 14 24 36
x/y
x = matrix(1:4,2,2); y = matrix(rep(10,4),2,2)
x * y # multiplicación elemento a elemento
## [,1] [,2]
## [1,] 10 30
## [2,] 20 40
x / y
## [,1] [,2]
## [1,] 0.1 0.3
## [2,] 0.2 0.4
x %*% y # multiplicación entre matrices habitual
## [,1] [,2]
## [1,] 40 40
## [2,] 60 60
sqrt(x) # raíz cuadrada de cada elemento de x
## [,1] [,2]
## [1,] 1.000000 1.732051
## [2,] 1.414214 2.000000
Para aplicar determinadas funciones a los distintos elementos de un objeto, en R existen varias funciones que nos
facilitan estas operaciones (MUY ÚTILES):
apply(X,MARGIN,FUN) #para un vector o array o lista de valores (X)
#le aplica una función (FUN) a las marginales
#(MARGIN, 1=filas, 2=columnas, 3=...) de X
lapply(X,FUN) #aplica FUN a cada elemento de la lista X
9.8. Ordenación
Las funciones R más habituales para realizar operaciones de ordenación son las siguientes:
sort(x) #crea un vector con los elemntos ordenados de x (tiene opciones)
tmp=sort(v,index.return=TRUE) #devuelve elementos ordenados e índices
#(s=tmp$x; idx=tmp$ix)
m[order(m[,1], m[,2], m[,3]),] #ordena la matriz m por primera columna,
#usa la segunda columna para romper empates, ...
df_datos = data.frame(A=c(70,40,50,30),
B=c(8,3,9,3),
C=c("Juan","Pablo","Enrique","Javier"))
df_datos
## A B C
## 1 70 8 Juan
## 2 40 3 Pablo
## 3 50 9 Enrique
## 4 30 3 Javier
sort(df_datos$A)
## [1] 30 40 50 70
order(df_datos$A)
## [1] 4 2 3 1
order(df_datos$C)
## [1] 3 4 1 2
df_datos[order(df_datos$A),]
## A B C
## 4 30 3 Javier
## 2 40 3 Pablo
## 3 50 9 Enrique
## 1 70 8 Juan
df_datos[order(-df_datos$A),]
## A B C
## 1 70 8 Juan
## 3 50 9 Enrique
## 2 40 3 Pablo
## 4 30 3 Javier
df_datos[order(df_datos$B,df_datos$C),]
## A B C
## 4 30 3 Javier
## 2 40 3 Pablo
## 1 70 8 Juan
## 3 50 9 Enrique
Filtrar filas y columnas puede hacerse usando las funciones subset() o which().
La función which(), devuelve un vector de índices de columnas o filas que verifican la condición.
A continuación, en el siguiente código, eliminamos la columna ‘Temp’ del data.frame ‘airquality’ y se devuelven
solamente las observaciones con ‘Day=1’. Hay que señalar que which() es una función independiente, por lo tanto,
debe usarse el nombre completo del objeto, por ejemplo, which(Day==1) no funcionaría, ya que no hay variable
llamada ‘Day’.
subset(airquality,Day == 1, select = - Temp) # selecciona Day=1 y excluye 'Temp'
## 32 NA 286 8.6 6 1
## 62 135 269 4.1 7 1
## 93 39 83 6.9 8 1
## 124 96 167 6.9 9 1
airquality[which(airquality$Day==1), -c(4)] # lo mismo que antes
## Wind Day
## 1 7.4 1
## 93 6.9 1
## 124 6.9 1
subset(airquality,Day==1 & Wind>6 & Wind<8,select=c("Wind","Day")) # lo mismo que antes
## Wind Day
## 1 7.4 1
## 93 6.9 1
## 124 6.9 1
Es una actividad muy habitual muestrear los datos en: conjuntos de entrenamiento (o training, datos con los
que construimos los modelos) y conjuntos test (datos conocidos en los que los modelos son probados).
Vemos a continuación cómo pueden crearse los conjuntos entrenamiento y test con 70:30 del data.frame ‘airquality’.
set.seed(100)
trainIndex <- sample(c(1:nrow(airquality)), size=nrow(airquality)*0.7, replace=F)
# anterior, obtiene índices del conjunto de entrenamiento
dt.train = airquality[trainIndex, ] # data.frame de entrenamiento
dt.test = airquality[-trainIndex, ] # data.frame test
head(dt.train)
## 11 7 NA 6.9 74 5 11
Se ha creado una muestra aleatoria del 70 % de los índices filas del data.frame ‘airquality’ y se ha usado para hacer
las muestras de entrenamiento y test. Necesitamos una muestra del 70 %, y se ha escrito ’size=nrow(airquality)*0.7’,
que calculará el 70 % de los números de filas en ‘airquality’.
Los data.frame pueden ser fusionados por una variable columna común. Los data.frame no necesariamente tienen
que estar ordenados antes de realizar la fusión. Si la columna ‘by’ tiene diferentes nombres, estas pueden especificarse
por los argumentos: ‘by.x’ y ‘by.y’. El inner/outer join, left y right join de las consultas SQL pueden llevarse a cabo
con los argumentos de merge: ‘all’, ‘all.x’, ‘all.y’. Consulte los ejemplos que vienen en la ayuda, escribiendo en la
consola de R example(merge).
vec1 <- c(10, 20, 15, 40) # vector numérico
vec2 <- c("a", "b", "c", NA) # vector caracteres
vec3 <- c(TRUE, FALSE, TRUE, TRUE) # vector lógico
vec4 <- gl(4, 1, 4, label = c("l1", "l2", "l3", "l4")) # factor 4 niveles
miDF1 <- data.frame(vec1, vec2) # crea data.frame con 2 columnas
miDF2 <- data.frame(vec1, vec3, vec4)
miDF1
miDF2
merge(miDF1,miDF2,by="vec1") # fusiona por la columna 'vec1'
Usa los siguientes data.frame, para realizar diferentes operaciones de fusión con merge().
set.seed(100)
df1 = data.frame(StudentId = c(1:10), Subject = sample(c("Matematicas", "Ciencias", "Arte"),
10, replace=T))
df2 = data.frame(StudentNum = c(2, 4, 6, 12), Sport = sample(c("Futbol", "Tenis", "Ajedrez"),
4, replace=T))
df1
## StudentId Subject
## 1 1 Matematicas
## 2 2 Matematicas
## 3 3 Ciencias
## 4 4 Matematicas
## 5 5 Ciencias
## 6 6 Ciencias
## 7 7 Arte
## 8 8 Ciencias
## 9 9 Ciencias
## 10 10 Matematicas
df2
## StudentNum Sport
## 1 2 Tenis
## 2 4 Ajedrez
## 3 6 Futbol
## 4 12 Tenis
# Operaciones merge
merge(df1,df2,by.x="StudentId",by.y = "StudentNum") # inner join
Las estructuras de control en R nos permiten controlar el flujo de ejecución del programa, dependiendo de las
condiciones del tiempo de ejecución.
Las estructuras más comunes son:
• if, else: comprueban una condición. switch.
• for: ejecuta un bucle un número fijo de veces.
• while: ejecuta un bucle mientras una condición sea verdadera.
• repeat: ejecuta un bucle infinito.
• break: finaliza la ejecución de un bucle.
• next: salta una iteración de un bucle.
• return: sale de una función.
La mayoría de las estructuras de control no se usan en sesiones interactivas, sino al escribir funciones o
expresiones grandes.
Operadores de comparación en R:
igual: ==
no igual: !=
mayor/menor que: > <
mayor/menor o igual que: >=, <=
Operadores lógicos en R:
Y lógico: &
O lógico: |
NO lógico: !
if (<condicion>) {
# hacer algo
} else {
# hacer algo en otro caso
}
if (<condicion1>) {
# hacer algo
} else if (<condicion2>) {
# hacer algo diferente
} else {
# hacer algo diferente
}
}
if (<condicion2>) {
Ejemplo:
x <- 1:10 # datos de ejemplo
ifelse(x<5 | x>8, x, 0)
## [1] 1 2 3 4 0 0 0 0 9 10
Para bucles se elige una variable iterador y asigna sus sucesivos valores de una secuencia o vector. Los bucles
for son más usados para iterar sobre los elementos de un objeto (list, vector, etc)
for (i in 1:10) {
print(i)
}
Este bucle selecciona la variable i y en cada iteración del bucle da los valores: 1, 2, 3, . . . , 10, y luego sale.
Estos tres bucles tienen el mismo comportamiento.
x = c("a","b","c","d")
for (i in 1:4) {
print(x[i])
}
for (i in seq_along(x)) {
print(x[i])
}
for (letter in x) {
print(letter)
}
Nota: ser cuidadoso con los bucles anidados, anidamientos de 2 o 3 niveles son más difíciles de leer/entender.
Los bucles while comienzan probando una condición. Si es verdad (TRUE), entonces se ejecuta el cuerpo del
bucle. Una vez que el cuerpo del bucle se ha ejecutado, la condición se prueba de nuevo, y así sucesivamente.
cuenta = 0
while (cuenta < 10) {
print(cuenta)
cuenta = cuenta + 1
}
Bucles while pueden potencialmente resultar en bucles infinitos sino se escriben convenientemente. Deben
usarse con cuidado.
Algunas veces podrá haber más de una condición que probar.
z = 5
while (z>=3 & z<=10) {
print(z)
moneda = rbinom(1,1,0.5)
if (moneda==1) { # camino aleatorio
z = z + 1
} else {
z = z - 1
}
}
repeat inicia un bucle infinito; no se usa habitualmente en estadística pero tienen sus usos. El único camino
de salir de un bucle repeat es llamando a break.
x <- 1
repeat {
print(x)
x = x+1
if (x == 6){
break
}
}
x0 = 1
tol = 1e-8
repeat {
x1 = calculoEstimador()
if (abs(x1-x0)<tol) {
break
} else {
x0 = x1
}
}
El bucle anterior es un poco peligroso ya que no hay garantía que se detenga. Lo mejor es definir un límite fijo
sobre el número de iteraciones (por ejemplo, usando for) y luego informar si la convergencia se alcanzó o no.
return indica que una función debe salir y devolver un valor dado.
Resumen:
• Las estructuras de control como if, while, y for permiten controlar el flujo de un programa R.
• Los bucles infinitos de forma general deben evitarse, aunque sean teóricamente correctos.
• Las estructuras de control citadas son útiles para escribir programas, para trabajo interactivo en la
consola, las funciones apply son más útiles.
10.11. Funciones
Las funciones se crean usando la directiva function() y son almacenadas como objetos R exactamente igual
que cualquier otro. En particular, son objetos R de la clase “function”.
f <- function(<argumentos>) {
# hacer algo interesante
}
Las funciones en R son “objetos de primera clase”, lo que significa que pueden considerarse como cualquier
otro objeto R.
• Las funciones pueden ser pasadas como argumentos a otras funciones.
• Las funciones pueden ser anidadas, así que puede definirse una función dentro de otra función.
El valor devuelto de una función es la última expresión en el cuerpo de la función que se evaluó.
Los nombres de la función puede ser casi cualquier cosa. Sin embargo, debe evitarse el uso de nombres de
funciones existentes.
Reglas de alcance. Las variables creadas dentro de una función existen solamente en el tiempo de vida de la
llamada a la función. Por lo que no son accesibles fuera de la función. Para forzar que variables en funciones
sean vistas globalmente, puede usarse el operador de asignación global <--.
## [1] TRUE
es.par(9)
## [1] FALSE
es.divisible.por <- function(numero.grande, numero.pequeno){
if (numero.grande %% numero.pequeno != 0)
return(FALSE)
return(TRUE)
}
es.divisible.por(10, 2)
## [1] TRUE
es.divisible.por(10, 3)
## [1] FALSE
es.divisible.por(9, 3)
## [1] TRUE
es.par <- function(num){
es.divisible.por(num, 2)
}
## function(x1, x2=5) {
## z1 <- x1/x1
## z2 <- x2*x2
## myvec <- c(z1, z2)
## return(myvec)
## }
myfct(x1=2, x2=5) # aplica la función a los valores 2 y 5
## [1] 1 25
myfct(2, 5) # los nombres de argumentos no serán necesarios,
## [1] 1 25
# pero el orden especificado es importante
myfct(x1=2) # igual que antes, pero el valor por defecto '5' se usa en este caso
## [1] 1 25
Función con argumentos opcionales
myfct2 <- function(x1=5, opt_arg) {
if(missing(opt_arg)) { # 'missing()' se usa para probar si se especificó un valor como argumento
z1 <- 1:10
} else {
z1 <- opt_arg
}
cat("mi función devuelve:", "\n")
return(z1/x1)
}
myfct2(x1=5) # realiza cálculos sobre vector por defecto (z1) definido en función
## mi función devuelve:
## [1] 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0
myfct2(x1=5, opt_arg=30:20) # se usa un vector personalizado en lugar del argumento opcional (opt_arg)
## mi función devuelve:
## [1] 6.0 5.8 5.6 5.4 5.2 5.0 4.8 4.6 4.4 4.2 4.0
Las funciones tienen argumentos con nombres los cuales potencialmente tienen valores por defecto.
• Los argumentos formales son los argumentos incluidos en la definición de la función.
• La función formals() devuelve una lista de todos los argumentos formales de una función.
• No todas las funciones llamadas en R hacen uso de todos los argumentos formales.
• Los argumentos de una función puede ser faltantes o pueden tener los valores por defecto.
Los argumentos de las funciones R pueden encontrarse por posición o por nombre. Por ejemplo, las siguientes
llamadas a la función sd son todas equivalentes.
misdatos = rnorm(100)
sd(misdatos)
sd(x = misdatos)
sd(x = misdatos, na.rm=FALSE)
sd(na.rm = FALSE, x = misdatos)
sd(na.rm = FALSE, misdatos)
Aunque es legal, no se recomienda mezclar el orden de los argumentos mucho, ya que puede llevar a confusión.
Podemos mezclar búsqueda posicional con búsqueda por nombre. Cuando un argumento es encontrado por
nombre, se “elige” de la lista de argumentos y los argumentos sin nombre que permanecen son buscados en el
orden que son listados en la definición de la función.
args(lm)
La mayoría de las veces, los argumentos nombrados son útiles en la línea de comandos cuando tenemos una
lista grande de argumentos y queremos usar los valores por defecto para cada cosa excepto para un argumento
cercano al final de la lista.
Argumentos nombrados también ayudan a recordar el nombre del argumento y no su posición en la lista de
argumentos (por ejemplo, la función plot() es un buen ejemplo de eso).
Además para no especificar un valor por defecto, podemos también definir un valor de argumento igual a NULL.
Los argumentos para las funciones son evaluados de forma perezosa, ya que se evalúan solamente cuando se
necesita.
f = function(a, b) {
a^2
}
f(2)
Esta función realmente nunca usa el argumento b, al llamar f(2) no producirá ningún error ya que el 2
encuentra el argumento a por posición.
Otro ejemplo
f = function(a, b) {
print(a)
print(b)
}
#> f(45)
#[1] 45
#Error in print(b) : el argumento "b" está ausente, sin valor por omisión
Observa que “45” se imprime primero antes de que se produzca el lanzamiento del error. Esto es porque “b”
no tiene que ser evaluado hasta después de “print(a)”. Una vez que la función intenta evaluar “print(b)” lanza
el error.
10.17. El argumento “. . . ”
El argumento “. . . ” indica un número variable de argumentos que son pasados realmente a otras funciones.
• “. . . ” se usa habitualmente cuando extendemos otra función y no queremos copiar la lista de argumentos
completa de la función original.
miplot = function(x, y, tipo=T, ...) {
plot(x,y,type=tipo,...)
}
Las funciones genéricas usan “. . . ” para pasar argumentos extras a los métodos.
mean
## function (..., file = "", sep = " ", fill = FALSE, labels = NULL,
## append = FALSE)
## NULL
Un problema con “. . . ” es que cualquier argumento que aparezca después de “. . . ” sobre la lista de argumentos
debe tener el nombre exacto y no parcialmente.
args(paste)
## [1] "a:b"
paste("a","b",se=":")
return: el flujo de evaluación de una función puede terminarse en cualquier parte con la función return().
Generalmente se usa con evaluaciones de condicionales.
stop(): para detener la acción de una función y mostrar un mensaje de error, puede usarse la función stop.
warning(): imprime un mensaje de aviso en situaciones inesperadas sin abortar el flujo de evaluación de la
función.
myfct <- function(x1) {
if (x1>=0) print(x1) else stop("Esta función no finaliza, ya que x1 < 0")
warning("Valor necesita ser > 0")
}
myfct(x1=2)
#[1] 2
#Warning message:
#In myfct(x1 = 2) : Valor necesita ser > 0
myfct(x1=-2)
#Error in myfct(x1 = -2) : Esta función no finaliza, ya que x1 < 0
Hay varias utilidades en R para hacer depuración (debugging) de código (y también en RStudio). Las más conocidas
son: browser() y debug().
Escribir bucles: for o while es útil cuando programamos pero no es fácil cuando trabajamos de forma
interactiva en la línea de comandos o consola.
Hay funciones en R que implementan estos bucles para hacernos la vida más fácil:
• lapply: recorre (bucle) una lista y evalúa un función para cada elemento.
• sapply: igual que lapply pero intenta simplificar los resultados.
• apply: aplica un función sobre las marginales de un array.
• tapply: aplica una función sobre subconjuntos de un vector.
• mapply: versión multivariante de lapply.
La función split es una función auxiliar muy útil, particularmente en conjunción con lapply.
lapply tiene 3 argumentos: una lista X, una función (o el nombre de una función) FUN, y otro argumento vía
argumento . . .
• Si X no es una lista, se convertirá a una lista usando la función as.list.
lapply
## $a
## [1] 3
##
## $b
## [1] -0.004101315
x = list(a=1:4, b=rnorm(10), c=rnorm(20,1),d=rnorm(100,5))
lapply(x, mean)
## $a
## [1] 2.5
##
## $b
## [1] 0.1295624
##
## $c
## [1] 1.152282
##
## $d
## [1] 4.906736
x = 1:4
lapply(x, runif)
## [[1]]
## [1] 0.3028884
##
## [[2]]
## [1] 0.07123327 0.66239047
##
## [[3]]
## [1] 0.7596036 0.5533602 0.5392721
##
## [[4]]
## [1] 0.8495923 0.6532260 0.9508858 0.6172230
x = 1:4
lapply(x, runif, min=0, max=10)
## [[1]]
## [1] 4.928406
##
## [[2]]
## [1] 9.760066 4.903452
##
## [[3]]
## [1] 6.551723 5.988018 9.475690
##
## [[4]]
## [1] 3.680115 8.781870 4.548751 4.964670
x = list(a=matrix(1:4,2,2), b=matrix(1:6,3,2))
x
## $a
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
##
## $b
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
lapply(x, colSums)
## $a
## [1] 3 7
##
## $b
## [1] 6 15
• Si el resultado es una lista donde cada elemento es un vector de la misma longitud (>1), devuelve una
matriz.
• Si no es posible encontrar un modelo simplificado, devolverá una lista.
x = list(a=1:4, b=rnorm(10), c=rnorm(20,1), d=rnorm(100,5))
lapply(x, mean)
## $a
## [1] 2.5
##
## $b
## [1] -0.01371844
##
## $c
## [1] 1.145113
##
## $d
## [1] 5.009561
sapply(x, mean)
## a b c d
## 2.50000000 -0.01371844 1.14511295 5.00956117
mean(x) # produce warning
apply se usa para evaluar una función (frecuentemente una función anónima) sobre las marginales de una
array.
• Es muy frecuente usar la función apply sobre las filas o columnas de una matriz.
• Puede usarse con arrays genéricos, por ejemplo, tomar la media de una array de matrices.
• Realmente no es más rápido que escribir un bucle, pero funciona en una única línea.
str(apply)
Para sumas y medias sobre las dimensiones de una matriz, existen funciones equivalentes:
• rowSums = apply(x,1,sum)
• rowMeans = apply(x,1,mean)
• colSums = apply(x,2,sum)
• colMeans = apply(x,2,mean)
Las funciones equivalentes son mucho más rápidas, pero no se notará excepto se use sobre matrices muy
grandes.
## [,1] [,2]
## [1,] -0.004879511 0.211119265
## [2,] 0.597110387 0.005750169
rowMeans(a,dims = 2)
## [,1] [,2]
## [1,] -0.004879511 0.211119265
## [2,] 0.597110387 0.005750169
–>
mapply es un apply multivariante de ordenaciones que aplica una función en paralelo sobre un conjunto de
argumentos.
str(mapply)
## [[1]]
## [1] 1 1 1 1
##
## [[2]]
## [1] 2 2 2
##
## [[3]]
## [1] 3 3
##
## [[4]]
## [1] 4
mapply(noise, 1:5,1:5,2)
## [[1]]
## [1] 0.1491205
##
## [[2]]
## [1] 1.600374 4.162554
##
## [[3]]
## [1] 1.838300 2.576522 2.175285
##
## [[4]]
## [1] 4.790926 1.325647 8.622636 3.299018
##
## [[5]]
## [1] 4.357793 4.142077 4.540777 4.888164 4.255909
Que es lo mismo que:
list(noise(1,1,2), noise(2,2,2),
noise(3,3,2), noise(4,4,2),
noise(5,5,2))
12. Dibujando en R
Las funciones plotf(), points(), lines(), text(), mtext(), axis(), identify() etc nos permitirán dibu-
jar puntos, líneas y texto.
Nota: puede ver algunas de las posibilidades que ofrece R usando:
demo(graphics)
Las siguientes formas de llamar a la función plot() dibujan y frente a x (también conocido como nube de puntos o
diagrama de dispersión):
plot(y ~ x) # usa una fórmula para especificar el gráfico
plot(x,y) # equivalente a la anterior
0.0
−0.5
−1.0
0 1 2 3 4 5 6
(0:20) * pi/10
x = (1:30)*0.92; y = sin((1:30)*0.92)
plot(x,y)
1.0
0.5
0.0
y
−0.5
−1.0
0 5 10 15 20 25
x
plot(y ~ x)
1.0
0.5
0.0
y
−0.5
−1.0
0 5 10 15 20 25
plot(y ~ x,type="l")
1.0
0.5
0.0
y
−0.5
−1.0
0 5 10 15 20 25
x
plot(y ~ x,type="b")
1.0
0.5
0.0
y
−0.5
−1.0
0 5 10 15 20 25
plot(y ~ x,type="h")
1.0
0.5
0.0
y
−0.5
−1.0
0 5 10 15 20 25
x
La función points() añade puntos a un gráfico creado con plot(), la función lines() añade líneas, la función
text() añade texto en localizaciones específicas, la función mtext() añade texto en uno de los márgenes, y la función
axis() da un control más preciso sobre las marcas y etiquetas sobre los ejes.
Con la función spline() nos permite ajustar curvas a los puntos facilitados:
plot(spline(x,y),type="l")
points(x,y)
1.0
0.5
spline(x, y)$y
0.0
−0.5
−1.0
0 5 10 15 20 25
spline(x, y)$x
Aplicar la función plot() sobre otros tipos de objetos, produce salidas diferentes. En el siguente ejemplo lo aplicamos
sobre un data.frame
class(airquality)
## [1] "data.frame"
plot(airquality) # nube de puntos entre todos los pares de columnas
pairs(airquality) # equivalente
0 100 250 60 80 0 10 20 30
100
Ozone
0
200
Solar.R
0
15
Wind
5
90
Temp
60
9
Month
7
5
Day
15
0
0 50 150 5 10 20 5 6 7 8 9
Los parámetros por defecto, tales como el tamaño del texto, el grosor de línea, etc, son generalmente adecuados. La
función par() nos permite cambiar los parámetros por defecto.
par(cex=1.25) # cambia el tamaño del texto
El primer uso de par() para hacer cambios al dispositivo actual de dibujo, se almacenan los parámetros existentes,
para que puedan ser restaurados más tarde.
par.viejos = par(cex=1.25,mex=1.25) # mex=1.25 expande el margen un 25%
En este ejemplo, se han guardado los parámetros existentes en el objeto par.viejos, y además se han cambiado
los parámetros: cex y mex. Para restaurar los parámetros a los valores anteriores, introduciríamos la expresión R:
par(par.viejos). A continuación, se muestra un ejemplo de uso:
par.viejos = par(cex=1.25,mex=1.25) # mex=1.25 expande el margen un 25%
plot(x,y)
1.0
0.0
y
−1.0
0 5 10 15 20 25
x
par(par.viejos)
El parámetro mfrow puede usarse para configurar la hoja de gráficos para que los gráficos consecutivos aparezcan
distribuidos en filas, uno detrás de otro en forma rectangular, sobre una página. Para una disposición por columnas,
usar mfcol. En el siguiente ejemplo, se presentan 4 transformaciones diferentes de los datos originales, en un formato
2x2:
p.viejos = par(mfrow=c(2,2), pch=16)
library(MASS)
plot(Animals$body,Animals$brain)
plot(sqrt(Animals$body),sqrt(Animals$brain))
plot((Animals$body)^0.1,(Animals$brain)^0.1)
plot(log(Animals$body),log(Animals$brain))
sqrt(Animals$brain)
Animals$brain
3000
40
0
0
0 20000 60000 0 50 100 150 200 250 300
Animals$body sqrt(Animals$body)
(Animals$brain)^0.1
log(Animals$brain)
8
2.0
4
1.0
(Animals$body)^0.1 log(Animals$body)
par(p.viejos)
En el siguiente ejemplo, se muestran dos gráficos, donde el de la derecha es una mejora del gráfico de la izquierda. A
ambos se les ha añadido texto.
p.viejos = par(mfrow=c(1,2))
library(MASS)
primates = Animals[row.names(Animals) %in% c("Potar monkey",
"Gorilla","Human","Rhesus monkey","Chimp"),]
plot(primates$body,primates$brain)
#' pos=4 # texto a la derecha del punto
text(x=primates$body,y=primates$brain,labels=row.names(primates),pos=4)
##' Gráfico 2
plot(primates$body,primates$brain,pch=16,
xlab="Peso Cuerpo (kg)",ylab="Peso Cabeza (g)",
xlim=c(0,280),ylim=c(0,1350))
text(x=primates$body,y=primates$brain,labels=row.names(primates),pos=4)
1400
Human Human
1000
1000
600
600
Gorilla
Gorilla
200
Rhesus monkey
200
Título gráfico
Subtítulo
Human
Comentario 2
1300
1200
1100
1000
Peso Cabeza (g)
900
Subtítulo Y
800
700
600
500
Comentario 1
400 Gorilla
300
200 Rhesus monkey
100 Potar monkey
0
En el siguiente ejemplo, usaremos el parámetro cex (tamaño carácter), col (color de los símbolos) y pch (símbolo).
Nota: type="n" no pinta ningún símbolo.
plot(1,1,xlim=c(1,7.5),ylim=c(1.75,5),type="n",axes=F,xlab="",ylab="")
box()
#' primera fila
points(1:7,rep(4.5,7),cex=1:7,col=1:7,pch=0:6)
#' segunda fila
text(1:7,rep(3.5,7), labels=paste(0:6),cex=1:7,col=1:7)
#' tercera fila
points(1:7,rep(2.5,7), pch=(0:6)+7)
text(1:7,rep(2.5,7), paste((0:6)+7),pos=4)
#' cuarta fila
points(1:7,rep(2,7), pch=(0:6)+14)
text(1:7,rep(2,7), paste((0:6)+14),pos=4)
0 1 2 3 4 56
7 8 9 10 11 12 13
14 15 16 17 18 19 20
Se pueden utilizar otras paletas de colores con el parámetro col, por ejemplo: col=rainbow(6).
palette()[1:7] # equivale a: col=1:7