library(learnr)
knitr::opts_chunk$set(echo = FALSE)

Introducción

knitr::include_graphics("images/operadores_logicos_relacionales.jpg")

El presente tutorial pretende ser un vehículo de aprendizaje interactivo para los novatos en el lenguaje R.

Ha sido desarrollado a través del paquete learnr que permite utilizar documentos RMarkdown para generar tutoriales interactivos.

Como se explica en la página de learnr, los tutoriales consisten en contenido (texto, figuras, ilustraciones, ecuaciones, vídeos, etc.) junto con componentes interactivos, como preguntas con múltiples opciones y fragmentos de código de R que los usuarios pueden editar y ejecutar directamente, para verificar y reforzar la comprensión.

Estos tutoriales conservan automáticamente el avance que un usuario realizó, por lo que si un estudiante trabaja en algunos ejercicios o preguntas y vuelve al tutorial más tarde, puede retomarlo exactamente donde lo dejó.

Este tutorial ha sido publicado como el paquete fundamentosr.

Objetivos de aprendizaje

Los objetivos de aprendizaje del presente tutorial son los siguientes:

Operadores relacionales

Los operadores relacionales son símbolos mediante los cuales podemos realizar operaciones comparativas cuyos resultados son objetos de la clase logical, que pueden adoptar los valores TRUE o FALSE, según se cumpla o no la relación propuesta en la operación. Las operaciones relacionales son las siguientes:

En la siguiente tabla se muestran ejemplos de uso de los operadores relacionales con los valores literales $7$ y $3$:

Operación | Operador | Ejemplo | Resultado |:--:|:--:|:--:|:--:| Igual que | == | 7 == 3 | FALSE
No es igual que | != | 7 != 3 | TRUE Menor que | < | 7 < 3 | FALSE Menor o igual que| <= | 7 <= 3 | FALSE Mayor que | > | 7 > 3 | TRUE Mayor o igual que| >= | 7 >= 3 | TRUE

Es posible comparar cualquier tipo de dato sin que resulte en un error. Sin embargo, al usar los operadores relacionales con cadenas de caracteres (character), estos tienen un comportamiento especial, permitiendo realizar comparaciones por orden alfabético. Veamos a continuación un ejemplo simple.

"Juan" < "Luis"
"Luis" < "Pablo"
"Pablo" > "Juan"
"Juan" == "Juan"
"Juan" != "JUAN"

Con las tres primeras comparaciones podríamos determinar que por orden alfabético "Juan" es anterior a "Luis" y "Luis" es anterior a "Pablo". La cuarta comparación nos presenta dos cadenas idénticas. La última comparación muestra que, obviamente, no es lo mismo mayúscula que minúscula. Cambia los operadores relacionales del código anterior para que los resultados de todas las operaciones sean FALSE.

Operadores lógicos

Los operadores lógicos son usados para operaciones de álgebra booleana, es decir, para describir relaciones lógicas, expresadas como verdadero (TRUE) o falso (FALSE). Pueden ser usados con datos de tipo numérico (numeric) y lógico (logical). Al igual que con los operadores relacionales, los operadores lógicos siempre devuelven TRUE o FALSE. En R están disponibles los siguientes operadores lógicos:

En la siguiente tabla se muestran ejemplos de uso de los operadores relacionales con los valores literales TRUE y FALSE:

Operación | Operador | Ejemplo | Resultado |:--:|:--:|:--:|:--:| Negación (NOT) | ! | !TRUE | FALSE
- | - | !FALSE | TRUE Afirmación (IS) | isTRUE | isTRUE(TRUE) | TRUE
- | - | isTRUE(FALSE) | FALSE Conjunción (AND) | & | TRUE & FALSE | FALSE - | && | TRUE && FALSE | FALSE Disyunción (OR) | | | TRUE | FALSE | TRUE - | || | TRUE || FALSE | TRUE Exclusividad (XOR) | xor | xor(TRUE,FALSE) | TRUE

Los operadores lógicos siguen las siguientes reglas:

Vamos a comprobar el uso de los distintos operadores lógicos mediante el uso de expresiones relacionales de comparación de literales numéricos.

#isTRUE(7>5) #Afirmación
#!(7>5) #Negación
#(7>5)&&(10>=10) #AND (Y lógico)
#(5<7)&(10==10)  
#(7>5)||(10>10) #OR (O lógico)
#(7<5)|(10>10)
#xor(7>5,10>10) #XOR (O lógico)
#xor(7<5,10>10)

Puedes comprobar el efecto de cada operador lógico eliminando el comentario al principio de la línea correspondiente y ejecutando el código.

Orden de evaluación

