preloader

Tipo y estructura de Datos

blog-image

Ya viste cómo trabajar en R y Rstudio, aprendiste a configurar tu directorio de trabajo, sabes instalar librerias y cómo llamarlas, aprendiste qué son los scripts y lo útiles para trabajar en R.

Es decir, ya tienes tus primeros pinitos de conocimiento sobre R, ya aumentaste un 1% de tu fitnes, tienes 1% de probabilidad más a tu favor, y si no lo has leído, acá te lo dejo …y ahora un poco de teoría.


Cómo lo prometido es deuda, en el post títulado ¿Qué necesito para comenzar en R?, viste que existen 7 tipos de datos (integer, numeric, logic, character, factor, NA y NULL); ahora bien, en este post comenzaremos con la verificación de los tipos de datos, es decir, vas a saber qué tipos de datos está leyendo R.

Para lograr tal objetivo, necesitas tener una base de datos para estudiar, en R puedes encontrar varias bases para prácticar, pero en esta oportunidad usaremos iris; que es una base de datos con valores asociados al largo (length) y ancho (width) de los sépalos y los pétalos de varias especies vegetales que podremos explorar, luego aprenderás cómo cargar tú propio archivo a R.

Exploración de datos

Vamos a empezar este post dando un pequeño resumen sobre la exploración de datos, pero ten en cuenta que iremos más profundo en un próximo post. Para realizar esta tarea existen algunas funciones propias Rbase, como head(), tail(), entre otras. Sin embargo hay muchas otras funciones para poder hacer una adecuada exploración y transformación de datos.

Para empezar vamos a explorar un poco la base de datos iris y ver que elementos la componen

Nota: Todo lo que esté después del signo # en nuestro código, R lo omite, así como cuando tu amorcito omite tus mensajes de buenos días.

head(iris) # (Cabecera) Se utiliza para mostrar las primeras 6 filas de los datos.
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
tail(iris) # (Cola) por el contrario muestra las 6 últimas
##     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
## 145          6.7         3.3          5.7         2.5 virginica
## 146          6.7         3.0          5.2         2.3 virginica
## 147          6.3         2.5          5.0         1.9 virginica
## 148          6.5         3.0          5.2         2.0 virginica
## 149          6.2         3.4          5.4         2.3 virginica
## 150          5.9         3.0          5.1         1.8 virginica

Tambien tenemos la función View(), la cual es una función bastante últil; es más, considero que debería ser la primera en usar al cargar nuestros datos a R con el objetivo de visualizar los datos en una nueva ventana y así poder hacer una primera inspección. Hagamos el siguiente ejercicio y utilicemos esta función

iris
View(iris)

¿Notaste alguna diferencia al llamar sólo iris y usar View(iris)?. Supongo que lograste ver la gran diferencia que existe en inspeccionar los datos en una ventana de Rstudio a tener que verlos sobre la consola.

En este punto, me gustaria hacerte una aclaración: también existen librerias especializadas en la exploración de datos.

Por ejemplo, la libreria tidyverse que contiene a su vez un set completo de librerías entre ellas dplyr, es una de las librerias más usadas por los científicos de datos por su fácil manejo y cómo ellos lo llaman por su “Curva de aprendizaje” que se refiere a la cantidad de información disponible y al número de personas estudiandolo.

Otra función muy interesante para conocer los tipos de datos que contiene nuestro dataset es: class(), esta función nos mostrará en la consola qué tipo de datos tenemos, ya que a simple vista es muy díficil saberlo, y si realizamos este pre proceso antes de comenzar a correr nuestros análsis, vamos a poder evitar varios inconvenientes con varias librerias de R, que son muy claras y muy sensibles con el tipo de datos que necesitamos para hacer nuestros análisis.

Atención, atención!!!

El simbolo <- lo usamos para asignar variables, o en otras palabras, ponerle nombre a las cosas. Si digitamos Alt + - nos aparecerá dicho simbolo en Rstudio.
número <- 357 # Como es un número esperamos que lo que vamos a obtener sea "numeric"
class(número)
## [1] "numeric"
nombre <- "Aotus"# Cómo está entre comillas Aotus, esperamos que lo lea como caracter
class(nombre)
## [1] "character"
combinado <- c(2,1.62, "alelo", "HardyWeinberg") 
# La letra "c" se usa para concatenar (agrupar)
class(combinado)
## [1] "character"

