3.9: Almacenamiento de datos “verdaderos o falsos”
- Page ID
- 151363
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)Tiempo para pasar a un tercer tipo de datos. Un concepto clave en el que se basa mucho R es la idea de un valor lógico. Un valor lógico es una afirmación sobre si algo es verdadero o falso. Esto se implementa en R de una manera bastante sencilla. Hay dos valores lógicos, a saber, VERDADERO
y FALSO
. A pesar de la sencillez, unos valores lógicos son cosas muy útiles. Veamos cómo funcionan.
Evaluar verdades matemáticas
En el clásico libro 1984 de George Orwell, una de las consignas utilizadas por el Partido totalitario era “dos más dos es igual a cinco”, siendo la idea que la dominación política de la libertad humana se completa cuando es posible subvertir incluso la más básica de las verdades. Es un pensamiento aterrador, sobre todo cuando el protagonista Winston Smith finalmente se descompone bajo tortura y acepta la proposición. “El hombre es infinitamente maleable”, dice el libro. Estoy bastante seguro de que esto no es cierto para los humanos 36 pero definitivamente no es cierto para R. R no es infinitamente maleable. Tiene opiniones bastante firmes sobre el tema de lo que es y lo que no es cierto, al menos en lo que respecta a las matemáticas básicas. Si le pido que calcule 2 + 2
, siempre da la misma respuesta, y no es sangrienta 5:
2 + 2
## [1] 4
Por supuesto, hasta ahora R solo está haciendo los cálculos. No le he pedido que afirme explícitamente que 2+2=4 es una afirmación verdadera. Si quiero que R haga un juicio explícito, puedo usar un comando como este:
2 + 2 == 4
## [1] TRUE
Lo que he hecho aquí es usar el operador de igualdad, ==
, para obligar a R a hacer un juicio “verdadero o falso”. 37 Bien, veamos qué piensa R del eslogan del Partido:
2+2 == 5
## [1] FALSE
¡Booyah! ¡Libertad y ponis para todos! O algo así. En fin, vale la pena echar un vistazo a lo que sucede si trato de forzar a R a creer que dos más dos son cinco haciendo una declaración de asignación como 2 + 2 = 5
o 2 + 2 <5
. Cuando hago esto, esto es lo que sucede:
2 + 2 = 5
## Error in 2 + 2 = 5: target of assignment expands to non-language object
A R no le gusta mucho esto. Reconoce que 2 + 2
no es una variable (eso es lo que dice la parte del “objeto no lenguaje”), y no te permitirá intentar “reasignarlo”. Si bien R es bastante flexible, y de hecho te permite hacer algunas cosas bastante notables para redefinir partes de la R misma, solo hay algunas verdades básicas y primitivas a las que se niega a renunciar. No va a cambiar las leyes de adición, y no va a cambiar la definición del número 2
.
Eso es probablemente lo mejor.
Operaciones lógicas
Entonces ahora hemos visto operaciones lógicas en funcionamiento, pero hasta ahora sólo hemos visto el ejemplo más simple posible. Probablemente no te sorprenderá descubrir que podemos combinar operaciones lógicas con otras operaciones y funciones de una manera más complicada, como esta:
3*3 + 4*4 == 5*5
## [1] TRUE
o esto
sqrt( 25 ) == 5
## [1] TRUE
No sólo eso, sino como lo ilustra la Tabla 3.2, existen varios otros operadores lógicos que se pueden utilizar, correspondientes a algunos conceptos matemáticos básicos.
Tabla 3.2: Algunos operadores lógicos. Técnicamente debería estar llamando a estos “operadores relacionales binarios”, pero francamente no quiero. Es mi libro para que nadie pueda obligarme.
operación | operador | entrada de ejemplo | responder |
---|---|---|---|
menos de | < | 2 < 3 | TRUE |
menor o igual a | <= | 2 <= 2 | TRUE |
mayor que | > | 2 > 3 | FALSE |
mayor o igual a | >= | 2 >= 2 | TRUE |
igual a | == | 2 == 3 | FALSE |
no es igual a | ! = | ¡2! = 3 | TRUE |
Ojalá todos estos sean bastante autoexplicativos: por ejemplo, el operador less than <
comprueba si el número de la izquierda es menor que el número de la derecha. Si es menor, entonces R devuelve una respuesta de VERDADERO
:
99 < 100
## [1] TRUE
pero si los dos números son iguales, o si el de la derecha es mayor, entonces R devuelve una respuesta de FALSE
, como ilustran los siguientes dos ejemplos:
100 < 100
## [1] FALSE
100 < 99
## [1] FALSE
En contraste, el operador menor o igual que <=
hará exactamente lo que dice. Devuelve un valor de VERDADERO
si el número del lado izquierdo es menor o igual que el número del lado derecho. Entonces, si repetimos los dos ejemplos anteriores usando <=
, esto es lo que obtenemos:
100 <= 100
## [1] TRUE
100 <= 99
## [1] FALSE
Y en este punto espero que sea bastante obvio lo que el mayor que el operador >
y el mayor que o igual que operador >=
hacer! Siguiente en la lista de operadores lógicos es el no igual a operador!
= que —como con todos los demás— hace lo que dice que hace. Devuelve un valor de VERDADERO
cuando las cosas de cada lado no son idénticas entre sí. Por lo tanto, como 2+2 no es igual a 5, obtenemos:
2 + 2 != 5
## [1] TRUE
Aún no hemos terminado del todo. Hay tres operaciones lógicas más que vale la pena conocer, enumeradas en la Tabla 3.3.
Tabla 3.3: Algunos operadores más lógicos.
operación | operador | entrada de ejemplo | responder |
---|---|---|---|
no | ! | ! (1==1) | FALSE |
o | | | (1==1) | (2==3) | TRUE |
y | & | (1==1) y (2==3) | FALSE |
¡Estos son los no operadores!
, el operador y y
, y el operador u |
. Al igual que los otros operadores lógicos, su comportamiento es más o menos exactamente lo que esperarías dado sus nombres. Por ejemplo, si le pido que evalúe la afirmación de que “ya sea 2+2=4 o 2+2=5” dirías que es verdad. Al tratarse de una declaración “cualquiera o”, todo lo que necesitamos es que una de las dos partes sea cierta. Eso es lo que hace el operador |
:
(2+2 == 4) | (2+2 == 5)
## [1] TRUE
Por otro lado, si le pido que evalúe la afirmación de que “tanto 2+2=4 como 2+2=5” dirías que es falso. Dado que esta es una declaración y necesitamos que ambas partes sean ciertas. Y eso es lo que hace el operador &
:
(2+2 == 4) & (2+2 == 5)
## [1] FALSE
Por último, está el operador no, que es sencillo pero molesto de describir en inglés. Si te pido que valoren mi afirmación de que “no es cierto que 2+2=5” entonces dirías que mi afirmación es cierta; porque mi afirmación es que “2+2=5 es falso”. Y estoy en lo cierto. Si escribimos esto como un comando R obtenemos esto:
! (2+2 == 5)
## [1] TRUE
En otras palabras, ya que 2+2 == 5
es una declaración FALSE
, ¡debe ser el caso que! (2+2 == 5)
es VERDADERO
. Esencialmente, lo que realmente hemos hecho es afirmar que “no falso” es lo mismo que “verdadero”. Obviamente, esto no es realmente correcto en la vida real. Pero R vive en un mundo mucho más negro o blanco: para R todo es verdadero o falso. No se permiten tonalidades de gris. En realidad podemos ver esto mucho más explícitamente, así:
! FALSE
## [1] TRUE
Por supuesto, en nuestro ejemplo 2+2=5, ¡realmente no necesitábamos usar “no”!
y “es igual a” ==
como dos operadores separados. ¡Podríamos haber usado el operador “no es igual a”!
= como esto:
2+2 != 5
## [1] TRUE
Pero hay muchas situaciones en las que realmente necesitas usar el!
operador. Veremos algunos más adelante. 38
Almacenamiento y uso de datos lógicos
Hasta este punto, he introducido datos numéricos (en las Secciones 3.4 y @ref (#vectors)) y datos de caracteres (en la Sección 3.8). Por lo que tal vez no se sorprenda al descubrir que estos valores VERDADERO
y FALSO
que R ha estado produciendo son en realidad un tercer tipo de datos, llamados datos lógicos. Es decir, cuando le pregunté a R si 2 + 2 == 5
y decía [1] FALSO
en respuesta, en realidad estaba produciendo información que podemos almacenar en variables. Por ejemplo, podría crear una variable llamada is.the.party.correct
, que almacenaría la opinión de R:
is.the.Party.correct <2 + 2 == 5
is.the.Party.correct
## [1] FALSE
Alternativamente, puedes asignar el valor directamente, escribiendo VERDADERO
o FALSO
en tu comando. Me gusta esto:
is.the.Party.correct <FALSE
is.the.Party.correct
## [1] FALSE
Mejor aún, porque es un poco tedioso escribir TRUE
o FALSE
una y otra vez, R te proporciona un atajo: puedes usar T
y F
en su lugar (pero es sensible a mayúsculas y minúsculas: t
y f
no funcionarán). 39 Así que esto funciona:
is.the.Party.correct <F
is.the.Party.correct
## [1] FALSE
pero esto no:
is.the.Party.correct <f
## Error in eval(expr, envir, enclos): object 'f' not found
Vectores de lógicas
Lo siguiente a mencionar es que puedes almacenar vectores de valores lógicos exactamente de la misma manera que puedes almacenar vectores de números (Sección 3.7) y vectores de datos de texto (Sección 3.8). Nuevamente, podemos definirlos directamente a través de la función c ()
, así:
x <c(TRUE, TRUE, FALSE)
x
## [1] TRUE TRUE FALSE
o puede producir un vector de lógicas aplicando un operador lógico a un vector. Esto podría no tener mucho sentido para ti, así que vamos a desempacarlo lentamente. Primero, supongamos que tenemos un vector de números (es decir, un “vector no lógico”). Por ejemplo, podríamos usar el vector sales.by.month
que estábamos usando en la Sección @ref (#vectors). Supongamos que quería que R me dijera, por cada mes del año, si realmente vendí un libro en ese mes. Puedo hacerlo escribiendo esto:
sales.by.month > 0
## [1] FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
## [12] FALSE
y nuevamente, puedo almacenar esto en un vector si quiero, como ilustra el siguiente ejemplo:
any.sales.this.month <sales.by.month > 0
any.sales.this.month
## [1] FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
## [12] FALSE
En otras palabras, any.sales.this.month
es un vector lógico cuyos elementos son TRUE
solo si el elemento correspondiente de ventas.por.mes
es mayor que cero. Por ejemplo, como vendí cero libros en enero, el primer elemento es FALSO
.
Aplicación de la operación lógica al texto
En un momento (Sección 3.10) te voy a mostrar por qué estas operaciones lógicas y vectores lógicos son tan útiles, pero antes de hacerlo quiero señalar muy brevemente que puedes aplicarlas tanto al texto como a los datos lógicos. Es solo que necesitamos ser un poco más cuidadosos al entender cómo R interpreta las diferentes operaciones. En esta sección voy a hablar de cómo se aplica al texto el igual a operador ==
, ya que este es el más importante. Obviamente, ¡el no igual a operador!
= da exactamente las respuestas opuestas a ==
así que estoy hablando implícitamente de eso también, pero no voy a dar comandos específicos que muestren el uso de!
=. En cuanto a los demás operadores, voy a diferir una discusión más detallada de este tema a la Sección 7.8.5.
Bien, veamos cómo funciona. En un sentido, es muy sencillo. Por ejemplo, puedo preguntarle a R si la palabra “gato”
es la misma que la palabra “perro”
, así:
"cat" == "dog"
## [1] FALSE
Eso es bastante obvio, y es bueno saber que incluso R puede resolverlo. Del mismo modo, R reconoce que un “gato”
es un “gato”
:
"cat" == "cat"
## [1] TRUE
De nuevo, eso es exactamente lo que esperaríamos. No obstante, lo que hay que tener en cuenta es que R no es para nada tolerante a la hora de gramática y espaciado. Si dos cadenas difieren de alguna manera, R dirá que no son iguales entre sí, como indican los siguientes ejemplos:
" cat" == "cat"
## [1] FALSE
"cat" == "CAT"
## [1] FALSE
"cat" == "c a t"
## [1] FALSE