2.2 Operaciones logicas

Una parte crucial de la informática consiste en hacer preguntas sobre las cosas. ¿Es una cosa más grande que otra? ¿Son dos cosas del mismo tamaño? Las preguntas se pueden unir usando palabras como “y”, “o”, “no”. Las preguntas en R normalmente se evalúan como TRUE(verdadero) o FALSE(falso), pero existe la opción de “tal vez” (cuando la respuesta no está disponible, NA). En R, < significa ‘menor que’, > significa ‘mayor que’ y ! significa ‘no’ (ver Tabla 2.2).

Tabla 2.2
Simbolos Significado
! NO lógico
& Y lógico
| O lógico
< Menor que
<= Menor o igual a
> Mayor que
= Mayor que o igual a
== IGUAL lógico (doble =)
!= No es igual
&& Y con
|| O con
xor(x,y) O exclusivo
isTRUE(X) Una abreviacion de identical(TRUE,X)

2.2.1 TRUE and T with FALSE and F

Puede usar T para VERDADERO y F para FALSO, pero debe tener en cuenta que es posible que T y F se hayan asignado como variables. Así que esto es obvio.

TRUE == FALSE
## [1] FALSE
T == F
## [1] FALSE

Esto, sin embargo, no es tan obvio.

T <- 0
T == FALSE
## [1] TRUE
F <- 1
TRUE == F
## [1] TRUE

Pero ahora, por supuesto, T no es igual a F.

T <- 0
F <- 1
T != F
## [1] TRUE

Para estar seguro, siempre escriba TRUE y FALSE en su totalidad, y nunca use T o F como nombres de variables.

2.2.2 Prueba de igualdad con números reales

Existen estándares internacionales para realizar aritmética de punto flotante, pero en su computadora estos los estándares están fuera del control de R. En términos generales, la aritmética de enteros será exacta entre -1016 y 1016, pero para fracciones y otros números reales perdemos precisión debido al error de redondeo. Esto es sólo es probable que se convierta en un verdadero problema en la práctica si tiene que restar números de tamaño similar pero muy grandes. Una pérdida drástica de precisión en estas circunstancias se denomina “error de cancelación catastrófico”. Ocurre cuando una operación sobre dos números aumenta el error relativo sustancialmente más de lo que aumenta el error absoluto. Debe tener cuidado en la programación cuando desee probar si dos números calculados son o no iguales. R asumirá que quiere decir “exactamente igual”, y lo que eso significa depende de la precisión de la máquina. La mayoría de los números se redondean con una precisión de 53 dígitos binarios. Típicamente, por lo tanto, dos números de punto flotante no serán confiablemente iguales a menos que hayan sido calculados por el mismo algoritmo, y no siempre incluso entonces. Tú puede ver esto elevando al cuadrado la raíz cuadrada de 2: ¿seguro que estos valores son los mismos?

x <- sqrt(2)
x * x == 2
## [1] FALSE

De hecho, no son lo mismo. Podemos ver en cuánto difieren los dos valores por resta:

x <- sqrt(2)
x*x-2
## [1] 4.440892e-16

Este no es un gran número, pero tampoco es cero. Entonces, ¿cómo probamos la igualdad de los números reales? los El mejor consejo es no hacerlo. En su lugar, trate de usar las alternativas ‘menor que’ con ‘mayor que o igual a’, o a la inversa, ‘mayor que’ con ‘menor que o igual a’. Entonces no te equivocarás. A veces, sin embargo, realmente desea probar la igualdad. En esas circunstancias, no use dobles iguales para probar la igualdad, pero emplee la función all.equal en su lugar.

2.2.3 Igualdad de números de punto flotante usando all.equal

La naturaleza de los números de coma flotante utilizados en la computación es la causa de algunas características inicialmente desconcertantes. Se imaginaría que dado que 0,3 menos 0,2 es 0,1, y la lógica que se presenta a continuación se evaluaría como TRUE. No tan.