¿Qué pasó con nuestra variable llamada combinado?

Allí podemos observar que ocurrieron dos cosas; primero, tenemos diferentes tipos de datos, es claro para nosotros que hay datos de tipo numeric (2 y 1.6) y character (“alelo”, “HardyWeinberg”), pero la función mostró que todos eran character.

¿Por qué ocurre esto?

Esto ocurre de manera implicita en R por algo llamado coerción; es decir los datos son forzados a transformarse a otro tipo de dato, o cómo dice el viejo refrán: “Al que anda entre miel, algo se le pega”


Esta coerción tiene un orden de jerararquía, es decir, que R transformará nuestros datos según un orden establecido y no ocurre al azar. Orden que podemos ver a continuación:

logical -> integer -> numeric -> character

Ahora que ya sabes qué ocurrió y que esto puede ocurrir en tus proyectos, es necesario prestar más atención a tus datos, y saber la importancia de revisarlos antes de comenzar a correr un código de una librería. Por otro lado, debes tener en cuenta que la coerción ocurre sin nosotros quererlo, pero no siempre va a ser así, nosotros podemos transformar los datos siempre y cuando sea lógico hacerlo usando la familia as() (más adelante la veremos).

Siguiendo con nuestros ejercicios, te voy a mostrar un ejemplo más usando la función class(), acompañado de la función lapply() (la cual veremos en otro post más a fondo, si quieres saber como funciona, en tu consola escribe ?lapply) que nos ayudará a evaluar cada una de las columnas de los datos de la database. Aquí pretendemos explorar que tipo de datos tenemos en nuestra data frame o base de datos.

lapply(iris, class)
## $Sepal.Length
## [1] "numeric"
## 
## $Sepal.Width
## [1] "numeric"
## 
## $Petal.Length
## [1] "numeric"
## 
## $Petal.Width
## [1] "numeric"
## 
## $Species
## [1] "factor"

Cómo puedes observar, con este par de funciones trabajando de la mano, podemos conocer qué tipos de datos tenemos en nuestra dataframe, esto nos facilitará mucho nuestro flujo de trabajo.

Transformación de datos o forzar coerción.

Ahora si, con todo lo que ya sabes, comprenderás mejor a través de ejemplos la transformación de datos, entonces, hágamoslo pequeñín:

Atención, atención!!!

El símbolo $ lo usamos en R para “llamar” a una columna de nuestra base datos

En este ejemplo quedará un poco más claro. Tenemos una base de datos llamada Proyecto y los lugares que se trabajaron los numeraron, en vez de haberles colocado un nombre, vaya problema!. Así, observaremos nuestros primeros datos y luego veremos el tipo de clase de la columna Lugar, tal y como lo vemos en este código:

head(Proyecto)
##   Lugar Sepal.Width Petal.Length Petal.Width Species
## 1     5         3.5          1.4         0.2  setosa
## 2     5         3.0          1.4         0.2  setosa
## 3     5         3.2          1.3         0.2  setosa
## 4     5         3.1          1.5         0.2  setosa
## 5     5         3.6          1.4         0.2  setosa
## 6     5         3.9          1.7         0.4  setosa
class(Proyecto$Lugar)
## [1] "numeric"

Cómo pudiste observar esta columna de datos es identificada por R como numeric, pero ya sabemos que no son números, si no que son nombres de sitios, por eso, tenemos que transformalos para que R no vaya a mezclarlos y quizá generar error en nuestros análisis. Para ello, utilizaremos la función as.character() como lo vemos en el siguiente ejemplo

char <- as.character(Proyecto$Lugar)
class(char)
## [1] "character"

Y quedó listo nuestra intención!

Pero… ¿Entonces sólo puedo transformar de numeric a character?