Como ya sabemos, en R las operaciones tienen un orden de evaluación definido. Cuanto aparecen varias operaciones en una misma expresión, en realidad, algunas de ellas son realizadas antes que otras y el resultado de ellas dependerá de este orden.

El orden de operaciones incluye a las aritméticas, relacionales, lógicas y de asignación. A continuación presentamos una tabla con el orden de precedencia de los diferentes operadores:

# | Operaciones | Operadores :--:|:--:|:--:| 1º | Potenciación | ^ 2º | Unarias | +,- 3º | Módulo | %% 4º | Multiplicación| * - | División | / 5º | Suma | + - | Resta | - 6º | Operadores relacionales | - - | Igual, no es igual | ==,!= - | Menor, menor o igual | <, <= - | Mayor, mayor o igual | >, >= 6º | Negación (NOT) | ! - | Afirmación (IS) | isTRUE 7º | Conjunción (AND) | &, && 8º | Disyunción (OR) | |, || - | Exclusividad (XOR) | xor 9º | Asignación | <-

En caso de igual orden de precedencia entra en juego la asociatividad, llevándose a cabo una evaluación de izquierda a derecha en todos los casos excepto con la potenciación, donde la evaluación se lleva a cabo de derecha a izquierda.

Si deseamos que una operación se lleve a cabo antes que otra, con independencia de este orden de evaluación, se deben usar paréntesis. Podemos también tener paréntesis anidados.

En el siguiente ejemplo, podemos comprobar la precedencia de operadores en las expresiones. Una de las conclusiones que obtendrás en el proceso de determinar los operadores que se evalúan con anterioridad a otros es que siempre es mejor utilizar paréntesis. Ayuda a la legibilidad y evita ambigüedades.

7+5>7-5 && 8*2>8/2
3^2>2^3 || 8%/%5 > 8%%5

Coloca paréntesis en la expresiones anteriores y comprueba que el resultado es el mismo:

Coerción

La coerción es una característica de los lenguajes de programación que permite, implícita o explícitamente, convertir un objeto de un tipo de datos en otro, sin tener en cuenta la comprobación de tipos. En R, los datos pueden ser coercionados, es decir, forzados, para transformarlos de un tipo a otro.

Coerción implícita

La coerción es muy importante. Cuando pedimos a R ejecutar una operación, intentará coercionar de manera implícita, sin avisarnos, los datos de su tipo original al tipo correcto que permita realizarla. Habrá ocasiones en las que R tenga éxito y la operación ocurra sin problemas, y otras en las que falle y obtengamos un error. Echa un vistazo al siguiente código.

#  1 + TRUE
# (1 + TRUE) > (2 + FALSE)
# ! (7 / 2.5)
# 8 * "Hola"

Puedes eliminar el comentario al principio de cada línea individual y comprobar qué ocurre con la ejecución.

El caso correspondiente a la última línea del ejemplo ocurre porque no todos los tipos de datos pueden ser transformados a los demás. Para la coerción se sigue una regla general: la coerción de tipos se realiza de los tipos de datos más restrictivos a los más flexibles.

Las coerciones implícitas siguen el orden logical -> integer -> numeric -> character.

Las coerciones no pueden ocurrir en orden inverso. Podemos coercionar un dato de tipo lógico (logical) a uno entero (integer), pero no uno de cadena de caracteres (character) a numérico (numeric).

Los datos de tipo lógico son los más restrictivos, pues sólo admiten dos valores (TRUE y FALSE). Los datos de tipo cadena de caracteres son los más flexibles, pues admiten cualquier cantidad y combinación de caracteres.

Veamos a continuación dos ejemplos representativos para poder entender mejor la coerción implícita:

En el primer ejemplo, conocida la altura de cuatro personas, deseamos conocer cuántas de ellas superan los dos metros.

altura_persona1 <- 177
altura_persona2 <- 199
altura_persona3 <- 201
altura_persona4 <- 215
personas_mayores_2m <- (altura_persona1>200)+(altura_persona2>200)+(altura_persona3>200)+(altura_persona4>200)
personas_mayores_2m

En este ejemplo, la coerción de lógico (logic) a entero (integer) permite sumar el número de personas que cumplen una determinada condición (altura superior a dos metros). Debes tener en cuenta que TRUE es coercionado a 1 y FALSE es coercionado a 0.

En el segundo ejemplo, dados cuatro nombres de usuario, deseamos conocer los que se colocarían, por orden alfabético, antes que uno de ellos (usuario2).

usuario1 <- 177
usuario2 <- "fenix199"
usuario3 <- 201
usuario4 <- "XxpipoxX"
anteriores_usuario2 <- (usuario1<usuario2) + (usuario3<usuario2) + (usuario4<usuario2) 
anteriores_usuario2

