Programación en R 1 Introducción a la programación en R ¿Qué es un programa de ordenador? Un programa de ordenador consiste en una secuencia de instrucciones que un ordenador pueda entender. El procesador de los ordenadores sólo es capaz de comprender un número limitado de instrucciones, y ello en un lenguaje incomprensible para la mayoría de personas. En la práctica, los programas se escriben en otros lenguajes más inteligibles para los humanos, como Pascal, Fortran, Java, o C, por citar algunos de los más conocidos. Luego, los programas escritos en estos lenguajes de alto nivel se traducen al lenguaje que entienden los procesadores. Está traducción la hacen otros programas que se denominan compiladores o intérpretes. ¿Qué es R? R es un dialecto de S. S es un lenguaje que se desarrolló para el análisis de datos, cálculos estadísticos, simulación y gráficos. Además, y eso es lo que nos interesa más aquí, es un lenguaje de programación de tipo general. S-Plus es la versión comercial de S. R es la versión en código abierto y gratuita de S. Componentes básicos de un programa Los programas de ordenador pueden llegar a ser muy complejos, pero, en realidad todos ellos constan de muy pocos componentes. El aprendizaje de los componentes básicos no es difícil. Esto es especialmente cierto en R, que es un lenguaje de programación con pocos requerimientos, por lo que se pueden escribir programas sencillos en poco tiempo. Cuando se ejecuta un programa es necesario acceder a la memoria interna del procesador. La mayoría de lenguajes no permiten el acceso directo a dicha memoria, sino que el acceso se hace mediante unas entidades denominadas variables. Estas variables pueden contener números, caracteres u otras estructuras más complejas. A lo largo del programa el contenido de una variable puede cambiar de valor. Los programas se estructuran en sentencias, las cuales se van ejecutando unas detrás de otras. Las sentencias pueden ser simples o complejas. Las sentencias complejas constan de varias sentencias simples. Para que un programa pueda hacer cosas interesantes es necesario que se le permita bifurcarse. Normalmente esto se hace mediante la evaluación de una condición lógica. Si ésta es cierta el programa hace una cosa y si es falsa hace otra cosa distinta. Los ordenadores son excelentes haciendo tareas repetitivas. Estas tareas que hay que realizar muchas veces se ponen dentro de unas estructuras conocidas como bucles. A veces nos encontramos dentro de un programa con partes muy parecidas, solo que unas veces se aplican a unas variables y otras veces a otras. Los lenguajes de programación suelen permitir unas estructuras (funciones en R) que pueden ser ejecutadas de forma ligeramente distinta dependiendo de unos parámetros o argumentos que se pasan en el momento de la ejecución. J Piñol Taller de Modelización Programación en R 2 Variables Las más elementales que nos encontraremos contendrán números (enteros o reales) o tiras de caracteres. Los nombres de las variables empiezan por una letra que puede ir seguida de más letras, dígitos o los símbolos punto (.) y subrayado (_). Las letras mayúsculas y minúsculas son tratadas como caracteres distintos. Para dar un valor a una variable se usa el símbolo de asignación <-. En R, a diferencia de otros lenguajes, no es necesario declarar a priori el nombre y el tipo de las variables. Para crear una variable denominada r que valga 2.5 basta con escribir: r <- 2.5 El signo de asignación <- se tiene que interpretar como una flecha que apunta a la izquierda y que dice que ponemos el valor 2.5 en la variable r. Para saber el contenido de una variable basta con teclear su nombre r [1] 2.5 Si queremos que una variable contenga una tira de caracteres introduciremos dichos caracteres entre comillas (“…”) apellido <- “Ferrer” Un tipo especial de variables contiene los valores lógicos cierto (TRUE) y falso (FALSE) condicion <- TRUE Muy a menudo conviene guardar varias variables del mismo tipo bajo el mismo nombre. Para ello usamos vectores y para asignarles valores se usa la función c primos <- c(1, 2, 3, 5, 7, 11, 13, 17, 19) Se puede acceder al vector entero por su nombre primos [1] 1 2 3 5 7 11 13 17 19 O a uno de sus elementos proporcionando la posición del mismo (el quinto elemento del vector primos es el número 7) primos[5] [1] 7 Operaciones aritméticas Suma Diferencia Producto J Piñol + * Taller de Modelización Programación en R 3 División División entera Módulo (resto) Potencia / %/% %% ^ Ejemplos: a <- 4 b <- 3 suma <- a + b diferencia <- a producto <- a * division <- a / potencia <- a^b division_entera modulo <- a%%b suma [1] 7 diferencia [1] 1 producto [1] 12 division [1] 1.333333 potencia [1] 64 division_entera [1] 1 modulo [1] 1 - b b b <- a %/% b A diferencia de otros lenguajes de programación, R puede efectuar operaciones directamente con vectores. Es fácil, por ejemplo, obtener el cuadrado de cada uno de los elementos contenidos en el vector primos primos^2 [1] 1 4 9 25 49 121 169 289 361 Bifurcaciones A veces nos interesa ejecutar alguna parte del programa dependiendo de alguna condición. Para ello R dispone de la instrucción if: alpha <- 2 if (alpha > 1) x <- 99 x [1] 99 Si la sentencia que se desea ejecutar cuando se cumple la condición es compleja, es decir, está compuesta de varias sentencias simples, entonces estas deben agruparse dentro de los símbolos “{” y “}”. Las sentencias simples se separan unas de otras mediante el símbolo “;” o mediante el salto de línea. J Piñol Taller de Modelización Programación en R 4 alpha <- 2 if (alpha > 1){ x <- 99 y <- 999} x [1] 99 y [1] 999 A menudo nos interesa indicar también lo que se debe hacer si no se cumple la condición. Para ello tenemos una variación de la sentencia if que es if … else alpha <- 0 if (alpha > 1) x <- 99 else x <- -99 x [1] -99 La sentencia que sigue a else puede ser a su vez una sentencia if, de forma que se pueden encadenar una serie de secuencias if … else if … else … alpha <- 1 if (alpha > 1) x <- 99 else if (alpha < 1) x <- -99 else x <- 0 x [1] 0 Bucles Hay dos tipos de bucles dependiendo de si conocemos de antemano el número de veces que hay que repetirlo (iteraciones). Si sabemos a priori el número de iteraciones la instrucción en R es for; por el contrario, si el número de iteraciones depende de los cálculos que se efectúen en el propio bucle la instrucción adecuada en R es while. Por ejemplo, si deseamos calcular e imprimir los cuadrados de los 10 primeros números naturales bastan con for [1] [1] [1] [1] [1] [1] [1] [1] [1] [1] (i in 1:10) print(i^2) 1 4 9 16 25 36 49 64 81 100 La variable i del bucle anterior se denomina variable de control del bucle. En el paréntesis que sigue a for indicamos el nombre de la variables de control y como debe variar mediante la instrucción in (entre 1 y 10 en este ejemplo). Aunque puede hacerse, es desaconsejable alterar dicho valor dentro del mismo bucle for. J Piñol Taller de Modelización Programación en R 5 Por supuesto, la sentencia que sigue a for puede ser compleja. Por ejemplo, si deseamos generar cinco números aleatorios de distribución uniforme entre 0 y 1 (función runif) e imprimirlos basta con for (i in 1:5){ x <- runif(1) print(x) } [1] 0.5627295 [1] 0.8562093 [1] 0.3574094 [1] 0.9727754 [1] 0.6712237 Supongamos ahora que queremos escribir todos los números naturales cuyo cubo sea inferior a 100. Un bucle while nos permite hacerlo fácilmente: i <- 1 i3 <- i^3 while (i3 < 100){ cat(i, i3, "\n") i <- i + 1 i3 <- i^3 } La palabra clave while va seguida de una condición. Si la condición es cierta se ejecuta la sentencia (compleja en este caso) que sigue. Después de ejecutar la sentencia se evalúa de nueva la misma condición (ahora con un valor distinto de i3) y si es cierta se ejecuta de nuevo. Cuando deja de cumplirse la condición el programa prosigue con la siguiente sentencia. Dentro del bucle se escribe el número natural que cumple la condición de que su cubo es menor que 100, se incrementa a cada paso la variable de control y se calcula el nuevo cubo. En este caso usamos la función cat para imprimir el resultado en lugar de la función print; cat permite concatenar el output ("\n" indica salto de línea). Funciones Una de las grandes ventajas de trabajar con R es que dispone de una gran cantidad de funciones escritas por miles de programadores en todo el mundo y puestas a nuestra disposición en Internet. Pero no siempre existirá la función que nosotros queramos, por lo que también es conveniente que sepamos crear nuestras propias funciones. Una función se define de la siguiente forma nombre <- function (lista_de_parametros) cuerpo_de_la_funcion donde nombre es el nombre de la función, function es una palabra reservada que indica que lo que sigue es una función, lista_de_parametros es una lista separada por comas que contiene los parámetros que se pueden pasar a la función y cuerpo_de_la_funcion es una serie de sentencias válidas en R, normalmente incluidas dentro de los símbolos “{” y “}”. J Piñol Taller de Modelización Programación en R 6 Una vez definida la función se puede invocar desde nuestro programa de la forma siguiente x <- nombre (par1, par2, par3) En la variable x obtendremos el resultado de aplicar la función nombre a los parámetros indicados (par1, par2, par3, en este ejemplo). Entenderemos mejor su funcionamiento con un ejemplo. R dispone de la función log para calcular el logaritmo natural de un número. También dispone de las funciones log2 y log10 para calcular los logaritmos en base 2 y base 10, respectivamente. Estas funciones se pueden invocar directamente puesto que ya vienen en la implementación por defecto de R: x <- log10(1000) x [1] 3 Supongamos que nosotros tuviéramos que efectuar en nuestro programa repetidas veces el cálculo del logaritmos en base 5 de un número. Para facilitar nuestra tarea lo mejor sería crear una función log5 que efectuara el cálculo. Veamos como: # devuelve el logaritmo en base 5 de un número log5 <- function(x){ y <- log(x) / log(5) return(y) } La instrucción return le dice a la función el valor que debe devolver. No es necesario que toda función contenga la instrucción return; hay muchas funciones que efectúan distintas tareas sin necesidad de devolver un resultado. La invocación de log5 nos proporciona el resultado deseado log5(25) [1] 2 Más general todavía sería la siguiente función que calcula logaritmos en cualquier base #Devuelve el logaritmo de un número en la base indicada logBase <- function(x, base){ y <- log(x) / log(base) return(y) } J Piñol Taller de Modelización Programación en R 7 Ejercicios 1. Escribir un programa que intercambie los valores de dos variables denominadas x e y. 2. Escribir un programa que escriba “Hola” si el valor de la variable x es menor que 0.5 y que escriba “Adiós” si x es mayor que 0.5. 3. Escribir un programa que genere 1000 números aleatorios (con distribución uniforme entre 0 y 1), que cuente los que son mayores y los que son menores o iguales que 0.5 y que escriba la respuesta. [Podemos generar los 100 números aleatorios en una sola instrucción de la siguiente forma: x <runif(1000)] 4. Escribir un programa que genere los primeros cien términos de la serie de Fibonacci. 5. Calcular el cociente entre términos consecutivos de la serie de Fibonacci y representar dichos valores. [La función plot(x) dibuja los valores del vector x] 6. Escribir un programa que genere números aleatorios (con distribución uniforme entre 0 y 1) hasta que encuentre uno que sea mayor que 0.9999 y que diga cuantos intentos ha necesitado. 7. Escribir una función que devuelva el valor medio de dos números. 8. Generar un vector de n números aleatorios con distribución normal y mostrar el valor mayor de todos. [rnorm(n, mean=0, sd=1) genera n números aleatorios con distribución normal de media 0 y desviación típica 1] 9. Hacer un programa que simule el crecimiento exponencial de una población con tasa finita de crecimiento λ y población inicial N0. Hacer un gráfico con el tamaño poblacional hasta un tiempo t = 100. 10. **Generar un vector de n números aleatorios y mostrarlo ordenado de mayor a menor. Obtención, instalación y ejecución de R R se ha desarrollado para las plataformas Unix, Windows y MAcOS. El copyright de R pertenece a “The R Foundation for Statistical Computing”, aunque se trata de software libre, por lo que su utilización es libre y gratuita. Los archivos de R se encuentran en el “Comprehensive R Archive Network”, o CRAN, en http://cran.r-project.org. En esta dirección se pueden descargar los archivos y la documentación necesaria para instalar R en nuestro ordenador. El archivo principal que se necesita es el de instalación (“setup file”); en el momento de redactar este documento, el nombre del archivo de instalación era R-2.5.1-win32.exe, lo que indica que se trata de la versión 2.5.1 de R. Este archivo es autoejecutable y instalará R automáticamente en nuestro ordenador una vez finalizada la descarga (de unas 29 MBytes). Para ejecutar R basta con clicar sobre el icono de R. Una vez iniciado el programa se puede obtener abundante información adicional sobre R mediante la ayuda del propio programa. En particular, es conveniente acudir a los manuales en pdf que contiene. J Piñol Taller de Modelización Programación en R 8 Con la operación anterior se habrá instalado la versión básica de R. Sin embargo, existen numerosas librerías de funciones de R que pueden sernos de utilidad en algún momento y que hay que instalar manualmente. Algunas de estas funciones se han descargado a nuestro ordenador con la instalación efectuada pero no se cargan automáticamente al ejecutar R. Podemos cargar estas librerías con la instrucción “Load package” de la pestaña “Packages” del programa. Alternativamente, podemos utilizar la instrucción library library(lattice) En este ejemplo se ha cargado la librería lattice, con la que es posible realizar un gran número de representaciones gráficas. Teclear help(lattice) en R para obtener más información. Hay otras librerías que no se han descargado a nuestro ordenador con la configuración básica. Si deseamos utilizar alguna de ellas se deben descargar manualmente (normalmente en formato zip) e instalar con la instrucción “Install packages from local zip files” de la pestaña “Packages” del programa. Una vez realizada esta operación hay que cargar la libraría deseada con la instrucción library. Instalación y ejecución de Tinn-R Tinn-R es un editor para escribir programas en R. No es imprescindible, ya que los programas se pueden escribir como scripts en el editor que proporciona el propio compilador de R (Rgui). Sin embargo, Tinn-R facilita notablemente esta tarea. Tinn-R es, al igual que R, un software de utilización libre y gratuita. Se puede descargar en https://sourceforge.net/projects/tinn-r. En el momento de redactar este documento el fichero de instalación (setup) era Tinn-R_2.3.2.3_setup.exe, el cual instalaba la versión 1.19.2.3 de Tinn-R. Una vez instalado, podemos ejecutar Tinn-R clicando sobre el icono correspondiente. El programa tiene un conjunto de menús más o menos estándar que permite abrir o crear nuevos ficheros de código (menú ‘File’), o trabajar con conjuntos de ficheros relacionados (menú ‘Project’). Una de las ventajas de Tinn-R sobre el editor de Rgui es que Tinn-R resalta la sintaxis utilizando colores distintos para indicar diferentes tipos de código, lo cual facilita mucho la detección de errores. Por ejemplo, los fragmentos comentados (#) se muestran en color verde y en cursiva; las palabras reservadas (funciones y parámetros de R, por ejemplo) se muestran en rojo, azul y fucsia, dependiendo de su tipo; mientras que los valores numéricos y las variables creadas por el usuario se muestran en negro. Tinn-R ofrece también opciones avanzadas de búsqueda, formato y visualización. Una vez escrito el programa de R utilizando Tinn-R, lo primero que hemos de hacer para ejecutarlo es abrir la consola de R (opción R: Start preferred Rgui). Una vez hecho esto podemos ejecutar todo el código de una vez (R: Send to R: All) o por fragmentos (R: Send to R: Selection), lo cual facilita mucho tanto la detección de errores como la construcción del código de una manera modular. Tinn-R permite también interactuar con la consola de R para controlar la ejecución de los programas mediante la opción R: Controlling R. Se puede obtener abundante información adicional consultando la ayuda que ofrece el propio programa. J Piñol Taller de Modelización