También puedes realizar otros tipos de coerción, según lo que necesites o como te lo pidan usando los comandos que verás en la siguiente tabla:

Función para transformar - Tipo de coerción o transformación
as.integer() Entero
as.numeric() Numérico
as.factor() Factor
as.logical() Lógico
as.null() Null


¿Cómo usarlos? Te cuento que se usan tal y como hicimos con as.character()

Conclusión sobre tipo y transformación de datos.

Hasta aquí has aprendido a identificar los tipos de datos usando la función class() y también sobre la coerción que ocurre automáticamente en R al crear un vector, que creemos que tiene diferentes tipos de datos; así mismo aprendiste sobre la familia as() para forzar la coerción o transformar los datos al tipo de dato que estas necesitando.

Adicionalmente, aprendiste sobre la exploración básica de los datos usando las funciones View(),head() y tail(), que te van a servir mucho para evitar incovenientes con R y así poder conocer cómo está organizada o compuesta tu base datos y también viste, que en R muchas formas de hacer lo mismo, así que no te preocupes, tú acomódate con lo que mas te guste.

Estructura de datos

La estructura de datos son objetos que contienen un tipo de dato o varios tipos de datos, y poseen diferentes caracteristicas como dimensiones si son homogéneas o heterogéneas.

Homogéneas Característica Heterogéneas Característica
Vector (Una dimensión) Colección de uno o mas datos del mismo tipo. Su dimensión es la misma cantidad de datos que posee Lista (Una dimensión) Al igual que los vectores posee solo una dimensión, pero sus datos pueden ser de diferentes tipos e incluso contener estructuras.
Matriz (Dos dimensiones) Vector multidimensional. Solo puede contener datos de un solo tipo y posee sólo dos dimensiones,largo (High) y alto (length) Data Frame (Dos dimensiones) Poseen dos dimensiones y puede contener datos de diferentes tipos, es la más común para hacer análisis de datos (versión mas flexible de una matriz).
Array (n dimensiones) Iguales características que una matriz, pero puede poseer más de dos dimensiones

Ahora, veremos como funciona cada una de estas estructuras con ejemplos útiles.

Vectores

Los vectores son la estructura de datos mas sencilla en R, como vimos en la anterior tabla, su dimensión depende del número de datos que contenga y sólo puede tener un sólo tipo de dato.

¿Cómo puedes saber que tienes un vector y cómo puedes crear vectores?

Ya conoces la función class() que nos ayuda a identificar el tipo de dato que tenemos y algunas veces el tipo de estructura de datos; sin embargo, la familia de funciones is() es la mas adecuada para definir estructura de los datos de la siguiente manera:

3
## [1] 3
is.vector(3)
## [1] TRUE
class(3)
## [1] "numeric"

Cómo lo puedes notar, al usar ambas funciones nos arrojan diferentes resultados, ya que la función class() nos indicará el tipo de dato y la función is() al ser lógica, nos dirá si es cierto (TRUE) o falsa (FALSE), este tipo de respuesta se conoce como Booleana.

Otro ejemplo:

tres <- 3
class(tres)
## [1] "numeric"
is.vector(tres)
## [1] TRUE

La forma de crear un vector es muy sencilla; es más, todo este tiempo lo estuviste viendo, necesitamos del operador <- y si vas a agregar varios datos del mismo tipo usas c(). Por otra parte, hay algo muy importante que debes aprender y es la forma en la que vas a asignar los nombres a la estructura de los datos. Lo importante es que signifiquen algo para ti y que alguien más lo pueda comprender.

Más ejemplos:

num <- c(1233,555,88,99,17)
class(num)
## [1] "numeric"
is.vector(num)
## [1] TRUE
nomb <- c("Sofia", "Camila", "Juliana", 
          "Pablo", "Andrés", "Wallace")
class(nomb)
## [1] "character"
is.vector(nomb)
## [1] TRUE

Ahora te toca a ti practicar, crea diferentes vectores, con diferentes tipos de datos, explora todo lo que puedes hacer, por ejemplo intenta sumar vectores numéricos y observa que pasa, como en el siguiente ejemplo:

emj1 <- c(112,667,99,56,47,12)
emj2 <- c(22,65,23.8,99,101,41)

suma <- emj1 + emj2
suma
## [1] 134.0 732.0 122.8 155.0 148.0  53.0

¿Que ocurrió?, te queda de tarea describir de la mejor manera lo que ocurrió. ¿Qué pasaría si los vectores no tienen el mismo número de datos? Cuéntanos!

Matrices y arrays

Estas estructuras son usadas en matemáticas y estadística; es más, es una de las estructuras más comunes y solicitadas en muchos de los paquetes que solemos usar en Biología, y también es una de las razones por las cuales nos desesperamos con R y de querer darle al teclado como locos.


Ahora, ¿Cómo reconocer y crear matrices?

Es tan fácil cómo escribir matrix(), esta función acepta dos argumentos, nrow (número de filas) y ncol (número de columnas) para indicar el número de filas y columnas de la matriz que vas a generar, como en el siguiente código

Esto lo podemos hacer sin especificar el número de columnas y filas. Para este ejemplo vas a generar una matriz del 1 al 12 de la siguiente manera: 1:12

matrix(1:12)
##       [,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

Acá R automáticamente nos muestra una matriz con 12 filas y una columna, pero supongamos que tu quieres que sean 6 filas y 2 columnas, para ello ingresaremos de la siguiente manera

matrix(1:12, nrow = 6, ncol = 2)
##      [,1] [,2]
## [1,]    1    7
## [2,]    2    8
## [3,]    3    9
## [4,]    4   10
## [5,]    5   11
## [6,]    6   12

Ahora crea una matriz con números del 1 al 12 (1:12) con un nrow de 6 y ncol de 4, observa que pasa.

También podemos crear matrices uniendo vectores con las funciones cbind() (unión cómo columnas) y rbind (unión cómo filas) de la siguiente forma:

vec1 <- c(1:5)
vec2 <- c(10:15)
vec3 <- c(20:25)
vec4 <- c(35:40)

matrix1 <- cbind(vec1, vec2, vec3,vec4)
matrix1
##      vec1 vec2 vec3 vec4
## [1,]    1   10   20   35
## [2,]    2   11   21   36
## [3,]    3   12   22   37
## [4,]    4   13   23   38
## [5,]    5   14   24   39
## [6,]    1   15   25   40
matrix2<-rbind(vec1, vec2, vec3, vec4)
matrix2
##      [,1] [,2] [,3] [,4] [,5] [,6]
## vec1    1    2    3    4    5    1
## vec2   10   11   12   13   14   15
## vec3   20   21   22   23   24   25
## vec4   35   36   37   38   39   40

Como puedes observar estas funciones nos son muy útiles y permiten realizar tareas puntuales.

Nota: Con las matrices también puedes realizar operaciones aritméticas.

matrix1 + 1
##      vec1 vec2 vec3 vec4
## [1,]    2   11   21   36
## [2,]    3   12   22   37
## [3,]    4   13   23   38
## [4,]    5   14   24   39
## [5,]    6   15   25   40
## [6,]    2   16   26   41
matrix1 * 2
##      vec1 vec2 vec3 vec4
## [1,]    2   20   40   70
## [2,]    4   22   42   72
## [3,]    6   24   44   74
## [4,]    8   26   46   76
## [5,]   10   28   48   78
## [6,]    2   30   50   80
matrix2 ^ 3
##       [,1]  [,2]  [,3]  [,4]  [,5]  [,6]
## vec1     1     8    27    64   125     1
## vec2  1000  1331  1728  2197  2744  3375
## vec3  8000  9261 10648 12167 13824 15625
## vec4 42875 46656 50653 54872 59319 64000

Como puedes notar la operación aritmética se realiza para cada uno de los datos de la matriz

Ahora veras la estructura de datos realmente más usada por nosotros en biología, las data frames. Pero… ¿Por qué es la más usada? Es la más usada, por que es la estructura que más se adapta a nuestras necesidades; además, de que es la forma en la que nosotros guardamos nuestro datos en excel y posteriormente cargamos generalmente en archivo .csv

