25 nov 2019

Operadores lógicos y relacionales en R


En la siguiente entrada se explica, a partir de algunos ejemplos, cómo utilizar los operadores lógicos y relacionales en R. Estos ejemplos se desarrollan usando una pequeña base de datos simulada:

nombre <- c("Miguel", "Ara", "Marirza", "Juan", "Maira", "Dro")
mujer <- c(0,1,1,0,1,0)
edad <- c(20,17,25,35,48,12)

data <- data.frame(nombre, mujer, edad)
head(data)

nombre mujer edad
1  Miguel     0   20
2     Ara     1   17
3 Marirza     1   25
4    Juan     0   35
5   Maira     1   48
6     Dro     0   12

1.1. Operadores relacionales

Los operadores relacionales permiten establecer relación entre variables o vectores, son los clásicos operadores de:
 
 > mayor que
>= mayor igual
 < menor
<= menor igual
== igual
!= diferente


Cuando aplicamos estos operadores relacionales (o de comparación) sobre un vector se obtienen vectores lógicos con el valor TRUE (==1) en caso de cumplirse comparación (de ser cierta) y 0 en los demás casos (FALSE==0), por ejemplo:
 
5>2
[1] TRUE

5<=2
[1] FALSE

Si quisiéramos que el nuevo vector asuma los valores 0 o 1 para presentar verdadero o falso, usaríamos la opción as.numeric:
 
as.numeric(5>2)
[1] 1

Cuando se aplica este operador sobre un vector este actúa de forma vectorizada, es decir, realiza la comparación para cada una de las posiciones del vector, por lo que, arroja un nuevo vector de la misma dimensión, indicando Falso o Verdadero para cada una de las posiciones del vector, según se cumpla o no la condición indicada. Por ejemplo, suponga necesitamos agregar una nueva variable a la base de datos simulada, donde se identifiquen a los menores de edad dentro de una base de datos:

data$menores <- edad<18  #Agrega una variable llamada menores a la data
head(data)
   nombre mujer edad menores
1  Miguel     0   20   FALSE
2     Ara     1   17    TRUE
3 Marirza     1   25   FALSE
4    Juan     0   35   FALSE
5   Maira     1   48   FALSE
6     Dro     0   12    TRUE

Sobre estos vectores podemos aplicar el operador de negación (!, not) que sería comparable con identificar el complemento de un conjunto. Por ejemplo, anteriormente obtuvimos los menores de edad, para obtener los mayores podemos utilizar el operador de negación sobre el vector (variable) menores creada anteriormente:

data$meyores <- !edad<18  # edad>=18
data
   nombre mujer edad menores meyores
1  Miguel     0   20   FALSE    TRUE
2     Ara     1   17    TRUE   FALSE
3 Marirza     1   25   FALSE    TRUE
4    Juan     0   35   FALSE    TRUE
5   Maira     1   48   FALSE    TRUE
6     Dro     0   12    TRUE   FALSE

En el caso de objetos no numéricos (caracteres), la expresión o el valor buscado se coloca entre comillas. En el siguiente ejemplo identificamos todas las observaciones que tienen por nombre Miguel:
 
data$Miguel <- nombre=="Miguel" 
head(data)
nombre mujer edad menores meyores Miguel
1  Miguel     0   20   FALSE    TRUE   TRUE
2     Ara     1   17    TRUE   FALSE  FALSE
3 Marirza     1   25   FALSE    TRUE  FALSE
4    Juan     0   35   FALSE    TRUE  FALSE
5   Maira     1   48   FALSE    TRUE  FALSE
6     Dro     0   12    TRUE   FALSE  FALSE

1.2. Operadores lógicos

1.2.1. Or

Los operadores lógicos nos permiten utilizar 2 o más operadores relacionales. Por ejemplo, la unión de eventos la asociamos al operador o (|). Este operador requiere se cumpla al menos una de las condiciones impuestas para asumir un valor verdadero. Por ejemplo, suponga deseamos identificar las personas que sean menores de edad o mujeres (o indica que solo necesitamos se cumpla una de las dos condiciones). Es decir, esta nueva variable colocará el valor de verdadero a todas las observaciones que cumplan al menos una de las dos condiciones:

data$mujeresOmenor <- edad<18 | mujer==1
data
   nombre mujer edad menores meyores Miguel mujeresOmenor
1  Miguel     0   20   FALSE    TRUE   TRUE         FALSE
2     Ara     1   17    TRUE   FALSE  FALSE          TRUE
3 Marirza     1   25   FALSE    TRUE  FALSE          TRUE
4    Juan     0   35   FALSE    TRUE  FALSE         FALSE
5   Maira     1   48   FALSE    TRUE  FALSE          TRUE
6     Dro     0   12    TRUE   FALSE  FALSE          TRUE

En caso de usar dos veces el operador o (||), nos estamos preguntando si todas las observaciones de nuestra data cumplen al menor una de las condiciones indicadas. En tal sentido, el ejemplo anterior arroja un FALSE, porque no todas las observaciones cumplen al menos una de las condiciones indicadas, preguntándonos si todas las observaciones son o mujeres o menores de edad.

edad<18 || mujer==1
[1] FALSE

Una alternativa al operador anterior es la función all:

all(edad<18 | mujer==1)
[1] FALSE

Por el contrario, el operador any se pregunta si al menos 1 cumple esa condición:

any(edad<18 | mujer==1)
[1] TRUE

1.2.1. AND

El operador (y) corresponde con la operación de intersección en álgebra de conjuntos. Este operador, para colocar un TRUE, requiere que se cumplan todas las restricciones indicadas. Respecto al ejemplo anterior, ahora requerimos que la observación sea mujer y menor de edad al mismo tiempo, por lo que usamos el operador y, que en R viene dado por "&":

data$mujeresYmenor <- edad<18 & mujer==1
data
   nombre mujer edad menores meyores Miguel mujeresOmenor mujeresYmenor
1  Miguel     0   20   FALSE    TRUE   TRUE         FALSE         FALSE
2     Ara     1   17    TRUE   FALSE  FALSE          TRUE          TRUE
3 Marirza     1   25   FALSE    TRUE  FALSE          TRUE         FALSE
4    Juan     0   35   FALSE    TRUE  FALSE         FALSE         FALSE
5   Maira     1   48   FALSE    TRUE  FALSE          TRUE         FALSE
6     Dro     0   12    TRUE   FALSE  FALSE          TRUE         FALSE

Tal como en el operador O, usar dos veces este operador realiza la pregunta de si todas las observaciones en la base de datos presentan o cumple con ambas condiciones. Es decir, pregunta si todas las mujeres son menores de edad:

edad<18 && mujer==1
[1] FALSE

1.2.3. Xor

El comando xor devuelve TRUE en los casos donde solo una de las observaciones de un vector creado con dos condiciones, contienen un true. Para el siguiente ejemplo, note que la segunda observación ahora es FALSE, dado que este operado equivale a or (|) pero haciendo falso aquellos casos donde la opción & también resultaría verdadera.

data$hombremayor <- xor(edad<18, mujer==1)
data
  nombre mujer edad menores meyores Miguel mujeresOmenor mujeresYmenor hombremayor
1  Miguel     0   20   FALSE    TRUE   TRUE         FALSE         FALSE       FALSE
2     Ara     1   17    TRUE   FALSE  FALSE          TRUE          TRUE       FALSE
3 Marirza     1   25   FALSE    TRUE  FALSE          TRUE         FALSE        TRUE
4    Juan     0   35   FALSE    TRUE  FALSE         FALSE         FALSE       FALSE
5   Maira     1   48   FALSE    TRUE  FALSE          TRUE         FALSE        TRUE
6     Dro     0   12    TRUE   FALSE  FALSE          TRUE         FALSE        TRUE

1.2.4. Contenido en (%in%)

Suponga queremos identificar los valores de una determinada variable que cumplen con varias condiciones, para tales fines podemos utilizar el operador or como se muestra en el siguiente ejemplo:
 
data$edad12_22 <- edad == 12 | edad == 22 | edad == 25

Ahora, R coloca un TRUE en las observaciones que cumplen con una de esas edades. Podemos abreviar esta instrucción mediante el operador contenido en (%in%), este coloca el valor TRUE en aquellas observaciones que contienen al meno uno de los valores mostrados en un conjunto determinado:
 
