Consideraciones y conceptos básicos
Antes de iniciar con la actividad de hoy es fundamental conocer un poco del vocabulario usado en este lenguaje de programación. algunos conceptos básicos tienen una nomenclatura en concreto que deberíamos manejar como lenguaje con común para que no hayan confusiones al momento de desarrollar las actividad.
Ejecución y devolución
Cuando hablamos del concepto ejecutar, llamar o correr nos referimos a pedir que R realice algo, en otras palabras, estamos dando una instrucción o una entrada .
Cuando hablamos de línea de código, hacemos referencia a cada linea con instrucciones específicas, las cuales pueden ser simples o complejas, dependiendo de cuantas instrucciones concatenadas se les haya incluido.
Cuando decimos que R nos devuelve algo, es que ha realizado algo que le hemos pedido, es decir, nos está dando una **salida* o respuesta de la instrucción solicitada.
Por ejemplo, si escribimos la línea de código siguiente en la consola y en seguida presionamos enter, estamos pidiendo que se ejecute la operación 1 + 1
, ello nos devolverá su resultado que es [1] 2
. Es así que el la primera parte estamos ejecutando o corriendo una linea de código, mientras que la consola nos devuelve o retorna el resultado.
# Ejecutamos una suma
1+1
## [1] 2
Por otro lado Una función, a grandes rasgos, es una serie de operaciones a las que les hemos asignados un nombre. Las funciones aceptan argumentos, es decir, especificaciones sobre cómo deben funcionar. Cuando llamamos una función, se realizan las operaciones que ésta contiene, usando los argumentos que hemos establecido.
directorios
El directorio o carpeta de trabajo es el lugar en nuestra computadora en el que se encuentran los archivos con los que estamos trabajando en R. Este es el lugar donde R buscara archivos para importarlos y al que serán exportados, a menos que indiquemos otra cosa.
Cómo ya habrán visto en la clase anterior, pueden encontrar cuál es el directorio de trabajo con la función getwd()
, mientras que para cambiar el directorio de trabajo se utiliza setwd()
, donde el principal argumento corresponde a la ruta en que trabajarán.
# revisamos el directorio de trabajo
getwd()
## [1] "G:/github/MODULO_03"
# definimos un nuevo directorio raiz
setwd("G:/nuevo directorio")
En el próximo módulo podrán estudiar más en detalle esta funciones y sus parámetros, así como también, podrán manipular ficheros y directorios para un trabajo más eficiente.
Paquetes
R puede ser expandido con paquetes o bibliotecas que permiten una manipulación más eficiente de la programación en función de sus objetivos específicos. Cada paquete es una colección de funciones diseñadas para atender una tarea específica. Por ejemplo, hay paquetes para trabajo visualización geoespacial, análisis psicométricos, minería de datos, interacción con servicios de Internet y muchas otras cosas más.
Podemos instalar paquetes usando la función install.packages()
, dando como argumento el nombre del paquete que deseamos instalar, entre comillas. Una vez concluida la instalación de un paquete, debemos cargarla en nuestro ambiente de trabajo, para así, poder usar sus funciones, esto se hace llamando a la función library()
o require()
, el único argumento necesario en esta función, será el nombre del paquete que queramos utilizar.
# instalamos paquetes
install.packages(c("raster","rgdal"))
# Cargamos paquetes
library(raster)
## Loading required package: sp
## rgdal: version: 1.5-12, (SVN revision 1018)
## Geospatial Data Abstraction Library extensions to R successfully loaded
## Loaded GDAL runtime: GDAL 3.0.4, released 2020/01/28
## Path to GDAL shared files: C:/Users/Admin/Documents/R/win-library/3.6/rgdal/gdal
## GDAL binary built with GEOS: TRUE
## Loaded PROJ runtime: Rel. 6.3.1, February 10th, 2020, [PJ_VERSION: 631]
## Path to PROJ shared files: C:/Users/Admin/Documents/R/win-library/3.6/rgdal/proj
## Linking to sp version:1.4-2
## To mute warnings of possible GDAL/OSR exportToProj4() degradation,
## use options("rgdal_show_exportToProj4_warnings"="none") before loading rgdal.
Por último, haremos referencia al concepto de script, los scripts son documentos de texto plano como cualquier otro documentos de texto, pero que permite la lectura y ejecución de las lineas de código R contenidas en éste.
Esquema de estructuración
Como ya habrán podido darse cuenta durante el desarrollo del curso, al momento de generar un script, éste se ejecuta de manera secuencial, y por lo tanto es necesario definir una estructura lógica para si escritura. Existen muchas formas en que pueden estructurar los script, a continuación, se les plantea uno de los esquemas más extendidos en el mundo de la programación.
Es posible diferenciar 3 bloques bien definidos que se aprecian en la imagen siguiente y que pasaremos a detallar a continuación.
main o cuerpo principal
Corresponde al bloque en el que se desarrollará la gran mayoría del código, en éste se cargarán los datos, constantes o variables de entrada (o iniciales) necesarias para desarrollar los procesos, se escriben los procesos a realizar en función de las operaciones aritméticas y lógicas definidas por las diversas estructuras de control (de las cuales hablaremos en unos instantes) y por último se guardarán los resultados de los procesos, exportándolos a sus respectivos formatos de salida.
Estructuras de control
Anteriormente mencionamos que las operaciones que se desarrollan en el main estaban definidas por las estructuras de control, justamente, como su nombre lo indica, éstas permiten controlar la manera en que se ejecuta nuestro programa.
Las estructuras de control establecen condiciones y rutinas para la ejecución del código. Un ejemplo de esto sería indicar las condiciones que se deben cumplir para realizar una operación aritmética o las necesarias para ejecutar una función en particular.
Esto es de gran utilidad para determinar la lógica y el orden en que ocurren las operaciones, en especial al definir funciones.
Es posible reconocer 3 principales tipos de estructuras de control, por un lado tenemos las estructuras de secuencia, la cual se caracterizan por ser el tipo de estructura mas simple y consta de ejecutar instrucciones en un orden especifico, una tras otra, este tipo de estructura se puede agrupar en 3 tipos de algoritmos, Asignación, Entrada y Salida.
Las estructuras condicionales o de decisión, por otro lado, son estructuras que permiten seleccionar la rama del código a ejecutar dependiendo de la falsedad o veracidad de una o varias expresiones lógicas, dicho resultado sera utilizado por una estructura condicional para desviar el flujo de ejecución de un programa, es decir, si la condición es verdadera se hace una cosa y si es falsa se hace otra. la estructura condicional se puede clasificar cómo simple (una respuesta si es verdadero y otra si es falso) o compleja (dependiendo de la decisión se tomará una rama u otra).
Esta estructura la podemos observar en nuestra vida cotidiana tal como lo podemos observar en el siguiente diagrama
Por último, la estructura de bucle, cíclica o también llamada iterativa cumplen la función de ejecutar un bloque de código un numero definido de veces, es decir como su nombre lo dice, repiten las mismas lineas de código una y otra vez según sea necesario. Podemos identificar 3 tipos de estructuras cíclicas, las que se ejecutan mientras se siga cumpliendo una condición, aquellas que se ejecutan hasta que se cumple una condición o las que se ejecutan una cantidad definida de veces.
Las estructuras de control más usadas en R son las siguientes.
Condicional |
if /else |
Si / de lo contrario |
Bucle |
for |
Para cada uno en |
Bucle |
while |
Mientras |
Bucle |
repeat |
ejecuta |
Secuencia |
break |
Interrupción |
Secuencia |
next |
Siguiente |
Operaciones condicionales
Tal como mencionamos anteriormente, las operaciones condicionales nos permiten tomar decisiones y desviar el flujo de código por distintas ramas de éste. una de las funciones más utilizadas cómo estructura de control condicional es if/else
.
if
(si) es usado cuando deseamos que una operación se ejecute únicamente cuando una condición se cumple. else
(de lo contrario) es usado para indicarle a R qué hacer en caso de la condición de un if no se cumpla.
se utiliza if
para decirle a R SI esta condición es cierta, ENTONCES haz estas operaciones, a continuación podemos apreciar la sintaxis necesaria para usar esta función.
# si se cumple la condición, enconces haz lo siguiente
if(Condición) {
operaciones_si_la_condición_es_TRUE
}
Si la condición se cumple, es decir, es verdadera (TRUE
), entonces se realizan las operaciones. En caso contrario, no ocurre nada y el código con las operaciones no es ejecutado. Si la condición conlleva a realizar una única acción, es posible usarla siguiente sintaxis.
# si se cumple la condición, enconces haz lo siguiente
if(Condición) operaciones_si_la_condición_es_TRUE
Por ejemplo, le pedimos a R que nos muestre el texto “Verdadero” si la condición se cumple.
# Se cumple la condición y se muestra "verdadero"
if(4 > 3) {
"Verdadero"
}
## [1] "Verdadero"
# No se cumple la condición y no pasa nada
if(4 > 5) {
"Verdadero"
}
En el caso que nuestra intención sea que el código ejecute una acción cuando la condición sea verdadera y otra cuando sea falsa, es posible utilizar el operador else
que complementa al if
, pues indica qué ocurrirá cuando la condición no se cumple, sea falsa (FALSE
), en lugar de no hacer nada.
Por lo tanto, utilizar la sentencia if
acompañada de un else
es como que planteemos que SI esta condición es cierta, ENTONCES realizamos estas operaciones, DE LO CONTRARIO realizamos estas otras operaciones.
Es así que la sintaxis para plantear esta sentencia será
# si se cumple la condición, enconces haz lo siguiente de lo cotnrario, haz lo otro
if(condición) {
operaciones_si_la_condición_es_TRUE
} else {
operaciones_si_la_condición_es_FALSE
}
Si la condición conlleva a realizar una única acción, es posible usarla siguiente sintaxis.
# si se cumple la condición, enconces haz lo siguiente de lo cotnrario, haz lo otro
if(condición) operaciones_si_la_condición_es_TRUE else operaciones_si_la_condición_es_FALSE
Usando los ejemplos anteriores, podemos mostrar “Falso” si no se cumple la condición, en lugar de que no ocurra nada.
# Se cumple la condición y se muestra "Verdadero"
if(4 > 3) {
"Verdadero"
} else {
"Falso"
}
## [1] "Verdadero"
# No se cumple la condición y se muestra "Falso"
if(4 > 5) {
"Verdadero"
} else {
"Falso"
}
## [1] "Falso"
Pongámonos en situación ¿qué estructura condicional es más adecuada utilizar en cada situación?
- Si quiero saber si una persona debería estar jubilada de acuerdo a su edad.
- Si tengo una válvula para riego y quiero saber si la abro o la cierro de acuerdo a la humedad del suelo.
- Estoy en un aula de clases, pero si hay más de 20 estudiantes debo cambiarme a un aula más grande.
Bucles o cíclos
Como indica su nombre, estas estructuras de control, permiten general ciclos y por lo tanto realizar operaciones repetitivas dentro de un código, digamos que deseo hacer una sumatoria, lo que implica ir sumando cada valor encontrado con el número anterior, para esto puedo utilizar un ciclo que haga justamente eso, tomar un valor acumulado sumarle un nuevo valor y realizar esa misma operación hasta el último valor de nuestra secuencia de datos.
Para esto tenemos distintos tipos de funciones que fungirán como estructuras de control, por un lado tenemos el ciclo for
el cual nos permite realizar una operación con cada elemento dentro de un conjunto de elementos, mientras que la función while
permite realizar una acción mientras se cumpla una cierta condición.
Ciclo for
Para la construcción del ciclo for
es posible utilizar la siguiente sintaxis
# En caso que haya más de una operación por ciclo
for(elemento in objeto) {
operacion_con_elemento
}
# En caso que haya una única operación por ciclo
for(elemento in objeto) {operacion_con_elemento}
for(elemento in objeto) operacion_con_elemento
Los dos bucles siguientes son equivalentes, sólo cambia el nombre del elemento que tomará el valor. Cabe destacar que tradicionalmente se usa la letra i
para denotar al elemento, ya que viene de la palabra iteration.
objeto <- 1:10
for(elemento in objeto) {
operacion_con_elemento
}
for(i in objeto) {
operacion_con_elemento
}
Pongámonos en situación ¿cómo resolveríamos el siguiente planteamiento?
- Se desea obtener e imprimir en pantalla el cuadrado de cada uno de los elementos en un vector numérico del 1 al 6, que representa las caras de un dado.
- Se desea calcular el promedio del vector
edades
.
- Necesitamos saber cuanto es el total de unidades vendidas del vector
vendidos
.
- Necesitamos saber la mayor estatura entre los estudiantes presentes en el vector
estatura
.
vendidos = c(120, 100, 132, 112, 95, 164, 172, 183, 155, 176, 110, 115)
edades = c(20.8, 20.6, 21.0, 20.9, 19.9, 20.2, 19.8, 19.6, 20.9, 21.1)
estatura = c(1.83, 1.71, 1.79, 1.64, 1.74, 1.81, 1.62, 1.84, 1.68, 1.81, 1.82, 1.74, 1.84,
1.61, 1.84)
Es importante mencionar que los ciclos for
a pesar de su utilidad son muy ineficientes y no se recomienda utilizarlos para programación de alto nivel, en ese caso es preferente usar la familia de funciones apply()
Ciclo while
Para la construcción del ciclo while
es posible utilizar la siguiente sintaxis
# En caso que haya más de una operación por ciclo
while(condicion) {
operaciones
}
# En caso que haya una única operación por ciclo
while(condicion) {operaciono}
while(condicion) operaciono
Pongámonos en situación ¿cómo resolveríamos el siguiente planteamiento?
- Se desea obtener e imprimir en pantalla el cuadrado de cada uno de los elementos en un vector numérico del 1 al 6, que representa las caras de un dado.
- Se desea calcular el promedio del vector
edades
.
- Necesitamos saber cuanto es el total de unidades vendidas del vector
vendidos
.
- Necesitamos saber la mayor estatura entre los estudiantes presentes en el vector
estatura
.
vendidos = c(120, 100, 132, 112, 95, 164, 172, 183, 155, 176, 110, 115)
edades = c(20.8, 20.6, 21.0, 20.9, 19.9, 20.2, 19.8, 19.6, 20.9, 21.1)
estatura = c(1.83, 1.71, 1.79, 1.64, 1.74, 1.81, 1.62, 1.84, 1.68, 1.81, 1.82, 1.74, 1.84,
1.61, 1.84)
Un uso común de while es que realice operaciones que queremos detener cuando se cumple una condición, pero desconocemos cuándo ocurrirá esto
Supongamos que, por alguna razón queremos sumar calificaciones, del 1 al 10 al azar, hasta llegar a un número que mayor o igual a 50. Además nos interesa saber cuántas calificaciones sumaron y cuál fue el resultado al momento de cumplir la condición.