Generalmente las filas en una data frame representa individuos u observaciones y las columnas representan los atributos, rasgos o variables.

¿Cómo luce una data frame?

La data frame iris que hemos estado utilizando, es una clara muestra de la organización y de los tipos de datos que puede contener una data frame.

Pero, ¿Cómo puedo crear una data frame en RStudio?

De forma rápida y sencilla, utilizaremos la función data.frame, en la cual podemos ingresar una serie de vectores que compondrán nuestro data frame, en el siguiente ejemplo ingresaremos 4 vectores con 4 clases de datos diferentes, esta es una de la ventajas de un data frame, podemos utilizar distintos tipos de datos.

Atención, atención!!!

Recordemos que los data frames requieren que las variables sean de la misma longitud. Por este motivo, tenemos que asegurarnos que el número de argumentos pasados a cada vector sean los mismos
mi_df <- data.frame(
  "entero" = 1:4, 
  "factor" = c("a", "b", "c", "d"), #  Observa que los caracteres deben estar entre ""
  "numero" = c(1.2, 3.4, 4.5, 5.6),
  "cadena" = as.character(c("a", "b", "c", "d")))
  
mi_df  
##   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

Así podemos ver que nuestro data frame ha sido creado exitosamente, nuevamente te invitamos a que juegues con estas funciones y te vuelvas más amigos de ellas.

Finalmente podemos usar la función str() para conocer la estructura de nuestros datos en un data frame, como podemos ver a continuación

str(mi_df)
## 'data.frame':    4 obs. of  4 variables:
##  $ entero: int  1 2 3 4
##  $ factor: chr  "a" "b" "c" "d"
##  $ numero: num  1.2 3.4 4.5 5.6
##  $ cadena: chr  "a" "b" "c" "d"

Ahora puedes observar la estructura de cada uno de nuestros datos, 4 observaciones de 4 variables, en la que nos especifica el tipo de dato de cada columna o variable.

Listas

Para finalizar nuestro post nutritivo del día de hoy, hablaremos de las listas, las cuales 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. Así podemos crear listas que contengan datos atómicos, vectores, matrices, arrays, data frames, así el largo de una lista es igual al número de elementos que contiene, sin importar de qué tipo o clase sean

Para crear una lista usamos 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, como observamos a continuación:

mi_vector <- 1:10
mi_matriz <- matrix(1:4, nrow = 2)
mi_df     <- data.frame("num" = 1:3, "letra" = c("a", "b", "c"))

mi_lista <- list("un_vector" = mi_vector, "una_matriz" = mi_matriz, "un_df" = mi_df)

mi_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 letra
## 1   1     a
## 2   2     b
## 3   3     c

Como podemos observar tenemos nuestros datos ingresados en nuestra lista y nos muestra su organización. Ahora procederemos a llamar un único elemento de nuestra lista, esto lo realizaremos ingresando el nombre de la lista creada y enseguida digitamos el operador $ (Signo dolar), como lo haremos en el siguiente código

mi_lista$un_vector 
##  [1]  1  2  3  4  5  6  7  8  9 10
# Llamamos al elemento "un_vector"

Atención, atención!!!

Pa´tener en cuenta: no es posible vectorizar operaciones aritméticas usando una lista!

Resumen

Listo!!!

Hemos finalizado este interesante y nutritivo post, el cual estuvo lleno de muchas cosas pa’ aprender y muchas otras pa’ digerir, pasamos por un breve aprendizaje sobre la exploración de datos (el cual trataremos más a fondo, en nuestras próximas entregas), hasta toda la información sobre la estructura y tipos de datos, ya sabes que hay datos tipos núméricos, caracteres, entre otros, y su organización como los vectores, data frames y las listas.

Con esta información esperamos que vayas conociendo de mejor manera tus datos y como R nos ayuda a tratarlos. No temas e intenta jugar con las funciones y dataframes que R nos proporciona, no importa que vayas teniendo errores, es normal, todos pasamos por estas y si necesitas algo, aquí estaremos!!!





Bibliografía:

Recuerda que todos nuestros códigos están almacenados en GitHub