En este ejemplo, la coerción de entero (integer) a cadena de caracteres (character) permite comparar cadenas de caracteres, en este caso para comprobar si un nombre de usuario sería anterior, en orden alfabético, al nombre de usuario2. Debes tener en cuenta que, por ejemplo, el número 177 es coercionado a la cadena de caracteres que incluye cada uno de sus dígitos como caracter "177".

Coerción explícita

Los objetos pueden ser convertidos en otro tipo de datos de foma explícita mediante el uso de:

Cuando estas funciones llevan a cabo la coerción, nos devuelven datos del tipo pedido. Si hay problemas, aparece la advertencia correspondiente y obtenemos como resultado NA (usado en R, entre otras posibilidades, para mostrar que una operación realizada no tuvo éxito en su ejecución).

Veamos a continuación algunos ejemplos de coerción explícita con éxito:

#Coerción explícita de lógico ``logical``
as.integer(TRUE)
as.numeric(TRUE)
as.character(TRUE)
#Coerción explícita de entero ``integer``
as.numeric(800)
as.character(800)
#Coerción explícita de numérico ``numeric``
as.character(755.323)

Puedes comprobar el efecto de la coerción explícita mediante la ejecución del código.

A continuación mostraremos diversos ejemplos de coerción explícita sin éxito (con cadenas de caracteres):

#Coerción explícita de cadena de caracteres ``character``
as.integer("Hola")
as.numeric("Hola")
as.logical("Hola")

Como ves, aparece la advertencia correspondiente y obtenemos como resultado NA en todas ellas.

Para que haya éxito en la coerción explícita, el orden no debe ser necesariamente: logical -> integer -> numeric -> character. Los ejemplos mostrados a continuación lo demuestran:

#Coerción explícita a lógico ``logical``
as.logical(100)
as.logical(800.533)
as.logical(0)
as.integer(800.533)

En las dos primeras conversiones, podemos comprobar que si el número es distinto de 0 (integer o numeric) será coercionado a TRUE. En la tercera conversión, vemos que si el número es 0 será coercionado a FALSE. Finalmente, en la última conversión vemos cómo podemos coercionar un número flotante a entero a costa de perder la parte decimal.

Ejercicio películas

Vamos a realizar un ejercicio acerca del uso de operadores relacionales y lógicos:

"La siguiente tabla muestra cuatro de las películas de mayor recaudación en salas de cine (millones de dólares) a nivel mundial a lo largo de la historia (hasta 2021).

Película | Recaudación | Año de estreno :--:|:--:|:--:| Avengers: Endgame | 2797.800 | 2019 Avatar | 2787.965 | 2009 Titanic | 2187.463 | 1997 Jurassic World | 1671.713 | 2015

Se desea saber:

Obviamente, es muy sencillo responder a todas las preguntas planteadas mediante la observación de la tabla. Sin embargo, pensemos en su resolución mediante código en R, debido a que el razonamiento nos servirá de punto de partida para cuando tengamos un número de películas mucho mayor y no abarcable visualmente.

Inicialización de variables

Para obtener la solución a las diferentes preguntas del ejercicio comenzaremos definiendo las variables del mismo que tienen un valor inicial.

#Inicializamos variables
pelicula1<-"Avengers: Endgame"
pelicula2<-"Avatar"
pelicula3<-"Titanic"
pelicula4<-"Jurassic World"
recaudacion1<-2797.800
recaudacion2<-2787.965
recaudacion3<-2187.463
recaudacion4<-1671.713
estreno1<-2019
estreno2<-2009
estreno3<-1997
estreno4<-2015

Hemos proporcionado a cada variable un nombre ilustrativo del valor que contiene y con el orden en que aparece en la tabla.

Recaudación superior

Para responder a la pregunta acerca de cuántas películas tienen una recaudación superior a los 2000 millones de dólares, debemos comparar la recaudación de cada película con la cantidad proporcionada. Esta comparación debe ser verdadera en caso de que se cumpla la condición (recaudación superior).

#Inicializamos variables
recaudacion1<-2797.800
recaudacion2<-2787.965
recaudacion3<-2187.463
recaudacion4<-1671.713
#Inicialización variable recaudación de referencia
ref_recaudacion<-2000
#Cálculo número películas con recaudación superior
recaudacion_superior=(recaudacion1>ref_recaudacion)+(recaudacion2>ref_recaudacion)+(recaudacion3>ref_recaudacion)+(recaudacion4>ref_recaudacion)
recaudacion_superior

En la solución puedes comprobar cómo se hace uso de la coerción de logical a integer en cada comparación para luego calcular el número de películas con recaudación superior a la indicada de referencia.