data$edad12_22in <-  edad %in% c(12,22,25)

La función identical me permite comparar todos los valores de dos vectores, aquí la usamos para verificar que ambos procesos arrojan el mismo resultado:
 
identical(data$edad12_22, data$edad12_22in)
[1] TRUE

cbind(edad, data$edad12_22, data$edad12_22)
edad   
[1,]   20 0 0
[2,]   17 0 0
[3,]   25 1 1
[4,]   35 0 0
[5,]   48 0 0
[6,]   12 1 1

# Borra una variable de la data
data<-data[,-which(colnames(data)=="edad12_22")]
data

1.2.5. Between
 
El operador %()% permite identificar si un valor está dentro o fuera de un rango determinando (equivale a > estrictamente mayor y [ es igual a >=.

1.2.6. ifelse

El comando si condicional (ifelse) permite modificar el valor que asuma nuestra variable en los casos donde se cumple la comparación indicada.

ifelse(edad<18,1,0)
[1] 0 1 0 0 0 1

menor1 <- ifelse(edad<18,1,0)
menor2 <- ifelse(edad<18,"Menor", "Mayor")

data.frame(edad, data$menores, menor1, menor2)

edad data.menores menor1 menor2
1   20        FALSE      0  Mayor
2   17         TRUE      1  Menor
3   25        FALSE      0  Mayor
4   35        FALSE      0  Mayor
5   48        FALSE      0  Mayor
6   12         TRUE      1  Menor

1.2.7. Funciones lógicas en R

> is.na(c(NA,22))
[1]  TRUE FALSE

> is.numeric(c(NA,22))
[1] TRUE

> is.logical(c(NA,22))
[1] FALSE

> is.vector(c(NA,22))
[1] TRUE

> is.matrix(c(NA,22))
[1] FALSE

2.3. Indexación con operadores lógicos

Podemos indexar (filtrar) colocando corchetes posteriores al nombre de un objeto o vector y dentro de este corchete colocar la opción lógica que queremos resaltar. Por ejemplo, si queremos traer las edades de las personas menores de edad.

edad[edad<18]            # Edad de los menores
[1] 17 12

edad[edad<18 & mujer==1] # edad de las mujeres menores
[1] 17

mean(edad[mujer==1])     # la edad promedio de las mujeres
[1] 30

2.4. Igualdad parcial (grep)

Los operadores anteriores cuestionan sobre el valor total de las celdas, sin embargo, podemos estar interesados en identificar valores parciales: edades que inician con 1, nombres que inician con A, entre otros. Esta tarea requiere un operador de igualdad parcial. En R este operador se obtiene a partir de la función grep, esta regresa las posiciones de las variables que cumplen con una determinada condición.

En los siguientes ejemplos identificamos, las observaciones cuyos nombres inician con m (hay muchos ejemplos en Internet):

 grep("M", nombre)   # posiciones
[1] 1 3 5

nombre[grep("M", nombre)] #nombres
[1] "Miguel"  "Marirza" "Maira"

nombre[grep("A|M", nombre)] #nombres inciain A o M
[1] "Miguel"  "Ara"     "Marirza" "Maira"

data[grep("M", nombre),] #filtar en la base estos nombres
nombre mujer edad menores meyores Miguel mujeresOmenor mujeresYmenor hombremayor edad12_22in
1  Miguel     0   20   FALSE    TRUE   TRUE         FALSE         FALSE       FALSE       FALSE
3 Marirza     1   25   FALSE    TRUE  FALSE          TRUE         FALSE        TRUE        TRUE
5   Maira     1   48   FALSE    TRUE  FALSE          TRUE         FALSE        TRUE       FALSE

mean(edad[grep("M", nombre)]) #edad promedio de los que su nombre inicia con m
[1] 31

nombre[grep("[A-J]", nombre)] #inicia con un nombre de A a J
[1] "Ara"  "Juan" "Dro"

@nerysramirez01

Creando variables por grupos en dplyr (group_by + mutate)

  Simulemos una base de hogares, donde se identifica el hogar, el sexo (1 mujer) y provincia y edad para cada miembro.   # Definir la lista ...