x <- 0.3 - 0.2
y <- 0.1
x == y
## [1] FALSE

La función llamada idénticaL da el mismo resultado.

x <- 0.3 - 0.2
y <- 0.1
identical(x,y)
## [1] FALSE

La solución es usar la función llamada all.equal que permite diferencias insignificantes.

x <- 0.3 - 0.2
y <- 0.1
all.equal(x,y)
## [1] TRUE

No utilice all.equal directamente en expresiones if. Utilice isTRUE(all.equal( ….))) o identical según corresponda.

2.2.4 Resumir diferencias entre objetos usando all.equal

La función all.equal es muy útil en programación para comprobar que los objetos son como se espera que sean. Cuando ocurren diferencias, all.equal hace un trabajo útil al describir todas las diferencias que encuentra.

a <- c("cat","dog","goldfish")
b <- factor(a)
all.equal(a,b)
## [1] "Modes: character, numeric"                      
## [2] "Attributes: < target is NULL, current is list >"
## [3] "target is character, current is factor"

Aquí, por ejemplo, informa sobre la diferencia entre a que es un vector de caracteres y b que es un factor.

En la función all.equal, el objeto de la izquierda (a) se denomina “TARGET” y el objeto de la derecha (b) es ‘CURRENT’.

Recuerde que los factores se almacenan internamente como números enteros, por lo que tienen modo = numérico.

a <- c("cat","dog","goldfish")
b <- factor(a)
class(b)
## [1] "factor"
mode(b)
## [1] "numeric"

La razón por la cual ‘actual es lista’ en la línea [2] de la salida es que los factores tienen dos atributos y estos se almacenan como una lista, es decir, sus niveles y su clase.

a <- c("cat","dog","goldfish")
b <- factor(a)
attributes(b)
## $levels
## [1] "cat"      "dog"      "goldfish"
## 
## $class
## [1] "factor"

La función all.equal también es útil para obtener comentarios sobre las diferencias en cosas como las longitudes de los vectores.

n1 <- c(1,2,3)
n2 <- c(1,2,3,4)
all.equal(n1,n2)
## [1] "Numeric: lengths (3, 4) differ"

También funciona bien para múltiples diferencias:

n1 <- c(1,2,3)
n2 <- c(1,2,3,4)
n2 <- as.character(n2)
all.equal(n1,n2)
## [1] "Modes: numeric, character"              
## [2] "Lengths: 3, 4"                          
## [3] "target is numeric, current is character"

Tenga en cuenta que “target” es el primer argumento de la función y “current” es el segundo. Si proporciona más de dos objetos que se van a comparar, el tercer objeto y los subsiguientes simplemente se ignoran.

2.2.5 Evaluación de combinaciones de TRUE y FALSE

Es importante comprender cómo se evalúan las combinaciones de variables lógicas y apreciar cómo funcionan las operaciones lógicas (como las de la tabla 2.2) cuando faltan valores, NA. Aquí están todos los resultados posibles expresados como un vector lógico llamado x:

x <- c(NA, FALSE, TRUE)
names(x) <- as.character(x)

Para ver las combinaciones lógicas de & (AND lógico) podemos usar la función externa con x para evaluar las nueve combinaciones de NA, FALSE y TRUE así:

x <- c(NA, FALSE, TRUE)
names(x) <- as.character(x)
outer(x, x, "&")
##        <NA> FALSE  TRUE
## <NA>     NA FALSE    NA
## FALSE FALSE FALSE FALSE
## TRUE     NA FALSE  TRUE

Solo TRUE Y TRUE se evalúa como TRUE. Tenga en cuenta el comportamiento de NA & NA y NA & TRUE. Cuando uno de los dos componentes es NA, el resultado será NA si el resultado es ambiguo. Por lo tanto, NA y VERDADERO se evalúa como NA, pero NA y FALSE se evalúa como FALSE. Para ver las combinaciones lógicas de | (OR lógico) escribir:

x <- c(NA, FALSE, TRUE)
names(x) <- as.character(x)
outer(x, x, "|")
##       <NA> FALSE TRUE
## <NA>    NA    NA TRUE
## FALSE   NA FALSE TRUE
## TRUE  TRUE  TRUE TRUE

Solo FALSE | FALSE se evalúa como FALSE. Tenga en cuenta el comportamiento de NA | NA y NA | FALSO.

2.2.6 Aritmética lógica

La aritmética que involucra expresiones lógicas es muy útil en la programación y en la selección de variables. Si la aritmética lógica no le resulta familiar, persevere con ella, porque quedará claro cuán útil es, una vez que se haya caído el centavo. La clave para entender es que las expresiones lógicas se evalúan como verdaderas o falsas (representadas en R por TRUE o FALSE), y que R puede convertir TRUE o FALSE en valores numéricos: 1 para TRUE y 0 para FALSE. Supongamos que x es una secuencia de 0 a 6 como esta:

x <- 0:6

Ahora podemos hacer preguntas sobre el contenido del vector llamado x. ¿Es x menor que 4?

x <- 0:6
x < 4
## [1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE

La respuesta es sí para los primeros cuatro valores (0, 1, 2 y 3) y no para los últimos tres (4, 5 y 6). Dos funciones lógicas importantes son all y any. Comprueban un vector completo pero devuelven un único valor lógico: TREU o FALSE. ¿Todos los valores de x son mayores que 0?

x <- 0:6
all(x>0)
## [1] FALSE

No. El primer valor de x es un cero. ¿Alguno de los valores de x es negativo?

x <- 0:6
any(x<0)
## [1] FALSE

No. El valor de x más pequeño es un cero.

Podemos usar las respuestas de funciones lógicas en aritmética. Podemos contar los valores verdaderos de (x<4), usando sum:

x <- 0:6
(x<4)*runif(7)
## [1] 0.204947081 0.562502888 0.990701697 0.008139373 0.000000000 0.000000000
## [7] 0.000000000

Podemos multiplicar (x<4) por otros vectores:

x <- 0:6
sum(x<4)
## [1] 4

La aritmética lógica es particularmente útil para generar niveles de factores simplificados durante el modelado estadístico. Supongamos que queremos reducir un factor de cinco niveles (a, b, c, d, e) llamado a un factor de tres niveles llamado agrupando los niveles a y e (nuevo factor de nivel 1) y c y d ( nuevo nivel de factor 3) dejando b distinto (con nuevo nivel de factor 2):

(treatment <- letters[1:5])
## [1] "a" "b" "c" "d" "e"
(t2 <- factor(1+(treatment=="b")+2*(treatment=="c")+2*(treatment=="d")))
## [1] 1 2 3 3 1
## Levels: 1 2 3

El nuevo factor toma el valor 1 por defecto para todos los niveles de factores, y queremos dejarlo como está para los niveles a y e. Por lo tanto, no agregamos nada al 1 si el nivel del factor anterior es a o e. Sin embargo, para el nivel de factor antiguo b, queremos el resultado de que t2=2, por lo que sumamos 1 (tratamiento==“b”) al 1 original para obtener la respuesta que necesitamos. Esto funciona porque la expresión lógica se evalúa como 1 (TRUE) para todos los casos en los que el nivel del factor anterior es b y como 0 (FALSO) en todos los demás casos. Para los niveles de factor antiguos c y d, queremos el resultado de que t2=3, por lo que sumamos 2 al valor de referencia de 1 si el nivel de factor original es c (2* (tratamiento==“c”)) o d (2* (tratamiento==“d”)). Es posible que deba leer esto varias veces antes de que caiga el centavo. Tenga en cuenta que ‘igual lógico’ es un signo igual doble sin un espacio en el medio (==). Necesitas entender la distinción entre:

x <- y -> x se le asigna el valor de y (x obtiene los valores de y)

x = y -> en una función o una lista, x se establece en y a menos que especifique lo contrario.

x == y -> produce TRUE si x es exactamente igual a y FALSE en caso contrario.

2.3 Generación de secuencias

Una forma importante de crear vectores es generar una secuencia de números. Las secuencias más simples están en pasos de 1, y el operador de dos puntos es la forma más fácil de generar este tipo de secuencias. Todo lo que haces es especificar el primer y último valor separados por dos puntos. Aquí hay una secuencia de 0 a 10:

0:10
##  [1]  0  1  2  3  4  5  6  7  8  9 10

Aquí hay una secuencia del 15 al 5:

15:5
##  [1] 15 14 13 12 11 10  9  8  7  6  5

Para generar una secuencia en pasos que no sean 1, use la función seq. Hay varias formas de esto, el cual el más simple tiene tres argumentos: from, to, by (el valor inicial, el valor final y el incremento). Si el valor inicial es menor que el valor final, el incremento debe ser positivo, así:

seq(0, 1.5, 0.1)
##  [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5

Si el valor inicial es mayor que el valor final, el incremento debe ser negativo, así:

seq(6,4,-0.2)
##  [1] 6.0 5.8 5.6 5.4 5.2 5.0 4.8 4.6 4.4 4.2 4.0

En muchos casos, desea generar una secuencia para que coincida con la longitud de un vector existente. En vez de tener para calcular el incremento que obtendrá de principio a fin y producir un vector de exactamente el longitud adecuada, R proporciona las opciones de longitud y longitud. Suponga que tiene un vector de población tamaños:

N<-c(55,76,92,103,84,88,121,91,65,77,99)

Debe trazar esto contra una secuencia que comienza en 0.04 en pasos de 0.01:

seq(from=0.04,by=0.01,length=11)
##  [1] 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13 0.14

Pero esto requiere que calcules la longitud de N. Un método más simple es usar el argumento a lo largo de y especifique el vector, N, cuya longitud debe coincidir:

seq(0.04,by=0.01,along=N)
##  [1] 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13 0.14

Alternativamente, puede hacer que R calcule el incremento (0.01 en este ejemplo), especificando el inicio y el valores finales (desde y hasta), y el nombre del vector (N) cuya longitud debe coincidir:

seq(from=0.04,to=0.14,along=N)
##  [1] 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13 0.14

Una aplicación importante de la última opción es obtener los valores de x para dibujar líneas suaves a través de un diagrama de dispersión de datos utilizando valores predichos de un modelo (consulte la página 207).

Tenga en cuenta que cuando el incremento no coincide con el valor final, la secuencia generada se detiene antes el último valor (en lugar de excederlo):

seq(1.4,2.1,0.3)
## [1] 1.4 1.7 2.0

Si desea un vector formado por secuencias de longitudes desiguales, use la función de secuencia. Suponer que la mayoría de las cinco secuencias que desea hacer coincidir son 1 a 4, pero la segunda es 1 a 3 y el último es del 1 al 5, entonces:

sequence(c(4,3,4,4,4,5))
##  [1] 1 2 3 4 1 2 3 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5

2.3.1 Generación de repeticiones

A menudo querrá generar repeticiones de números o caracteres, para los cuales la función es rep. El objeto que se nombra en el primer argumento se repite un número de veces como se especifica en el segundo argumento. En su más simple, generaríamos cinco 9s como este:

rep(9,5)
## [1] 9 9 9 9 9

Puede ver los problemas involucrados en una comparación de estos tres usos cada vez más complicados del proxy. función:

rep(1:4, 2)
## [1] 1 2 3 4 1 2 3 4
rep(1:4, each = 2)
## [1] 1 1 2 2 3 3 4 4
rep(1:4, each = 2, times = 3)
##  [1] 1 1 2 2 3 3 4 4 1 1 2 2 3 3 4 4 1 1 2 2 3 3 4 4