Estreno anterior

Para responder a la pregunta acerca de cuántas películas han sido estrenadas antes de 2010 el proceso a seguir es similar a la resolución de la pregunta anterior. La diferencia se encuentra en este caso en que la comparación se realiza con los años de estreno y teniendo de cantidad de referencia en la comparación al año 2010.

#Inicializamos variables
estreno1<-2019
estreno2<-2009
estreno3<-1997
estreno4<-2015
#Inicialización estreno de referencia
ref_estreno<-2010
#Cálculo número películas con recaudación superior
estreno_antes=(estreno1<ref_estreno)+(estreno2<ref_estreno)+(estreno3<ref_estreno)+(estreno4<ref_estreno)
estreno_antes

Se hace uso de la coerción de logical a integer en cada comparación para luego calcular el número de películas con año de estreno anterior (operador relacional <) al indicado de referencia.

Estreno fuera del periodo

Para responder a la pregunta acerca de cuántas películas han sido estrenadas fuera del periodo 2005-2015 se puede llevar a cabo de dos formas distintas (comprobándose en todo caso dos condiciones para cada año de estreno):

Veamos el código correspondiente a la primera solución (disyunción): cuando se cumpla una condición para el año de estreno es suficiente para saber que está fuera del periodo (2005-2015).

#Inicializamos variables
estreno1<-2019
estreno2<-2009
estreno3<-1997
estreno4<-2015
#Inicialización periodo de referencia
inicio_periodo<-2005
fin_periodo<-2015
#Cálculo número películas con recaudación superior
estreno_fuera=
  ((estreno1<inicio_periodo)||(estreno1>fin_periodo)) +
  ((estreno2<inicio_periodo)||(estreno2>fin_periodo)) +
  ((estreno3<inicio_periodo)||(estreno3>fin_periodo)) +
  ((estreno4<inicio_periodo)||(estreno4>fin_periodo)) 
estreno_fuera

Veamos el código correspondiente a la segunda solución (conjunción y negación): cuando se cumplan las dos condiciones para el año de estreno está dentro del periodo por lo que no se sumaría para el cálculo (negación). Ten en cuenta la importancia de los paréntesis en la ejecución y el orden de evaluación.

#Inicializamos variables
estreno1<-2019
estreno2<-2009
estreno3<-1997
estreno4<-2015
#Inicialización periodo de referencia
inicio_periodo<-2005
fin_periodo<-2015
#Cálculo número películas con recaudación superior
estreno_fuera=
  (!((estreno1>=inicio_periodo)&&(estreno1<=fin_periodo))) +
  (!((estreno2>=inicio_periodo)&&(estreno2<=fin_periodo))) +
  (!((estreno3>=inicio_periodo)&&(estreno3<=fin_periodo))) +
  (!((estreno4>=inicio_periodo)&&(estreno4<=fin_periodo))) 
estreno_fuera

Titulos estrenados después con recaudación superior

Para responder a la cuestión acerca de cuántos títulos estrenados a partir de 2015 (incluido) han tenido una recaudación superior a 2500 millones de dólares se debe llevar a cabo una doble comparación para cada película (año de estreno y recaudación).

#Inicializamos variables
recaudacion1<-2797.800
recaudacion2<-2787.965
recaudacion3<-2187.463
recaudacion4<-1671.713
estreno1<-2019
estreno2<-2009
estreno3<-1997
estreno4<-2015
#Inicialización variables recaudación y estreno de referencia
ref_recaudacion<-2500
ref_estreno<-2015
#Cálculo número películas que cumplen dos condiciones 
num_peliculas_dos_condiciones=
  ((recaudacion1>ref_recaudacion)&&(estreno1>=ref_estreno))+
  ((recaudacion2>ref_recaudacion)&&(estreno2>=ref_estreno))+
  ((recaudacion3>ref_recaudacion)&&(estreno3>=ref_estreno))+
  ((recaudacion4>ref_recaudacion)&&(estreno4>=ref_estreno))
num_peliculas_dos_condiciones

El papel de los paréntesis es fundamental en la evaluación.

Conclusión

En la resolución de todas las preguntas del ejercicio hemos podido comprobar la redundancia (repetición) de las comparaciones para cada variable. Aparece aquí la necesidad de un nuevo tipo de datos que evite esta repetición y permita generalizar la operación a un número indeterminado de variables. Se trata del tipo de datos vector que abordaremos posteriormente.

Felicidades, has completado el tutorial de Operadores Relacionales y Lógicos. Puedes continuar con el siguiente tutorial: Funciones predefinidas.



eyeguas/fundamentosr documentation built on March 31, 2021, 5:20 p.m.