TRUE + TRUE
[1] 2
TRUE + FALSE
[1] 1
El desarrollo de un programa involucra la necesidad de efectuar operaciones de distinto tipo entre los valores guardados en los objetos: suma, resta, concatenación de caracteres, comparaciones, etc. Los elementos que describen el tipo de operación a realizar entre dos objetos se denominan operadores.
En este capítulo exploraremos los operadores en R, fundamentales para realizar cálculos, comparaciones y evaluaciones lógicas en nuestros programas. Comenzaremos con los operadores aritméticos, que permiten realizar operaciones matemáticas básicas. Luego, abordaremos los operadores relacionales, esenciales para comparar valores, y los operadores lógicos, que nos ayudan a evaluar condiciones. También estudiaremos el orden de precedencia en R, clave para interpretar correctamente las expresiones, y la evaluación en cortocircuito, una optimización importante en decisiones condicionales.
Los operadores aritméticos permiten realizar operaciones matemáticas con vectores atómicos que almacenen valores numéricos, como double o integer (Tabla 4.1).
Operación | Operador | Ejemplo de uso | Resultado con x <- 7 e y <- 3 |
---|---|---|---|
Suma | + |
x + y |
10 |
Resta | - |
x - y |
4 |
Multiplicación | * |
x * y |
21 |
División | / |
x / y |
2.33 |
Potenciación | ^ |
x ^ y |
343 |
División entera | %/% |
x %/% y |
2 |
División módular (resto de la división) | %% |
x %% y |
1 |
Los operadores aritméticos actúan con un orden de prioridad establecido, también conocido como orden de evaluación u orden de precedencia, tal como estamos acostumbrados en matemática. Las expresiones entre paréntesis se evalúan primero. Si hay paréntesis anidados se evalúan desde adentro hacia afuera. Dentro de una misma expresión, los operadores se evalúan en este orden:
^
)%/%
, %%
)*
, /
)+
, -
)Si la expresión presenta operadores con igual nivel de prioridad, se evalúan de izquierda a derecha.
Operación | Resultado |
---|---|
4 + 2 * 4 |
12 |
23 * 2 / 5 |
9.2 |
3 + 5 * (10 - (2 + 4)) |
23 |
2.1 * 1.5 + 12.3 |
15.45 |
2.1 * (1.5 + 12.3) |
28.98 |
1 %% 4 |
1 |
8 * (7 - 6 + 5) %% (1 + 8 / 2) - 1 |
7 |
Los operadores aritméticos también se pueden aplicar con valores lógicos. En este caso, TRUE
es considerado como 1
y FALSE
, como 0
1:
TRUE + TRUE
[1] 2
TRUE + FALSE
[1] 1
Los operadores relacionales sirven para comparar dos valores de cualquier tipo y dan como resultado un valor lógico, TRUE
o FALSE
.
Comparación | Operador | Ejemplo de uso | Resultado con x <- 7 e y <- 3 |
---|---|---|---|
Mayor que | > |
x > y |
TRUE |
Menor que | < |
x < y |
FALSE |
Mayor o igual que | >= |
x >= y |
TRUE |
Menor o igual que | <= |
x <= y |
FALSE |
Igual a | == |
x == y |
FALSE |
Distinto a | != |
x != y |
TRUE |
Ejemplos del uso de operadores relacionales:
<- 3
a <- 4
b <- 2
d <- 10
e <- 15
f
* b) == (d + e) (a
[1] TRUE
* b) != (f - b) (a
[1] TRUE
Es interesante notar que primero se evalúan las operaciones a cada lado de los operadores relacionales y luego se hace la comparación. Es decir, los operadores aritméticos preceden a los relacionales en el orden de prioridad. Por eso, en los ejemplos anteriores en realidad no son necesarios los paréntesis y podríamos omitirlos:
* b == d + e a
[1] TRUE
* b != f - b a
[1] TRUE
Para pensar… ¿en base a qué criterio se determina si un valor de tipo character es mayor qué otro? Mirá este ejemplo:
<- "Hola"
texto1 <- "Chau"
texto2 <- "Adiós"
texto3
> texto2 texto1
[1] TRUE
> texto2 texto3
[1] FALSE
¿Qué valor lógico devuelve esta operación?
== "hola" texto1
Mientras que los operadores relacionales comparan cualquier tipo de valores, los operadores lógicos sólo toman operandos de tipo logical y producen también un resultado lógico.
Operación | Operador | Ejemplo de uso | Resultado con x <- TRUE e y <- FALSE |
---|---|---|---|
Conjunción | && |
x && y |
FALSE |
Disyunción | || |
x || y |
TRUE |
Negación | ! |
!x |
FALSE |
Veamos uno por uno:
TRUE
sólo si son verdaderas ambas expresiones que vincula. Ejemplo: (3 > 2) && (3 > 5)
resulta en TRUE && FALSE
y esto es FALSE
.TRUE
si al menos una de las dos expresiones que vincula es verdadera. Ejemplo: (3 > 2) || (3 > 5)
resulta en TRUE || FALSE
y esto es TRUE
.!(3 > 2)
resulta en !TRUE
y esto es FALSE
.La tabla de verdad o tabla de valores de verdad se utiliza para mostrar todos los resultados posibles de estas operaciones lógicas:
x |
y |
!x |
x && y |
x || y |
---|---|---|---|---|
TRUE |
TRUE |
FALSE |
TRUE |
TRUE |
TRUE |
FALSE |
FALSE |
FALSE |
TRUE |
FALSE |
TRUE |
TRUE |
FALSE |
TRUE |
FALSE |
FALSE |
TRUE |
FALSE |
FALSE |
Con estos operadores es posible construir evaluaciones lógicas algo más elaboradas como los siguientes ejemplos:
Determinar si el valor numérica guardado en la variable x
está entre 5 y 7. Tal vez tu intuición te sugiere que la expresión lógica a evaluar en este caso debe ser 5 < valor < 7
, pero esto genera un error en R. Para saber si valor
está entre 5 y 7, se tiene que evaluar por separado que valor
sea mayor que 5 y también menor que 7, y ambas condiciones deben ser verdaderas.
<- 6.4
valor > 5) && (valor < 7) (valor
[1] TRUE
<- 2.1
valor > 5) && (valor < 7) (valor
[1] FALSE
Establecer si el valor de tipo carácter almacenado en la variable nacionalidad
sea igual a una de dos opciones.
<- "Argentino"
nacionalidad == "Uruguayo") || (nacionalidad == "Chileno") (nacionalidad
[1] FALSE
Verificar que el valor guardado en nacionalidad
no coincida con “Argentino”.
<- "Uruguayo"
nacionalidad !(nacionalidad == "Argentino")
[1] TRUE
Chequear que el valor numérico guardado en x
no sea igual a 2 ni a 3.
Opción correcta 1: (x != 2) && (x != 3)
# Da verdadero porque x no es ni 2 ni 3
<- 10
x != 2) && (x != 3) (x
[1] TRUE
# Da falso porque x es igual a 3
<- 3
x != 2) && (x != 3) (x
[1] FALSE
Opción correcta 2: !(x == 2 || x == 3)
# Da verdadero porque x no es ni 2 ni 3
<- 10
x !(x == 2 || x == 3)
[1] TRUE
# Da falso porque x es igual a 3
<- 3
x !(x == 2 || x == 3)
[1] FALSE
Opción incorrecta: (x != 2) || (x != 3)
# Como la primera parte es verdadera (porque x es igual a 3), la
# conjunción es verdadera, cuando quisiéramos que en este caso el
# resultado sea FALSO
<- 3
x != 2) || (x != 3) (x
[1] TRUE
Es importante notar que todos los paréntesis usados en el código de R de los ejemplos 1, 2 y 4 son innecesarios, puesto que los operadores relacionales preceden a los lógicos en el orden de prioridad. Sin embargo, a veces preferimos usar paréntesis para que la lectura sea más sencilla. Retomando el ejemplo 1, notemos que ambas expresiones son equivalentes:
<- 2.1
valor > 5) && (valor < 7) (valor
[1] FALSE
> 5 && valor < 7 valor
[1] FALSE
¿Cuál es el resultado de las siguientes operaciones?
<- 2
x <- -2 y
x > 0 && y < 0
: x > 0 || y < 0
: !(x > 0 && y < 0)
: Tanto para la conjunción como para la disyunción, R provee dos operadores diferentes, los ya mencionados &&
y ||
y otros que no repiten el símbolo, &
y |
. La diferencia entre las dos versiones se hace notar cuando operamos con vectores atómicos que almacenen más de un valor, por lo cual por ahora podemos ignorarla. Usaremos la versión de símbolos dobles.
Resumiendo la información anterior, a continuación se presenta el orden de precedencia completo de los operadores en R que utilizaremos2:
Orden | Operaciones | Operadores |
---|---|---|
1 | Potenciación | ^ |
2 | Signo de un número (ej: -3) | + , - |
3 | División entera y resto | %/% , %% |
4 | Multiplicación y división | * . / |
5 | Suma y resta | + . - |
6 | Operadores de comparación | < , > , <= , >= , == , != |
7 | Negación | ! |
8 | Conjunción | && , & |
9 | Disyunción | || , | |
10 | Asignación | <- |
Dentro de una misma expresión, operadores con igual prioridad se evalúan de izquierda a derecha.
Para evaluar la operación de conjunción x && y
, en R se comienza por evaluar la expresión del primer operando x
y si su resultado es FALSE
ya no se evalúa la expresión y
del segundo operando. Esto es porque si x
es FALSE
, el resultado de x && y
ya no depende de y
, será siempre FALSE
. Por este motivo se dice que el operador &&
se evalúa en cortocircuito. La evaluación en cortocircuito evita realizar operaciones innecesarias3.
Por ejemplo:
<- 1
f <- 2
g
# La primera parte da TRUE, se continúa con la segunda, pero da error porque no
# existe un objeto llamado h
> f) && (f > h) (g
Error: object 'h' not found
# La primera parte da FALSE, entonces toda la operación será FALSE, no se
# continúa con la segunda parte, con lo cual no se intenta usar el objeto
# inexistente h y no hay error
< f) && (f > h) (g
[1] FALSE
La operación de disyunción también se evalúa en cortocircuito, es decir, si se encuentra que uno de los operandos es TRUE
, no hace falta evaluar los restantes, puesto que el resultado general será TRUE
:
# Es TRUE porque la primera parte es TRUE, sin evaluar la segunda, que daría
# error
> f) || (f > h) (g
[1] TRUE
# Como la primera parte es FALSE, debe evaluar la segunda, no encuentra a h y da
# error
> g) || (f > h) (f
Error: object 'h' not found