Operadores
Los operadores son los símbolos que le indican a R que debe realizar una tarea. Combinando datos y operadores es que logramos que R haga su trabajo.
Existen operadores específicos para cada tipo de tarea. Los tipos de operadores principales son los siguientes:
- Aritméticos
- Relacionales
- Lógicos
- De asignación
Operadores aritméticos
Como su nombre lo indica, este tipo de operador es usado para operaciones aritméticas.
En R tenemos los siguientes operadores aritméticos:
| Operador | Operación | Ejemplo | Resultado |
|---|---|---|---|
| + | Suma | 5 + 3 | 8 |
| - | Resta | 5 - 3 | 2 |
| * | Multiplicación | 6 * 3 | 18 |
| / | División | 5 /3 | 1.666667 |
| ^ | Potencia | 5 ^ 3 | 125 |
| %% | División entera | 5 %% 3 | 2 |
Es posible realizar operaciones aritméticas con datos de tipo entero y numérico.
Si escribes una operación aritmética en la consola de R y das Enter, esta se realiza y se devuelve su resultado.
## [1] 45
Cuando intentas realizar una operación aritmética con otro tipo de dato, R primero intentará coercionar ese dato a uno numérico. Si la coerción tiene éxito se realizará la operación normalmente, si falla, el resultado será un error.
Por ejemplo, 4 + “tres”
## Error in 4 + "tres": argumento no-numérico para operador binario
El mensaje “non-numeric argument for binary operator” aparece siempre que intentas realizar una operación aritmética con un argumento no numérico. Si te encuentras un un error que contiene este mensaje, es la primera pista para que identifiques donde ha ocurrido un problema.
Cualquier operación aritmética que intentemos con un dato NA, devolverá NA como resultado.
## [1] NA
## [1] NA
## [1] NA
La división entera
La operación que realiza es una división de un número entre otro, pero en lugar de devolver el cociente, nos devuelve el residuo.
Por ejemplo, si hacemos una división entera de 4 entre 2, el resultado será 0. Esta es una división exacta y no tiene residuo.
## [1] 0
En cambio, si hacemos una división entera de 5 entre 2, el resultado será 1, pues este es el residuo de la operación.
## [1] 1
Operadores relacionales
Los operadores lógicos son usados para hacer comparaciones y siempre devuelven como resultado TRUE o FALSE (verdadero o falso, respectivamente).
| Operador | Comparación | Ejemplo | Resultado |
|---|---|---|---|
| < | Menor que | 5 < 3 | FALSE |
| <= | Menor o igual que | 5 <= 3 | FALSE |
| > | Mayor que | 5 > 3 | TRUE |
| >= | Mayor o igual que | 5 >= 3 | TRUE |
| == | Exactamente igual que | 5 == 3 | FALSE |
| != | No es igual que | 5 != 3 | TRUE |
Es posible comparar cualquier tipo de dato sin que resulte en un error.
Sin embargo, al usar los operadores >,
>= , < y <= con cadenas
de texto, estos tienen un comportamiento especial.
Por ejemplo,
## [1] TRUE
Este resultado se debe a que se ha hecho una comparación por orden alfabético.
Cuando intentamos comparar factores, siempre obtendremos como resultado NA y una advertencia acerca de que estos operadores no son significativos para datos de tipo factor.
## Warning in Ops.factor(as.factor("casa"), "barco"): '>' not meaningful for
## factors
## [1] NA
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 (FALSO).
| Operador | Comparación | Ejemplo | Resultado |
|---|---|---|---|
x | y |
x Ó y es verdadero | TRUE | FALSE |
TRUE |
x & y |
x Y y son verdaderos | TRUE & FALSE |
FALSE |
!x |
x no es verdadero (negación) | !TRUE |
FALSE |
isTRUE(x) |
x es verdadero (afirmación) | isTRUE(TRUE) |
TRUE |
Estos operadores pueden ser usados con estos con datos de tipo numérico, lógico y complejo. Al igual que con los operadores relacionales, los operadores lógicos siempre devuelven TRUE o FALSE.
Para realizar operaciones lógicas, todos los valores numéricos y complejos distintos a 0 son coercionados a TRUE, mientras que 0 siempre es coercionado a FALSE.
Por ejemplo, 5 | 0 resulta en TRUE y 5 & FALSE resulta en FALSE. Podemos comprobar lo anterior con la función isTRUE().
## [1] TRUE
## [1] FALSE
## [1] FALSE
## [1] FALSE
Estos operadores se pueden combinar para expresar relaciones complejas.
## [1] TRUE
Operadores de asignación
Este es probablemente el operador más importante de todos, pues nos permite asignar datos a variables.
| Operador | Operación |
|---|---|
| <- | Asigna un valor a una variable |
| = | Asigna un valor a una variable |
En este ejemplo, asignamos valores a las variables estatura y peso.
Llamamos a sus valores asignados
## [1] 1.73
## [1] 83
Usamos los valores asignados para realizar operaciones.
## [1] 27.7323
Cambiamos el valor de una variable a uno nuevo y realizamos operaciones
## [1] 76
## [1] 25.39343
## [1] 19.72387
Asignamos el resultado de una operación a una variable nueva.
## [1] 19.72387
Estructuras de datos
Las estructuras tienen diferentes características. Entre ellas, las que distinguen a una estructura de otra son su número de dimensiones y si son homogeneas o hereterogeneas.
La siguiente tabla muestra las principales estructuras de control que te encontrarás en R.
| Dimensiones | Homogeneas | Heterogeneas |
|---|---|---|
| 1 | Vector | Lista |
| 2 | Matriz | Data frame |
| n | Array |
Vectores
Un vector es la estructura de datos más sencilla en R. Un vector es una colección de uno o más datos del mismo tipo.
Todos los vectores tienen tres propiedades:
- Tipo. Un vector tiene el mismo tipo que los datos que contiene. Si tenemos un vector que contiene datos de tipo numérico, el vector será también de tipo numérico. Los vectores son atómicos, pues sólo pueden contener datos de un sólo tipo, no es posible mezclar datos de tipos diferentes dentro de ellos.
- Largo. Es el número de elementos que contiene un vector. El largo es la única dimensión que tiene esta estructura de datos.
- Atributos. Los vectores pueden tener metadatos de muchos tipos, los cuales describen características de los datos que contienen. Todos ellos son incluidos en esta propiedad.
Cuando una estructura únicamente puede contener datos de un sólo tipo, como es el caso de los vectores, decimos que es homogénea, pero no implica que necesariamente sea atómica
Como los vectores son la estructura de datos más sencilla de R, datos simples como el número 3, son en realidad vectores. En este caso, un vector de tipo numérico y largo igual a 1.
## [1] 3
verificamos que el 3 es un vector con la función is.vector().
## [1] TRUE
Y usamos la función length() para conocer su largo.
## [1] 1
Lo mismo ocurre con los demás tipos de datos, por ejemplo, con cadenas de texto y datos lógicos.
## [1] TRUE
## [1] TRUE
Creación de vectores
Creamos vectores usando la función c() (combinar).
Llamamos esta función y le damos como argumento los elementos que deseamos combinar en un vector, separados por comas.
- Vector numérico
## [1] 1 2 3 5 8 13
- Vector de cadena de texto
## [1] "arbol" "casa" "persona"
- Vector lógico
## [1] TRUE TRUE FALSE FALSE TRUE
Si deseamos agregar un elemento a un vector ya existente, podemos hacerlo combinando nuestro vector original con los elementos nuevos y asignando el resultado a nuestro vector original.
## [1] TRUE FALSE TRUE FALSE
Naturalmente, podemos crear vectores que son combinación de vectores.
mi_vector_1 <- c(1, 3, 5)
mi_vector_2 <- c(2, 4, 6)
mi_vector_3 <- c(mi_vector_1, mi_vector_2)
mi_vector_3## [1] 1 3 5 2 4 6
Si intentamos combinar datos de diferentes tipos en un mismo vector, R realizará coerción automáticamente. El vector resultante será del tipo más flexible entre los datos que contenga, siguiendo las reglas de coerción.
Creamos un vector numérico.
## [1] "numeric"
Si intentamos agregar un dato de tipo cadena de texto, nuestro vector ahora será de tipo cadena de texto.
## [1] "character"
Como las cadenas de texto son el tipo de dato más flexible, siempre que creamos un vector que incluye un dato de este tipo, el resultado será un vector de texto.
## [1] "character"
Podemos crear vectores de secuencias numéricas usando :. De un lado de los dos puntos escribimos el número de inicio de la secuencia y del otro el final.
Por ejemplo, creamos una secuencia del 1 al 10.
## [1] 1 2 3 4 5 6 7 8 9 10
También podemos crear una secuencia del 10 al 1.
## [1] 10 9 8 7 6 5 4 3 2 1
Las secuencias creadas con : son consecutivas con incrementos o decrementos de 1. Estas secuencias pueden empezar con cualquier número, incluso si este es negativo o tiene cifras decimales
-Número negativo
## [1] -43 -42 -41 -40 -39 -38 -37 -36 -35 -34 -33 -32 -31 -30
- Número con cifras decimales
## [1] 67.23 68.23 69.23 70.23 71.23 72.23 73.23 74.23
Si nuestro número de inicio tiene cifras decimales, estas serán respetadas al hacer los incrementos o decrementos de uno en uno. En contraste, si es nuestro número de final el que tiene cifras decimales, este será redondeado.
- Se conservan los decimales del inicio
## [1] -2.48 -1.48 -0.48 0.52 1.52
## [1] 1 3 5 7 9 11 13 15
Vectorización de operaciones
Existen algunas operaciones al aplicarlas a un vector, se aplican a cada uno de sus elementos. A este proceso le llamamos vectorización.
Las operaciones aritméticas y relacionales pueden vectorizarse. Si las aplicamos a un vector, la operación se realizará para cada uno de los elementos que contiene.
Por ejemplo, creamos un vector numérico.
Si aplicamos operaciones aritméticas, obtenemos un vector con un resultado por cada elemento.
- Operaciones aritméticas
## [1] 4 5 8 9 10 12 13
## [1] 4 6 12 14 16 20 22
## [1] 0 1 0 1 0 0 1
Al aplicar operaciones relacionales, obtenemos un vector de TRUEy FALSE, uno para cada elemento comparado.
## [1] FALSE FALSE FALSE FALSE TRUE TRUE TRUE
## [1] TRUE TRUE TRUE FALSE FALSE FALSE FALSE
## [1] FALSE FALSE FALSE TRUE FALSE FALSE FALSE
Esta manera de aplicar una operación es muy eficiente. Comparada con otros procedimientos, requiere de menos tiempo de cómputo, lo cual a veces es considerable, en particular cuando trabajamos con un número grande de datos.
Aunque el nombre de este proceso es vectorización, también funciona, en ciertas circunstancias, para otras estructuras de datos.
Claro, aquí tienes un ejercicio simple para trabajar con vectores en R:
Ejercicio:
Supón que tienes un conjunto de datos de temperaturas en grados Celsius registradas a lo largo de una semana. Quieres convertir estas temperaturas a grados Fahrenheit, calcular la temperatura promedio en Fahrenheit para esa semana, y determinar cuál fue la temperatura máxima y mínima en Celsius.
Datos de temperatura en Celsius: 17, 20, 15, 22, 16, 21, 18
Pasos del ejercicio:
- Crea un vector en R con los datos de temperatura en Celsius.
- Convertir el vector de temperaturas a Fahrenheit. (F = C * 9/5 + 32).
- Calcula el promedio de las temperaturas en Fahrenheit.
- Encuentra la temperatura máxima y mínima en Celsius.
Matrices y arrays
Las matrices y arrays pueden ser descritas como vectores multidimensionales. Al igual que un vector, únicamente pueden contener datos de un sólo tipo, pero además de largo, tienen más dimensiones.
Los arrays, por su parte, pueden tener un número arbitrario de dimensiones. Pueden ser cubos, hipercubos y otras formas.
Creación de matrices
Creamos matrices en R con la función matrix(). La
función matrix() acepta dos argumentos, nrow y
ncol. Con ellos especificamos el número de renglones y
columnas que tendrá nuestra matriz.
- Un vector numérico del uno al doce
## [1] 1 2 3 4 5 6 7 8 9 10 11 12
- matrix() sin especificar renglones ni columnas
## [,1]
## [1,] 1
## [2,] 2
## [3,] 3
## [4,] 4
## [5,] 5
## [6,] 6
## [7,] 7
## [8,] 8
## [9,] 9
## [10,] 10
## [11,] 11
## [12,] 12
- Tres renglones y cuatro columnas
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
- Cuatro columnas y tres columnas
## [,1] [,2] [,3]
## [1,] 1 5 9
## [2,] 2 6 10
## [3,] 3 7 11
## [4,] 4 8 12
Los datos que intentemos agrupar en una matriz serán acomodados en orden, de arriba a abajo, y de izquierda a derecha, hasta formar un rectángulo.
Cuando intentamos acomodar un número diferente de elementos y celdas, ocurren dos cosas diferentes.
Si el número de elementos es mayor al número de celdas, se acomodarán todos los datos que sean posibles y los demás se omitirán.
## Warning in matrix(1:12, nrow = 3, ncol = 3): data length differs from size of
## matrix: [12 != 3 x 3]
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
Si, por el contrario, el número de celdas es mayor que el número de elementos, estos se reciclaran. En cuanto los elementos sean insuficientes para acomodarse en las celdas, R nos devolverá una advertencia y se empezaran a usar los elementos a partir del primero de ellos
## Warning in matrix(1:12, nrow = 5, ncol = 4): data length [12] is not a
## sub-multiple or multiple of the number of rows [5]
## [,1] [,2] [,3] [,4]
## [1,] 1 6 11 4
## [2,] 2 7 12 5
## [3,] 3 8 1 6
## [4,] 4 9 2 7
## [5,] 5 10 3 8
Otro procedimiento para crear matrices es la unión vectores con las siguientes funciones:
cbind()para unir vectores, usando cada uno como una columna.rbind()para unir vectores, usando cada uno como un renglón. De este modo podemos crear cuatro vectores y unirlos para formar una matriz. Cada vector será un renglón en esta matriz.
Creamos cuatro vectores, cada uno de largo igual a cuatro.
Usamos rbind() para crear un matriz, en la que cada
vector será un renglón.
## [,1] [,2] [,3] [,4]
## vector_1 1 2 3 4
## vector_2 5 6 7 8
## vector_3 9 10 11 12
## vector_4 13 14 15 16
Si utilizamos cbind(), entonces cada vector será una
columna.
## vector_1 vector_2 vector_3 vector_4
## [1,] 1 5 9 13
## [2,] 2 6 10 14
## [3,] 3 7 11 15
## [4,] 4 8 12 16
Al igual que con matrix(), los elementos de los vectores son reciclados para formar una estructura rectangular y se nos muestra un mensaje de advertencia.
- Elementos de largo diferente
## Warning in cbind(vector_1, vector_2, vector_3): number of rows of result is not
## a multiple of vector length (arg 1)
## vector_1 vector_2 vector_3
## [1,] 1 1 1
## [2,] 2 2 2
## [3,] 1 3 3
## [4,] 2 1 4
## [5,] 1 2 5
Finalmente, las matrices pueden contener NAs.
Creamos dos vectores con un NA en ellos.
Creamos una matriz con rbind().
## [,1] [,2] [,3] [,4]
## vector_1 1 2 3 4
## vector_2 5 6 7 8
## vector_3 9 10 11 12
## vector_4 13 14 15 16
Como NA representa datos perdidos, puede estar presente
en compañía de todo tipo de de datos.
Propiedades de las matrices
No obstante que las matrices y arrays son estructuras que sólo pueden contener un tipo de datos, no son atómicas. Su clase es igual a matriz (matrix) o array segun corresponda.
Verificamos esto usando la función class().
## [1] "matrix" "array"
Las matrices y arrays pueden tener más de una dimensión.
Obtenemos el número de dimensiones de una matriz o array con la función dim(). Esta función nos devolverá varios números, cada uno de ellos indica la cantidad de elementos que tiene una dimensión.
## [1] 4 3
Cabe señalar que si usamos dim() con un vector,
obtenemos NULL. Esto ocurre con todos los objetos unidimensionales
## NULL
Finalmente, las operaciones aritméticas también son vectorizadas al aplicarlas a una matriz. La operación es aplicada a cada uno de los elementos de la matriz.
Creamos una matriz.
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
Intentemos sumar, multiplicar y elevar a la tercera potencia.
## [,1] [,2] [,3]
## [1,] 2 5 8
## [2,] 3 6 9
## [3,] 4 7 10
- Multiplicación
## [,1] [,2] [,3]
## [1,] 2 8 14
## [2,] 4 10 16
## [3,] 6 12 18
- Potenciación
## [,1] [,2] [,3]
## [1,] 1 64 343
## [2,] 8 125 512
## [3,] 27 216 729
Si intentamos vectorizar una operación utilizando una matriz con
NAs, esta se aplicará para los elementos válidos,
devolviendo NA cuando corresponda.
Creamos una matriz con NAs.
## [,1] [,2] [,3]
## vector_1 NA 2 3
## vector_2 4 5 NA
Intentamos dividir sus elementos entre dos.
## [,1] [,2] [,3]
## vector_1 NA 1.0 1.5
## vector_2 2 2.5 NA
Finalmente, podemos usar la función t() para transponer
una matriz Creamos una matriz con tres renglones y dos columnas.
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
Usamos t() para transponer.
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
Ejercicio Construya la matriz en R
\[ A=\left(\begin{array}{ccc} 6 & 8 & 9\\ 7 & 4 & 2\\ 1 & 5 & 4\\ 10 & 0 & 9 \end{array}\right) \]
Data frames
Los data frames son estructuras de datos de dos dimensiones (rectangulares) que pueden contener datos de diferentes tipos, por lo tanto, son heterogéneas. Esta estructura de datos es la más usada para realizar análisis de datos.
En términos generales, los renglones en un data frame representan casos, individuos u observaciones, mientras que las columnas representan atributos, rasgos o variables.
Para crear un data frame usamos la función data.frame().
Esta función nos pedirá un número de vectores igual al número de
columnas que deseemos. Todos los vectores que proporcionemos deben tener
el mismo largo.
Esto es muy importante: Un data frame está compuesto por vectores.
mi_df <- data.frame(
"entero" = 1:4,
"factor" = c("a", "b", "c", "d"),
"numero" = c(1.2, 3.4, 4.5, 5.6),
"cadena" = as.character(c("a", "b", "c", "d"))
)## entero factor numero cadena
## 1 1 a 1.2 a
## 2 2 b 3.4 b
## 3 3 c 4.5 c
## 4 4 d 5.6 d
## [1] 4 4
El largo de un data frame es igual a su número de columnas
## [1] 4
names()nos permite ver los nombres de las columnas
## [1] "entero" "factor" "numero" "cadena"
- La clase de un data frame es data.frame
## [1] "data.frame"
Si los vectores que usamos para construir el data frame no son del mismo largo, los datos no se reciclaran. Se nos devolverá un error
Creamos una matriz.
Usamos as.data.frame() para coercionar una matriz a un
data frame.
Verificamos el resultado
## [1] "data.frame"
## V1 V2 V3 V4
## 1 1 4 7 10
## 2 2 5 8 11
## 3 3 6 9 12
Listas
Las listas, al igual que los vectores, son estructuras de datos unidimensionales, sólo tienen largo, pero a diferencia de los vectores cada uno de sus elementos puede ser de diferente tipo o incluso de diferente clase, por lo que son estructuras heterogéneas.
Para crear una lista se usa la función list(), que nos
pedirá los elementos que deseamos incluir en nuestra lista. Para esta
estructura, no importan las dimensiones o largo de los elementos que
queramos incluir en ella.
Al igual que con un data frame, tenemos la opción de poner nombre a cada elemento de una lista.
## $un_vector
## [1] 1 2 3 4 5 6 7 8 9 10
##
## $una_matriz
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
##
## $un_df
## num let
## 1 1 a
## 2 2 b
## 3 3 c
Creamos una lista que contiene otras listas.
## $lista1
## $lista1$un_vector
## [1] 1 2 3 4 5 6 7 8 9 10
##
## $lista1$una_matriz
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
##
## $lista1$un_df
## num let
## 1 1 a
## 2 2 b
## 3 3 c
##
##
## $lista2
## $lista2$un_vector
## [1] 1 2 3 4 5 6 7 8 9 10
##
## $lista2$una_matriz
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
##
## $lista2$un_df
## num let
## 1 1 a
## 2 2 b
## 3 3 c
Propiedades de una lista
Una lista es unidimensional, sólo tiene largo.
El largo de una lista es igual al número de elementos que contiene, sin importar de qué tipo o clase sean. Usamos la lista recursiva que creamos en la sección anterior para ilustrar esto.
## [1] 2
Las listas tienen clase list, sin importar qué elementos contienen.
## [1] "list"
Coerción
Al igual que con los datos, cuando intentamos hacer operaciones con una estructura de datos, R intenta coercionarla al tipo apropiado para poder llevarlas a cabo con éxito.
También podemos usar alguna de las funciones de la familia as() coercionar de un tipo de estructura de datos. A continuación se presentan las más comunes.
| Función | Coerciona a | Coerciona exitosamente a |
|---|---|---|
| as.vector() | Vector | Matrices |
| as.matrix() | Matrices | Vectores, Data frames |
| as.data.frame() | Data frame | Vectores, Matrices |
| as.list() | Lista | Vectores, Matrices, Data frames |
Importar y exportar datos
Lo primero que tenemos que hacer para empezar un análisis con datos en R es, evidentemente, cargar los datos en R.