En el caso más simple, se repite todo el primer argumento (es decir, la secuencia 1 a 4 aparece dos veces). tú a menudo desea que se repita cada elemento de la secuencia, y esto se logra con cada argumento. Finalmente, puede querer que cada número se repita y toda la serie se repita un cierto número de veces (aquí tresveces). Cuando cada elemento de la serie debe repetirse un número diferente de veces, entonces el segundo argumento debe ser un vector de la misma longitud que el vector que comprende el primer argumento (longitud 4 en este ejemplo). Asi que si queremos un 1, dos 2, tres 3 y cuatro 4 escribiríamos:

rep(1:4,1:4)
##  [1] 1 2 2 3 3 3 4 4 4 4

En un caso más complicado, hay una repetición diferente pero irregular de cada uno de los elementos del primero. gráfico. Supongamos que necesitamos cuatro 1, un 2, cuatro 3 y dos 4. Luego usamos la función de concatenación c para crear un vector de longitud 4 c(4,1,4,2) que actuará como segundo argumento de la función rep:

rep(1:4,c(4,1,4,2))
##  [1] 1 1 1 1 2 3 3 3 3 4 4

Aquí está el caso más complejo con datos de caracteres en lugar de números: cada elemento de la serie se repite un número irregular de veces:

rep(c("cat","dog","gerbil","goldfish","rat"),c(2,3,2,1,3))
##  [1] "cat"      "cat"      "dog"      "dog"      "dog"      "gerbil"  
##  [7] "gerbil"   "goldfish" "rat"      "rat"      "rat"

Esta es la forma más general y también la más útil de la función rep.

2.3.2 Niveles de factores generadores

La función gl (‘generar niveles’) es útil cuando desea codificar vectores largos de niveles de factores.La sintaxis de los tres argumentos es: ‘hasta’, ‘con repeticiones de’, ‘hasta la longitud total’. Aquí está el caso más simple donde queremos niveles de factor hasta 4 con repeticiones de 3 repetidas solo una vez (es decir, hasta una longitud total de 12):

gl(4,3)
##  [1] 1 1 1 2 2 2 3 3 3 4 4 4
## Levels: 1 2 3 4

Aquí está la función cuando queremos que todo el patrón se repita dos veces:

gl(4,3,24)
##  [1] 1 1 1 2 2 2 3 3 3 4 4 4 1 1 1 2 2 2 3 3 3 4 4 4
## Levels: 1 2 3 4

Si desea texto para los niveles de los factores, en lugar de números, use etiquetas como esta:

Temp <- gl(2, 2, 24, labels = c("Low", "High"))
Soft <- gl(3, 8, 24, labels = c("Hard","Medium","Soft"))
M.user <- gl(2, 4, 24, labels = c("N", "Y"))
Brand <- gl(2, 1, 24, labels = c("X", "M"))
data.frame(Temp,Soft,M.user,Brand)
##    Temp   Soft M.user Brand
## 1   Low   Hard      N     X
## 2   Low   Hard      N     M
## 3  High   Hard      N     X
## 4  High   Hard      N     M
## 5   Low   Hard      Y     X
## 6   Low   Hard      Y     M
## 7  High   Hard      Y     X
## 8  High   Hard      Y     M
## 9   Low Medium      N     X
## 10  Low Medium      N     M
## 11 High Medium      N     X
## 12 High Medium      N     M
## 13  Low Medium      Y     X
## 14  Low Medium      Y     M
## 15 High Medium      Y     X
## 16 High Medium      Y     M
## 17  Low   Soft      N     X
## 18  Low   Soft      N     M
## 19 High   Soft      N     X
## 20 High   Soft      N     M
## 21  Low   Soft      Y     X
## 22  Low   Soft      Y     M
## 23 High   Soft      Y     X
## 24 High   Soft      Y     M