Manual Introductorio a R
¿Qué es R?
R
es una plataforma para el análisis y graficación de datos. R
utiliza como base el lenguaje S
, desarrollado por John Chambers y colaboradores (Becker et al., 1988; Chambers and Hastie, 1992; Chambers et al., 1998) en los Laboratorios Bell (anteriormente AT&T, ahora pertenece a Lucent Technologies) a inicios de los años 1960s. El lenguaje S
fue diseñado y desarrollado como un lenguaje de programación para realizar funciones de análisis de datos.
El desarrollo del sistema R
para estadística computacional esta influenciado por la idea de “fuentes de libre acceso”: Las funciones base de R
y un gran número de contribuciones (extensiones) están disponibles bajo los términos de Fundación de Software Libre. Esta licencia tiene dos implicaciones importantes para analistas de datos que trabajan con R
. Todos los códigos completos están disponibles y son de acceso libre para todos. Entonces cualquier persona puede examinar, editar y manipular el códido de acuerdo a sus necesidades. Esto ha hecho que R
se haya vuelta tan popular y flexible.
La distribución base de R
es mantenida por un pequeño grupo de estadísticos, denominados “R Development Core Team”. Una gran cantidad de funciones adicionales y extensiones han sido creadas y mantenidas por otras personas voluntarias que colaboran del proyecto R
.
Instalación de R / RStudio
La fuente principal de información acerca de este sistema se encuentra en el sitio web oficial del proyectoR
(R Project). RStudio
es un entorno de desarrollo integrado (IDE) para el lenguaje de programación R
, dedicado al análisis estadístico y gráficación. RStudio
tiene la misión de proporcionar el entorno informático estadístico R, el cual permite un análisis y desarrollo para que cualquiera pueda analizar los datos con R
.
En general, recomendamos utilizar la plataforma R
en conjunto con RStudio
, que es una plataforma dinámica y un poco más amigable mediante la cual podemos guardar nuestros códigos, ejecutar comandos y visualizar los resultados.
Para instalar R
y RStudio
podemos seguir los pasos en el siguiente enlace: (Instalación de R) o mediante el siguiente video:
Paquetes / librerías
La instalación de R
contiene varios paquetes o librerías asociadas. Algunas de ellas son parte de la instalación base, otras pueden ser descargadas por medio del portal CRAN
.
El portal CRAN
tiene acceso a +1000 paquetes para diferentes propósitos. Además, mucha gente continua actualizando y copilando paquetes específicos que también pueden ser accesados vía CRAN o por otros portales. R
viene pre-instalado con algunos paquetes “base” por lo que no es necesario tener cargados todos los paquetes existentes al mismo tiempo. Generalmente uno carga únicamente los paquetes que va ocupando en los distintos análisis.
Estos son algunos enlances en donde podemos accesar información de como instalar paquetes/librerías de R
, o de los paquetes disponibles:
Además, podemos instalar paquetes o librerías de forma automatizada usando el siguiente código en nuestra consola o editor de RStudio
(Fig. 1):
Figura 1. Esquema de paneles de RStudio
Una vez que tenemos instalado un paquete o librería, debemos cargarlo. El simple hecho de tener un paquete instalado no significa que ya el paquete es funcional dentro de nuestra plataforma de trabajo. Para esto, podemos utilizar R
podemos utilizar el siguiente código en nuestra consola o editor de RStudio
:
¿Cómo pedir ayuda en R?
R
tiene varias formas en las que podemos pedir ayuda. Lo más sencillo si estamos usando RStudio
es accesar la pestaña de ayuda. Ahí podemos introducir el nombre de una función o prueba estadística para poder tener más información. Desde la consola de comandos también podemos usar varias funciones para que pueden accesar la documentación dentro de los paquetes/librerías de R
.
Algunas de las funciones que podemos utilizar desde nuestra consola o editor de RStudio
son:
Documentación
Documentación adicional de R
está disponible de diferentes fuentes, incluyendo las siguientes:
Sesión de repaso
En esencia, R
| RStudio
funciona usando un modelo de pregunta-respuesta. Se introduce una línea con un comando (similar a realizar una pregunta) y luego se presiona “Enter” para generar una respuesta. Tanto R
como RStudio
realizan un proceso (en el fondo) en el que imprimen/presentan la información relevante, o puede pedir más información si hiciera falta. Cuando R
| RStudio
esta listo para recibir un comando, entonces imprimirá en la consola usando el siguiente símbolo >
.
Una de las funciones más simples en R
es introducir expresiones aritméticas, del mismo modo que lo hacemos en nuestras calculadoras o en hojas de Excel
, por ejemplo:
## [1] 5
## [1] 8
## [1] 25
## [1] 11
## [1] 16
## [1] 6
## [1] 3.141593
## [1] 2.718282
Si quisiéramos visualizar una secuencia de valores, por ejemplo de 3 a 107, podemos usar el siguiente comando:
## [1] 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
## [19] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
## [37] 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
## [55] 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
## [73] 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
## [91] 97 98 99 100 101 102 103 104 105 106 107
## [1] 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
## [19] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
## [37] 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
## [55] 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
## [73] 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
## [91] 97 98 99 100 101 102 103 104 105 106 107
## [1] 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
## [19] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
## [37] 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
## [55] 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
## [73] 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
## [91] 97 98 99 100 101 102 103 104 105 106 107
## [1] 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
## [19] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
## [37] 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
## [55] 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
## [73] 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
## [91] 97 98 99 100 101 102 103 104 105 106 107
## [1] 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43
## [20] 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81
## [39] 83 85 87 89 91 93 95 97 99 101 103 105 107
## [1] 7 12 17 22 27 32 37 42 47 52 57 62 67 72 77 82 87 92 97
## [20] 102 107
# Ahora generemos una secuencia de 7 a 107, cual tendrá una longitud de 10
seq(7, 107, length.out = 100)
## [1] 7.000000 8.010101 9.020202 10.030303 11.040404 12.050505
## [7] 13.060606 14.070707 15.080808 16.090909 17.101010 18.111111
## [13] 19.121212 20.131313 21.141414 22.151515 23.161616 24.171717
## [19] 25.181818 26.191919 27.202020 28.212121 29.222222 30.232323
## [25] 31.242424 32.252525 33.262626 34.272727 35.282828 36.292929
## [31] 37.303030 38.313131 39.323232 40.333333 41.343434 42.353535
## [37] 43.363636 44.373737 45.383838 46.393939 47.404040 48.414141
## [43] 49.424242 50.434343 51.444444 52.454545 53.464646 54.474747
## [49] 55.484848 56.494949 57.505051 58.515152 59.525253 60.535354
## [55] 61.545455 62.555556 63.565657 64.575758 65.585859 66.595960
## [61] 67.606061 68.616162 69.626263 70.636364 71.646465 72.656566
## [67] 73.666667 74.676768 75.686869 76.696970 77.707071 78.717172
## [73] 79.727273 80.737374 81.747475 82.757576 83.767677 84.777778
## [79] 85.787879 86.797980 87.808081 88.818182 89.828283 90.838384
## [85] 91.848485 92.858586 93.868687 94.878788 95.888889 96.898990
## [91] 97.909091 98.919192 99.929293 100.939394 101.949495 102.959596
## [97] 103.969697 104.979798 105.989899 107.000000
Si quisieramos repetir elementos, podríamos usar el siguiente comando:
## [1] 2 2 2
## [1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [1] 15.96872 15.96872 15.96872 15.96872 15.96872 15.96872
Objetos
Uno de los procedimientos más comunes en R
es el de guardar/almacenar/asignar valores a un objeto. Como cualquier otro lenguaje de computación, R
utiliza variables simbólicas para representar valores o resultados. Para esto se utiliza los caracteres <-
(esto también equivale al símbolo =
), los cuales se deben leer como un símbolo de igual. La flecha apunta a la variable, a la cual asignaremos el valor o conjunto de valores.
También es importante considerar que, aunque no vemos un valor inmediato en la pantalla, nuestro objeto contiene el valor asignado. Si queremos extraer este valor, solo debemos llamar a nuestro objeto. Por ejemplo, si quisiéramos asignar el valor de 10 a la variable “a”, entonces lo podemos expresar así:
## [1] 10
## [1] 20
## [1] 1100
Técnicamente R
es un lenguaje de expresión con una sintaxis muy simple. Sin embargo, este lenguaje es sensitivo a cambios de mayúscula. De modo que las variables A
y a
son distintas.
## Error in eval(expr, envir, enclos): object 'A' not found
## [1] 10
Para remover un objeto, podemos usar la función “rm(objeto)”.
Un objeto no necesariamente tiene que ser una letra. A veces para recordar una variable asignamos una abreviación que tenga alguna relación con algo que queremos recordar o que estamos haciendo. Por ejemplo:
## [1] 70.5
## [1] 65
## [1] 5.5
## [1] 4582.5
## [1] 9.991868e-119
Constantes especiales
Constantes especiales incluyen:
- NA para datos que no existen o no han sido definidos
- NULL para objetos en blanco
- Inf y -Inf para representar números infinitos positivos o negativos
- NaN para resultados que no pueden ser definidos de forma razonable
## [1] NA
## [1] TRUE
## numeric(0)
## [1] FALSE
## [1] TRUE
## [1] Inf
# ¿Es la variable "d" un objeto finito?
d <- 5 / 0 # Chequear si la expresión es finita
is.finite(d)
## [1] FALSE
## [1] NaN
## [1] TRUE
Vectores
Un vector es un conjunto de valores (números, caracteres, etc.) que podemos guardar dentro de un objeto o variable. Para asignar una serie de valores a un objeto, vamos a crear una variable usando la función de concatenar - c()
. Esta es una función genérica para combinar argumentos en una serie de datos única.
## [1] 1 5 11 33
## [1] 5 10 15 20 25 30 35 40 45 50
## [1] 2 224 446 668 890 1112 1334 1556 1778 2000
## [1] "a" "b" "c" "d"
## [1] "y" "nos" "dieron" "las" "diez" "y" "las" "once"
# Vector de caracteres complejo usando función "rep"
v6 <- c(rep("a", 5), rep("b", 10), rep("once", 20), rep("d", 50))
v6
## [1] "a" "a" "a" "a" "a" "b" "b" "b" "b" "b"
## [11] "b" "b" "b" "b" "b" "once" "once" "once" "once" "once"
## [21] "once" "once" "once" "once" "once" "once" "once" "once" "once" "once"
## [31] "once" "once" "once" "once" "once" "d" "d" "d" "d" "d"
## [41] "d" "d" "d" "d" "d" "d" "d" "d" "d" "d"
## [51] "d" "d" "d" "d" "d" "d" "d" "d" "d" "d"
## [61] "d" "d" "d" "d" "d" "d" "d" "d" "d" "d"
## [71] "d" "d" "d" "d" "d" "d" "d" "d" "d" "d"
## [81] "d" "d" "d" "d" "d"
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
## [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
## [20] "T"
# Combinar vectores de caracteres y números
v9 <- c(1, "b", 2, "d", 3, "z", 10, "alpha", 500, "tom", 1000)
v9
## [1] "1" "b" "2" "d" "3" "z" "10" "alpha" "500"
## [10] "tom" "1000"
# Combinar vectores de caracteres y números con funciones "seq" y "rep"
v10 <- c(seq(1, 355, l = 34), letters[4:15], rep(5, 10), LETTERS[15:20])
v10
## [1] "1" "11.7272727272727" "22.4545454545455" "33.1818181818182"
## [5] "43.9090909090909" "54.6363636363636" "65.3636363636364" "76.0909090909091"
## [9] "86.8181818181818" "97.5454545454545" "108.272727272727" "119"
## [13] "129.727272727273" "140.454545454545" "151.181818181818" "161.909090909091"
## [17] "172.636363636364" "183.363636363636" "194.090909090909" "204.818181818182"
## [21] "215.545454545455" "226.272727272727" "237" "247.727272727273"
## [25] "258.454545454545" "269.181818181818" "279.909090909091" "290.636363636364"
## [29] "301.363636363636" "312.090909090909" "322.818181818182" "333.545454545455"
## [33] "344.272727272727" "355" "d" "e"
## [37] "f" "g" "h" "i"
## [41] "j" "k" "l" "m"
## [45] "n" "o" "5" "5"
## [49] "5" "5" "5" "5"
## [53] "5" "5" "5" "5"
## [57] "O" "P" "Q" "R"
## [61] "S" "T"
## [1] TRUE TRUE FALSE TRUE TRUE FALSE FALSE FALSE FALSE
## [1] 1 5 11 33 5 10 15 20 25 30 35 40 45 50 2
## [16] 224 446 668 890 1112 1334 1556 1778 2000
Podemos manipular o seleccionar elementos específicos de un vector utilizando la función [ ]
sobre un índice. Entender esto será muy importante posteriormente cuando tratemos de analizar y manipular bases de datos más complejas.
## [1] 5
## [1] 25
## [1] "d"
## [1] "once"
## [1] "k"
¿Qué tal si quisieramos seleccionar el último elemento del vector v10
. Veremos una forma manual y otra mucho más rápida y automatizada, que utiliza la función length
.
***
## [1] "T"
## [1] 62
## [1] "T"
## [1] "T"
La función sample
nos permite “muestrear” un vector existente o un vector númerico para realizar una selección aleatoria. Por ejemplo, podemos crear un objeto o vector “v.nuevo” que contenga una secuencia de 100 números, iniciando en 1.3 y terminando en 1024, y muestrear de forma aleatoria 20 números de esa secuencia.
# Crear secuencia y depositarla en vector "v.nuevo"
v.nuevo <- seq(1.3, 1024, l = 100)
# Crear vector aleatorio con 20 elementos numéricos (replace = FALSE)
v.nuevo2a <- sample(v.nuevo, size = 20, replace = FALSE)
v.nuevo2a
## [1] 1013.66970 579.79697 796.73333 765.74242 683.10000 445.50303
## [7] 207.90606 993.00909 982.67879 652.10909 176.91515 517.81515
## [13] 538.47576 662.43939 827.72424 900.03636 466.16364 63.28182
## [19] 1003.33939 693.43030
# Crear vector aleatorio con 20 elementos numéricos (replace = TRUE)
v.nuevo2b <- sample(v.nuevo, size = 20, replace = FALSE)
v.nuevo2b
## [1] 827.72424 931.02727 73.61212 786.40303 776.07273 280.21818 249.22727
## [8] 734.75152 63.28182 125.26364 559.13636 1.30000 693.43030 548.80606
## [15] 807.06364 11.63030 414.51212 32.29091 600.45758 993.00909
## [1] 94.27273 548.80606 445.50303 290.54848 1.30000 528.14545 300.87879
## [8] 786.40303 941.35758 259.55758 858.71515 125.26364 879.37576 228.56667
## [15] 920.69697 590.12727 383.52121 352.53030 714.09091 166.58485
Ejercicios
- Crear un vector
v
que contenga la secuencia de 1 a 6 repetida 5 veces.
- Crear un vector
v
en donde se repita cada número de la secuencia de 25-250 tres veces.
- Crear un vector
v
que contenga 10 números aleatorios que varían entre -100 y 100. La secuencia de números no se pueden repetir.
- Crear un vector de caracteres llamado
v.car
que contenga la siguiente secuencia de palabras: “a”, “la”, “mayoria”, “de”, “las”, “personas”, “no”, “les”, “gusta”, “la”, “programacion”. Una vez creado el vectorv.car
, seleccione las palabras “a”, “las”, “personas”, “les”, “gusta”, y lo guarda en un nuevo vectorv.car2
.
- Cree un vector
v.nuevo
que contenga los vectoresv1
,v2
,v3
yv4
que fueron creados anteriormente.
- Utilice la función
seq
para crear un vectorv.seq
que contenga solo los elementos impares del vectorv10
, el cual fue creado anteriormente.
Operaciones con vectores
## [1] 8
## [1] 20
## [1] 2 7 14 37
## [1] 6 7 8 9
## [1] 2 4 6 8
## [1] 2 5 10 5
## [1] 10
## [1] 2.5
## [1] 1.290994
## [1] 0.9773111
Operadores lógicos
# Vector numérico
v1 <- c(2, 5, 11, 33, 4, 1050)
# Comparar cada elemento con el número 5, regresa un vector lógico
v1 > 5
## [1] FALSE FALSE TRUE TRUE FALSE TRUE
## [1] TRUE FALSE FALSE TRUE FALSE TRUE
## [1] FALSE TRUE TRUE FALSE TRUE FALSE
# Operador "OR" (regresa un vector lógico)
v.n <- (v1 > 5) | (v2 > 12)
# Operador "AND" (regresa vector lógico)
v.n2 <- (v1 > 5) & (v2 > 12)
# Doble operador "OR"; regresa un sólo valor lógico
(v1 > 5) || (v2 > 12)
## [1] FALSE
## [1] FALSE
## [1] TRUE
Selección con operadores lógicos
A continuación, vamos a usar lo que hemos aprendido para realizar selecciones usando operadores lógicos.
Ejemplo 1, usando vectores con caracteres.
# Vectores con caracteres
v1 <- c("juan", "Carlos", "mario", "elena", "Sofia")
v2 <- c("Juan", "Carlos", "victor", "elena", "Sofya")
# Determinar elementos de v1 y v2 que sean exactamente iguales
v1[v1 == v2]
## [1] "Carlos" "elena"
## [1] "Carlos" "elena"
## [1] "Carlos" "elena"
Ejemplo 2, usando vectores numéricos.
# Vectores numéricos
v1 <- c(22.3, 24, 21, 16, 28.6, 26.0, 23.3, 30.9, 28.7, 20.0, 23.4)
v2 <- sample(seq(16, 32, 0.4), 11)
# Identificar valores de ambos vectores que sean menores a 22
v1 < 22
## [1] FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
## [1] TRUE FALSE FALSE TRUE FALSE FALSE FALSE TRUE TRUE FALSE FALSE
## [1] 21 16 20
## [1] 20.4 17.6 21.2 16.8
Ejemplo 3, usando vectores lógicos.
# Vectores numéricos
v1 <- c("TRUE", "TRUE", "FALSE", "TRUE", "FALSE", "FALSE", "FALSE")
v2 <- c("TRUE", "FALSE", "TRUE", "TRUE", "FALSE", "TRUE", "FALSE")
# Seleccionar elementos que sean verdaderos o "TRUE
v1[v1 == TRUE]
## [1] "TRUE" "TRUE" "TRUE"
## [1] "TRUE" "TRUE" "TRUE" "TRUE"
Ejercicios
- Crear dos vectores, uno que represente el peso de un grupo de 10 hombres y otro que represente el peso de un grupo de 10 mujeres. Una vez que tengamos ambos vectores, vamos a determinar la diferencia entre el peso promedio de los hombres y las mujeres. Utilice las funciones
sample
yseq
para crear los vectores de 10 valores de los pesos para hombres y mujeres. Los pesos de hombres pueden oscilar entre 60-95 kg y los pesos de mujeres entre 50-80 kg. Nota: Los valores de cada vector no pueden repetirse.
- A partir de los vectores creados en el ejercicio anterior, seleccione: (i) los pesos de hombres que sean mayores a 75 kg, y (ii) los pesos de mujeres que sean menores a 75 kg. Guarde ambos resultados en un objeto llamado “v.sel1” y v.sel2", respectivamente.
Factores
Los factores se usan para almacenar datos categóricos. Por ejemplo, el color de los ojos, las provincias o estados de un país, las especies de mamíferos, etc.
# Vector
col.ojo1 <- c("café", "verde", "café", "azul", "azul", "verde")
# Factor
col.ojo2 <- factor(c("café", "verde", "café", "azul", "azul", "verde"))
# Niveles del factor
levels(col.ojo1)
## NULL
## [1] "azul" "café" "verde"
## [1] 3
## Warning: NAs introduced by coercion
## [1] NA NA NA NA NA NA
## [1] 2 3 2 1 1 3
## [1] "café" "verde" "café" "azul" "azul" "verde"
## [1] "café" "verde" "café" "azul" "azul" "verde"
Manipulación de datos: I parte
Una de las mejores herramientas y utilidades que tiene R
es poder accesar y manipular grandes bases de datos. Sin embargo, la manipulación de bases de datos puede resultar un poco compleja al inicio. Realizar operaciones sencillas requiere de práctica. Muchas personas se frustran mucho al inicio, ya que, para aprender este lenguaje, y sobre todo para ser muy fluido se debe practicar constantemente, y eso toma tiempo. Lo que hacíamos antes en programas como Excel se complica un poco cuando cambiamos a R
. Pocas veces vemos el gran valor que tiene R
al inicio, y continuamos nuestra dependencia de otros programas estadísticos y de graficación que nos resultan más amigables. Sin embargo, una vez que tenemos una buena base y fluidez, nos damos cuenta que en realidad hacer las cosas en R
es más rápido y sencillo. Este tipo de lenguajes de programación nos obligan a razonar mejor y resolver problemas más complejos.
Esta sección pretende darnos herramientas importantes para poder manipular elementos en R
. Por ejemplo, volviendo a nuestro pequeño set de datos de los pesos del grupo de hombres y mujeres, si yo quisiera comparar el peso específico de algunos hombres y mujeres del grupo, debo realizar operaciones que me permitan extraer ciertos valores.
# Vector de pesos
hombres <- sample(60:100, size = 10, replace = FALSE)
mujeres <- sample(40:80, size = 10, replace = FALSE)
# Seleccionar el segundo valor de peso de los hombres
hombres.sel <- hombres[2]
# Seleccionar quinto valor de peso de las mujeres
mujeres.sel <- mujeres[5]
# Diferencia (absoluta) entre las tallas de individuos seleccionados
peso.sel.dif <- abs(hombres.sel - mujeres.sel)
peso.sel.dif
## [1] 30
Matrices
Una matriz es un vector que tiene dos dimensiones. El tamaño de una matriz esta definida por el número de filas y columnas que posee.
# Crear una matriz de 5 columnas y 4 filas, con solo valores de 1s
m <- matrix(data = 1, nrow = 5, ncol = 4)
m <- matrix(1, 5, 4)
# Dimensiones
dim(m)
## [1] 5 4
# Crear una matriz al combinar vectores
c1 <- seq(1, 5, 1)
c2 <- 5:1
c3 <- 5:9
m1 <- cbind(c1, c2, c3)
m2 <- rbind(1:5, 5:1, 5:9)
Seleccionar elementos de una matriz.
# Crear una matriz
m <- matrix(seq(from = 1, to = 35, l = 100), 10, 10)
# Seleccionar elemento de la fila 2, columna 3 de la matriz
m[2, 3]
## [1] 8.212121
## [1] 1.343434 4.777778 8.212121 11.646465 15.080808 18.515152 21.949495
## [8] 25.383838 28.818182 32.252525
## [1] 4.434343 4.777778 5.121212 5.464646 5.808081 6.151515 6.494949 6.838384
## [9] 7.181818 7.525253
# Crear submatriz: filas 1 y 2; columnas 4, 5 y 6
sel <- m[c(1,2), c(4, 5, 6)]
sel <- m[1:2, 4:6]
# Seleccionar todas las filas de la matriz "m" excepto la 1
m1 <- m[-1,]
# Seleccionar todas las columnas excepto la 3, 5, 6, 7 y 9
m2 <- m[, -c(3, 5:7, 9)]
Otros operadores
# Crear una matriz
m <- matrix(seq(from = 1, to = 35, l = 100), 10, 10)
# ¿Son todos los elementos en la fila 1 equivalentes a elementos de columna 1?
m[1, ] == m[, 1]
## [1] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# Matriz lógica, "TRUE" para elementos de "m" mayores a 15.
m1 <- m > 15
# Frecuencia de verdaderos y falsos de acuerdo a selección lógica
table(m > 15)
##
## FALSE TRUE
## 41 59
## [1] 59
## [1] 41
## [1] 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
## [20] 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
## [39] 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
## [58] 99 100
# Seleccionar solo elementos verdaderos, mayores a 15
m2 <- m[m > 15]
# Transponer matriz "m"
m3 <- t(m)
data.frame
Es una especie de lista que se utiliza para almacenar bases de datos. Piensen en filas como observaciones y columnas como variables. Cada columna es un vector o factor.
# Crear dataframe
df <- data.frame(ID = 1:8,
Nombre = c("Jorge", "Marta", "Isaac", "Tati",
"Luis", "Esteban", "Maria", "Laura"),
Mujer = c(FALSE, TRUE, FALSE, TRUE,
F, F, T, T),
Edad = c(28, 27, 44, 55, 23, 32, 16, 36),
Provincia = c(rep("San Jose", 3), rep("Guanacaste", 4), "Limon"))
# Resumir o visualizar base de datos
head(df) # visualizar primeras 6 filas
## ID Nombre Mujer Edad Provincia
## 1 1 Jorge FALSE 28 San Jose
## 2 2 Marta TRUE 27 San Jose
## 3 3 Isaac FALSE 44 San Jose
## 4 4 Tati TRUE 55 Guanacaste
## 5 5 Luis FALSE 23 Guanacaste
## 6 6 Esteban FALSE 32 Guanacaste
## ID Nombre Mujer Edad Provincia
## 3 3 Isaac FALSE 44 San Jose
## 4 4 Tati TRUE 55 Guanacaste
## 5 5 Luis FALSE 23 Guanacaste
## 6 6 Esteban FALSE 32 Guanacaste
## 7 7 Maria TRUE 16 Guanacaste
## 8 8 Laura TRUE 36 Limon
## 'data.frame': 8 obs. of 5 variables:
## $ ID : int 1 2 3 4 5 6 7 8
## $ Nombre : Factor w/ 8 levels "Esteban","Isaac",..: 3 7 2 8 5 1 6 4
## $ Mujer : logi FALSE TRUE FALSE TRUE FALSE FALSE ...
## $ Edad : num 28 27 44 55 23 32 16 36
## $ Provincia: Factor w/ 3 levels "Guanacaste","Limon",..: 3 3 3 1 1 1 1 2
## ID Nombre Mujer Edad Provincia
## Min. :1.00 Esteban:1 Mode :logical Min. :16.00 Guanacaste:4
## 1st Qu.:2.75 Isaac :1 FALSE:4 1st Qu.:26.00 Limon :1
## Median :4.50 Jorge :1 TRUE :4 Median :30.00 San Jose :3
## Mean :4.50 Laura :1 Mean :32.62
## 3rd Qu.:6.25 Luis :1 3rd Qu.:38.00
## Max. :8.00 Maria :1 Max. :55.00
## (Other):2
## [1] "ID" "Nombre" "Mujer" "Edad" "Provincia"
## [1] Jorge Marta Isaac Tati Luis Esteban Maria Laura
## Levels: Esteban Isaac Jorge Laura Luis Maria Marta Tati
## [1] Jorge Marta Isaac Tati Luis Esteban Maria Laura
## Levels: Esteban Isaac Jorge Laura Luis Maria Marta Tati
Alternativamente, podemos usar la opción stringsAsFactors = FALSE
para que los caracteres no sean considerados como factores
# Especificar que texto no es un factor, sino un caracter
df2 <- data.frame(ID = 1:8,
Nombre = c("Jorge", "Marta", "Isaac", "Tati",
"Luis", "Esteban", "Maria", "Laura"),
Mujer = c(FALSE, TRUE, FALSE, TRUE,
F, F, T, T),
Edad = c(28, 27, 44, 55, 23, 32, 16, 36),
Provincia = c(rep("San Jose", 3), rep("Guanacaste", 4), "Limon"),
stringsAsFactors = F)
str(df2)
## 'data.frame': 8 obs. of 5 variables:
## $ ID : int 1 2 3 4 5 6 7 8
## $ Nombre : chr "Jorge" "Marta" "Isaac" "Tati" ...
## $ Mujer : logi FALSE TRUE FALSE TRUE FALSE FALSE ...
## $ Edad : num 28 27 44 55 23 32 16 36
## $ Provincia: chr "San Jose" "San Jose" "San Jose" "Guanacaste" ...
## [1] "Jorge" "Marta" "Isaac" "Tati" "Luis" "Esteban" "Maria"
## [8] "Laura"
Si queremos cambiar el nombre de las variables en nuestra base de datos, debemos usar la función names
y proporcionar la lista de los nombres de las nuevas variables.
# Crear dataframe
df <- data.frame(ID = 1:8,
Nombre = c("Jorge", "Marta", "Isaac", "Tati",
"Luis", "Esteban", "Maria", "Laura"),
Mujer = c(FALSE, TRUE, FALSE, TRUE,
F, F, T, T),
Edad = c(28, 27, 44, 55, 23, 32, 16, 36),
Provincia = c(rep("San Jose", 3), rep("Guanacaste", 4), "Limon"))
# Cambiar nombres de las variables o columnas de un data.frame
names(df) <- c("id", "nombre", "mujer", "edad", "provincia")
names(df)[2] <- "estudiante"
colnames(df)
## [1] "id" "estudiante" "mujer" "edad" "provincia"
Accesar elementos del data.frame
# Crear dataframe
df <- data.frame(ID = 1:8,
Nombre = c("Jorge", "Marta", "Isaac", "Tati",
"Luis", "Esteban", "Maria", "Laura"),
Mujer = c(FALSE, TRUE, FALSE, TRUE,
F, F, T, T),
Edad = c(28, 27, 44, 55, 23, 32, 16, 36),
Provincia = c(rep("San Jose", 3), rep("Guanacaste", 4), "Limon"))
# Seleccionar toda la primera fila
df[1, ]
## ID Nombre Mujer Edad Provincia
## 1 1 Jorge FALSE 28 San Jose
## [1] 1 2 3 4 5 6 7 8
## [1] 28 27 44 55 23 32 16 36
## Mujer Edad
## 1 FALSE 28
## 2 TRUE 27
## ID Nombre Mujer Edad Provincia
## 1 1 Jorge FALSE 28 San Jose
## 3 3 Isaac FALSE 44 San Jose
## [1] Isaac Tati Esteban Laura
## Levels: Esteban Isaac Jorge Laura Luis Maria Marta Tati
## [1] 33.5
Data Frame vs. Matrix
Las bases de datos tipo data.frame
y matrix
tienen propiedades distintas. En una matrix
solo podemos tener valores numéricos o caracteres, mientras que en un data.frame
podemos combinar ambos. Esto facilita la selección de valores en un data.frame
. Por ejemplo, si quisiéramos escoger una única variable en nuestra data.frame
podemos usar el símbolo $
. Sin embargo, a pesar de estás diferencias, muchas de las formas de manipulación de datos son similares.
Para saber si nuestra base de datos/variable es una matriz o una data.frame podemos usar la función str
. Esta función proporciona información de la estructura de una variable. Por ejemplo, cuantos datos/observaciones existen, cuantas columnas/filas tiene la base de datos (o las dimensiones), el nombre de las columnas/filas, el tipo de variable que son (numéricas, de caracteres, factores, etc).
La función names
no funciona en bases de datos tipo matrix
. Para matriz debemos usar la función colnames
. A continuación, vamos a cambiar el nombre de las columnas en nuestra data frame y matriz de pesos de hombres y mujeres.
# Vector de pesos
hombres <- sample(60:100, size = 10, replace = FALSE)
mujeres <- sample(40:80, size = 10, replace = FALSE)
# Crear data.frame
db <- data.frame(hombres, mujeres)
db
## hombres mujeres
## 1 92 59
## 2 75 46
## 3 63 48
## 4 76 63
## 5 67 71
## 6 82 47
## 7 77 54
## 8 98 40
## 9 87 80
## 10 84 49
## 'data.frame': 10 obs. of 2 variables:
## $ hombres: int 92 75 63 76 67 82 77 98 87 84
## $ mujeres: int 59 46 48 63 71 47 54 40 80 49
## hombres mujeres
## [1,] 92 59
## [2,] 75 46
## [3,] 63 48
## [4,] 76 63
## [5,] 67 71
## [6,] 82 47
## [7,] 77 54
## [8,] 98 40
## [9,] 87 80
## [10,] 84 49
## int [1:10, 1:2] 92 75 63 76 67 82 77 98 87 84 ...
## - attr(*, "dimnames")=List of 2
## ..$ : NULL
## ..$ : chr [1:2] "hombres" "mujeres"
## [1] TRUE
## [1] FALSE
## [1] FALSE
## [1] TRUE
## [1] "H" "M"
## NULL
## [1] "hombres" "mujeres"
Ya hemos generado variables por separado y agrupado esas variables en una sola base de datos (data.frame
o matrix
). También sabemos cómo inspeccionar la estructura de las bases de datos y preguntarle a R
si eso que vemos es un data.frame
o una matrix
. Ahora es tiempo de ampliar nuestras habilidades en la manipulación de datos.
A continuación usaremos nuestra base de datos (“df”), la cual contenía información de varios estudiantes para responder algunos preguntas.
Ejercicios
- Usando el
data.frame
“df” que habiamos creado anteriormente, seleccione solo la columna con la información de provincia.
- Seleccione la provincia que esta en la cuarta fila
- Seleccione toda la información de Marta, Tati y Esteban
- Seleccione los estudiantes que tienen más de 30 años
- Seleccione los hombres que tienen más de 30 años
- Seleccione el nombre de los estudiantes (hombres) que tienen más de 30 años y guardar la selección en un objeto de caracteres
Ejemplo guiado
Ahora vamos a dar un paso más en complejidad que nos va ayudar también a mejorar nuestras habilidades para manipular datos. Vamos a generar una base de datos más compleja, y la vez aprenderemos algunas funciones básicas, pero mucha utilidad.
Pensemos en una base de datos en donde las variables no están en columnas sino en filas. De hecho, para muchos análisis estadísticos es necesario tener las variables agrupadas y no en modo “expandido”, como lo acabamos de ver en nuestro ejemplo pequeño con tiburones.
A continuación, vamos a generar un set de datos ficticio en el que se evalua el efecto de la concentración de un contaminante (mercurio Hg) en peces (machos y hembras) de 3 regiones de Costa Rica (Pacífico Norte, Pacífico Central y Pacífico Sur). Los niveles del Hg fueron determinados en una muestra aleatoria de peces recolectados en las 3 regiones (mg Hg / 100 ml de sangre).
La función runif
puede ser usada para generar una lista de valores aleatorios que representen los niveles de calcio en los pacientes. Entre los parámetros de esta función están n
, min
y max
, que representan el número de observaciones, el valor mínimo y el valor máximo, respectivamente.
# Generar lista de valores aleatorios que representen niveles de calcio
Hg <- rep(runif(n = 27, min = 15, max = 28), times = 3)
# Nombre de los sitios de muestreo
region <- rep(c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
times = 1000)
# Estadios de madurez sexual
sexo <- rep(c("macho", "hembra"), times = 1000)
# Chequear estructura
str(Hg)
## num [1:81] 17.1 22.3 22.6 23.7 25.6 ...
## chr [1:3000] "Pacifico Norte" "Pacifico Central" "Pacifico Sur" ...
## chr [1:2000] "macho" "hembra" "macho" "hembra" "macho" "hembra" "macho" ...
# Transformar variables a factores
region <- as.factor(region)
sexo <- as.factor(sexo)
levels(region)
## [1] "Pacifico Central" "Pacifico Norte" "Pacifico Sur"
## [1] "hembra" "macho"
## Factor w/ 3 levels "Pacifico Central",..: 2 1 3 2 1 3 2 1 3 2 ...
## Factor w/ 2 levels "hembra","macho": 2 1 2 1 2 1 2 1 2 1 ...
## [1] "Pacifico Central" "Pacifico Norte" "Pacifico Sur"
region <- factor(region,
levels = c("Pacifico Norte",
"Pacifico Central", "Pacifico Sur"))
# Niveles de factor estadios
sexo <- factor(sexo, levels = c("macho", "hembra"))
levels(region)
## [1] "Pacifico Norte" "Pacifico Central" "Pacifico Sur"
## [1] "macho" "hembra"
# Crear data frame
db <- data.frame(region = sample(region, 81),
sexo = sample(sexo, 81), Hg)
# Visualizar primeras 6 filas de base de datos
head(db, 5)
## region sexo Hg
## 1 Pacifico Norte hembra 17.06718
## 2 Pacifico Sur hembra 22.25200
## 3 Pacifico Central macho 22.58404
## 4 Pacifico Central hembra 23.70426
## 5 Pacifico Norte macho 25.55639
## region sexo Hg
## 76 Pacifico Central hembra 17.91686
## 77 Pacifico Central hembra 20.01691
## 78 Pacifico Sur macho 26.78062
## 79 Pacifico Sur hembra 21.92487
## 80 Pacifico Norte macho 17.92497
## 81 Pacifico Norte macho 24.87701
## region sexo Hg
## Pacifico Norte :24 macho :32 Min. :15.35
## Pacifico Central:34 hembra:49 1st Qu.:18.80
## Pacifico Sur :23 Median :22.14
## Mean :21.61
## 3rd Qu.:24.88
## Max. :26.78
## [1] 81 3
## 'data.frame': 81 obs. of 3 variables:
## $ region: Factor w/ 3 levels "Pacifico Norte",..: 1 3 2 2 1 2 1 2 3 3 ...
## $ sexo : Factor w/ 2 levels "macho","hembra": 2 2 1 2 1 1 2 1 2 2 ...
## $ Hg : num 17.1 22.3 22.6 23.7 25.6 ...
Cuando empezamos a trabajar con bases de datos más grandes es importante encontrar formas para resumir, extraer, visualizar y analizar ciertas relaciones. Además, es importante mantener el orden, ya que eso nos ayudará a entender mejor lo que estamos haciendo.
Podemos usar la función order
para ordenar nuestra base de datos de acuerdo a una o varias de las variables que tenemos. Por ejemplo,
# Generar lista de valores aleatorios que representen niveles de calcio
Hg <- rep(runif(n = 27, min = 15, max = 28), times = 3)
# Nombre de los sitios de muestreo
region <- factor(rep(c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
times = 1000), levels = c("Pacifico Norte",
"Pacifico Central", "Pacifico Sur"))
# Estadios de madurez sexual
sexo <- factor(rep(c("macho", "hembra"), times = 1000),
levels = c("macho", "hembra"))
# Crear data frame
db <- data.frame(region = sample(region, 81),
sexo = sample(sexo, 81), Hg)
# Ordenar base de datos por region
db.reg <- db[order(db$region), ]
# Ordenar base de datos por sexo
db.sexo <- db[order(db$sexo), ]
# Ordenar base de datos por concentración de Hg
db.Hg <- db[order(db$Hg, decreasing = TRUE), ]
db.Hg2 <- db[order(db$Hg, decreasing = T), ]
# Ordenar base de datos por region, sexo y concentración de Hg
db.ord <- db[order(db$region, db$sexo, db$Hg), ]
# Visualizar primeras filas
head(db.ord)
## region sexo Hg
## 52 Pacifico Norte macho 15.05806
## 47 Pacifico Norte macho 15.64251
## 74 Pacifico Norte macho 15.64251
## 69 Pacifico Norte macho 16.62664
## 78 Pacifico Norte macho 17.32341
## 1 Pacifico Norte macho 19.63615
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 15.06 18.69 20.78 20.85 23.52 27.26
## [1] 20.84602
## [1] 3.341794
# Seleccionar la variable mercurio y almacenarla en la variable "c.Hg"
c.Hg <- db.ord[, 3]
c.Hg <- db.ord$Hg
# Calcular el promedio de la concentración de Hg
mean(db.ord[, 3])
## [1] 20.84602
## [1] 20.84602
## [1] 20.84602
Manipular Datos: II Parte
Ahora que hemos cubierto algunos conceptos básicos que permiten generar, extraer, resumir y manipular bases de datos, el siguiente paso sería determinar como resumir una variable a través de otra. Por ejemplo, si quisiéramos ver cómo cambia el promedio o la desviación estándar de la concentración de Hg de acuerdo a la región y al sexo:
Función aggregate
Existen varias formas en las que podemos llegar a esto. Por ejemplo, una forma seria por medio de la función aggregate
,
# Crear data frame
db <- data.frame(region = sample(factor(rep(c("Pacifico Norte",
"Pacifico Central",
"Pacifico Sur"),
times = 1000),
levels = c("Pacifico Norte",
"Pacifico Central",
"Pacifico Sur")), 81),
sexo = sample(factor(rep(c("macho",
"hembra"),
times = 1000),
levels = c("macho",
"hembra")), 81),
Hg = rep(runif(n = 27, min = 15, max = 28), times = 3))
# Ordenar base de datos por region, sexo y concentración de Hg
db.ord <- db[order(db$region, db$sexo, db$Hg), ]
# Calcular el promedio de la variable mercurio según la región
aggregate(Hg ~ region, data = db.ord, FUN = mean)
## region Hg
## 1 Pacifico Norte 22.76981
## 2 Pacifico Central 22.51859
## 3 Pacifico Sur 21.81273
# Calcular el promedio de la variable mercurio según el sexo
aggregate(Hg ~ sexo, data = db.ord, FUN = mean)
## sexo Hg
## 1 macho 22.35812
## 2 hembra 22.57071
# Calcular la suma de la variable calcio según la región
aggregate(Hg ~ region, data = db.ord, FUN = sum)
## region Hg
## 1 Pacifico Norte 865.2528
## 2 Pacifico Central 472.8903
## 3 Pacifico Sur 479.8800
# Calcular la desviación estándar de la variable calcio según el sexo
aggregate(Hg ~ sexo, data = db.ord, FUN = sd)
## sexo Hg
## 1 macho 3.977783
## 2 hembra 3.434152
## sexo Hg
## 1 macho 48
## 2 hembra 33
## region Hg
## 1 Pacifico Norte 38
## 2 Pacifico Central 21
## 3 Pacifico Sur 22
# Calcular el promedio de Hg según región y sexo
dat.mean <- aggregate(Hg ~ region + sexo, data = db.ord, FUN = mean)
# Calcular la desviación estándar de Hg según región y sexo
dat.sd <- aggregate(Hg ~ region + sexo, data = db.ord, FUN = sd)
# Combinar el promedio +/- SD en una sola data.frame (Hint: cbind)
dat.mean.sd <- cbind(dat.mean, dat.sd$Hg)
dat.mean.sd <- cbind(dat.mean, dat.sd[, 3])
# Cambiar los nombres de las variables
names(dat.mean.sd)[4] <- "sd"
dat.mean.sd
## region sexo Hg sd
## 1 Pacifico Norte macho 22.81675 3.463302
## 2 Pacifico Central macho 22.79918 4.380810
## 3 Pacifico Sur macho 21.36320 4.400279
## 4 Pacifico Norte hembra 22.71183 2.816141
## 5 Pacifico Central hembra 22.14446 3.862092
## 6 Pacifico Sur hembra 22.77601 4.635076
## 'data.frame': 6 obs. of 4 variables:
## $ region: Factor w/ 3 levels "Pacifico Norte",..: 1 2 3 1 2 3
## $ sexo : Factor w/ 2 levels "macho","hembra": 1 1 1 2 2 2
## $ Hg : num 22.8 22.8 21.4 22.7 22.1 ...
## $ sd : num 3.46 4.38 4.4 2.82 3.86 ...
# ¿Cómo calcular error estandar por region y sexo?
dat.n <- aggregate(Hg ~ region + sexo, db.ord,
FUN = length)
dat.se <- dat.mean.sd$sd / sqrt(dat.n$Hg)
# Unir base de datos resumida con se
dat.final <- cbind(dat.mean.sd, dat.se)
names(dat.final)[5] <- c("se")
Agreguemos un grado de complejidad más antes de seguir adelante. Ya hemos visto un poco como manipular una base de datos más grande, como resumirla, como explorarla y como extraer filas, columnas o valores específicos. Ahora vamos a tomar la misma base de datos de nuestro ejemplo anterior y vamos a agregar una columna de valores más. En el siguiente ejemplo vamos a manipular una base de datos de mayor complejidad en donde existen dos o más variables numéricas que pueden ser de interés para un análisis estadístico.
Por ejemplo, que tal si además de medir la concentración de Hg de cada pez también medimos su peso. Por lo tanto, vamos a agregar una nueva variable “peso” (kg) a nuestra base de datos, y finalmente, generar una nueva base de datos o data.frame
con nuestras variables resumidas.
# Crear data frame
db <- data.frame(region = sample(factor(rep(c("Pacifico Norte",
"Pacifico Central",
"Pacifico Sur"),
times = 1000),
levels = c("Pacifico Norte",
"Pacifico Central",
"Pacifico Sur")), 81),
sexo = sample(factor(rep(c("macho",
"hembra"),
times = 1000),
levels = c("macho",
"hembra")), 81),
Hg = rep(runif(n = 27, min = 15, max = 28), times = 3))
head(db)
## region sexo Hg
## 1 Pacifico Norte hembra 23.23834
## 2 Pacifico Central hembra 27.00540
## 3 Pacifico Central hembra 24.17543
## 4 Pacifico Sur hembra 20.21509
## 5 Pacifico Norte hembra 22.72740
## 6 Pacifico Sur hembra 24.57354
## [1] 81 3
# Crear variable de peso del paciente
peso <- rnorm(n = length(db$Hg), mean = 75, sd = 4.5)
# Crear una nueva base de datos con la nueva variable
db.new <- cbind(db, peso)
head(db.new)
## region sexo Hg peso
## 1 Pacifico Norte hembra 23.23834 77.10608
## 2 Pacifico Central hembra 27.00540 76.50446
## 3 Pacifico Central hembra 24.17543 76.56021
## 4 Pacifico Sur hembra 20.21509 75.39833
## 5 Pacifico Norte hembra 22.72740 73.19990
## 6 Pacifico Sur hembra 24.57354 69.24594
# Calcular el promedio, desviación estándar y error estándar
dat.mean <- aggregate(cbind(Hg, peso) ~ region + sexo,
data = db.new, FUN = mean)
# Desviación estándar
dat.sd <- aggregate(cbind(Hg, peso) ~ region + sexo,
data = db.new, FUN = sd)
names(dat.sd)[3] <- c("sd.Hg")
names(dat.sd)[4] <- c("sd.peso")
# Número de observaciones
dat.N <- aggregate(cbind(Hg, peso) ~ region + sexo,
data = db.new, FUN = length)
# Calcular error estándar
se <- dat.sd[, c(3:4)] / sqrt(dat.N[, c(3:4)])
names(se) <- c("se.Hg", "se.peso")
# Guardar todas las estadísticas calculadas en una nueva base de datos
dat.resumidas <- cbind(dat.mean, dat.sd[, c(3:4)], se)
names(dat.resumidas)
## [1] "region" "sexo" "Hg" "peso" "sd.Hg" "sd.peso" "se.Hg"
## [8] "se.peso"
dat.resumidas2 <- dat.resumidas[ , c(1:3, 5, 7, 4, 6, 8)]
dat.resumidas2 <- dat.resumidas[ , c("region", "sexo", "Hg",
"sd.Hg", "se.Hg", "peso",
"sd.peso", "se.peso")]
dat.resumidas2
## region sexo Hg sd.Hg se.Hg peso sd.peso
## 1 Pacifico Norte macho 19.73525 3.381412 1.0195340 77.21625 2.234234
## 2 Pacifico Central macho 20.97377 2.984391 0.7705664 74.90433 5.247326
## 3 Pacifico Sur macho 22.96272 2.316457 0.6424695 73.00591 4.527967
## 4 Pacifico Norte hembra 22.07744 3.383095 1.0698287 76.71409 2.480108
## 5 Pacifico Central hembra 21.88548 3.250980 0.7269413 76.01414 4.679472
## 6 Pacifico Sur hembra 21.94270 3.076780 0.8881898 74.38153 3.552990
## se.peso
## 1 0.6736470
## 2 1.3548537
## 3 1.2558322
## 4 0.7842789
## 5 1.0463616
## 6 1.0256599
Ejercicios
- Crear un
data.frame
llamadoDF
que contenga 5 columnas y 10 filas. Las dos primeras columnas serán categóricas y tendran la siguiente información:col1
= secuencia de letras minúsculas;col2
= sequencia de letras mayúsculas. Las últimas dos columnas serán númericas y tendrán la siguiente información:col3
= secuencia númerica que inicie en 2 y termine en 20;col4
= sequencia que inicie en 5 y termine en 35, pero que vaya de 3 en 3 hasta completar la última fila.
- Utilice la base de datos
DF
para realizar lo siguiente: (i) cambie los nombres de la columna 1 a “región”, columna 2 a “país”, columna 3 a “indice” y columna 4 a “peso”; (ii) seleccione todas las filas de la columna 1 y la columna 4 y guardela en el objetoDF1
; (iii) seleccione todas las columnas de la base de datosDF
cuyo país sea “D”, “E”, “F” y “J”; seleccione todas las columnas y filas correspondientes cuyo índice sea menor a 11.
- Utilice la base de datos
DF
para realizar seleccionar todas las regiones y países cuyo índice es mayor a 5 y peso menor a 42.5.
- Crear una nueva columna y agregarla a la base de datos
DF
que contenga al menos 3 secuencias de 3 letras minúsculas repetidas, y llame a esa columna “grupo”. ¿Cuál es el peso promedio y desviación estándar de la nueva columna creada “grupo”? Crear un objetoresults
que contenga sus cálculos de promedio y desviación estándar.
Función tapply
La función tapply
pertenece a una familia muy versatil de funciones que le permitirá manipular, resumir y realizar una serie de cálculos rápidos sobre bases de datos de gran tamaño. Para más información de las aplicaciones de estás funciones ver los siguientes enlances:
# Crear data frame
db.new <- data.frame(region = sample(factor(rep(c("Pacifico Norte",
"Pacifico Central",
"Pacifico Sur"),
times = 1000),
levels = c("Pacifico Norte",
"Pacifico Central",
"Pacifico Sur")), 81),
sexo = sample(factor(rep(c("macho",
"hembra"),
times = 1000),
levels = c("macho",
"hembra")), 81),
Hg = rep(runif(n = 27, min = 15, max = 28), times = 3),
peso = rnorm(n = 81, mean = 75, sd = 4.5))
head(db.new)
## region sexo Hg peso
## 1 Pacifico Central macho 23.87140 77.61816
## 2 Pacifico Norte macho 26.27001 73.08006
## 3 Pacifico Central macho 25.84462 72.41930
## 4 Pacifico Norte hembra 22.60171 75.65895
## 5 Pacifico Norte hembra 26.68412 76.13696
## 6 Pacifico Central hembra 26.57985 70.92322
## [1] Pacifico Central Pacifico Norte Pacifico Central Pacifico Norte
## [5] Pacifico Norte Pacifico Central Pacifico Norte Pacifico Sur
## [9] Pacifico Norte Pacifico Norte Pacifico Central Pacifico Central
## [13] Pacifico Norte Pacifico Sur Pacifico Sur Pacifico Sur
## [17] Pacifico Norte Pacifico Central Pacifico Norte Pacifico Sur
## [21] Pacifico Norte Pacifico Norte Pacifico Sur Pacifico Sur
## [25] Pacifico Norte Pacifico Central Pacifico Norte Pacifico Central
## [29] Pacifico Norte Pacifico Central Pacifico Norte Pacifico Central
## [33] Pacifico Central Pacifico Central Pacifico Sur Pacifico Norte
## [37] Pacifico Norte Pacifico Norte Pacifico Central Pacifico Sur
## [41] Pacifico Central Pacifico Norte Pacifico Sur Pacifico Sur
## [45] Pacifico Central Pacifico Central Pacifico Norte Pacifico Central
## [49] Pacifico Norte Pacifico Sur Pacifico Sur Pacifico Central
## [53] Pacifico Central Pacifico Central Pacifico Central Pacifico Sur
## [57] Pacifico Sur Pacifico Norte Pacifico Sur Pacifico Central
## [61] Pacifico Sur Pacifico Norte Pacifico Norte Pacifico Sur
## [65] Pacifico Central Pacifico Norte Pacifico Central Pacifico Norte
## [69] Pacifico Norte Pacifico Central Pacifico Sur Pacifico Central
## [73] Pacifico Central Pacifico Norte Pacifico Norte Pacifico Sur
## [77] Pacifico Norte Pacifico Sur Pacifico Sur Pacifico Norte
## [81] Pacifico Sur
## Levels: Pacifico Norte Pacifico Central Pacifico Sur
## [1] 77.61816 73.08006 72.41930 75.65895 76.13696 70.92322 72.31661 74.53184
## [9] 75.26072 79.92675 74.48757 71.30234 71.02284 69.48550 67.59631 76.53221
## [17] 81.61067 69.01429 77.36908 67.30539 74.01884 72.83359 76.60385 73.42087
## [25] 78.13159 70.99660 70.60502 67.36047 69.96114 77.85341 69.49336 75.42436
## [33] 69.05122 72.74471 73.85989 75.00677 81.29919 72.84154 72.86026 78.07397
## [41] 74.95486 72.03337 67.93966 76.12088 71.08237 70.11333 80.80159 66.56980
## [49] 79.10284 74.39110 80.87685 80.52401 72.22725 71.73296 73.44102 77.50648
## [57] 72.28794 78.96923 76.74276 75.40874 68.37968 77.58424 71.59738 71.77554
## [65] 74.02544 76.69830 73.41894 78.55857 71.73117 76.01176 78.72339 72.80425
## [73] 79.12654 70.66596 68.19153 71.66374 74.56975 75.18645 78.33463 75.72490
## [81] 70.27302
# Calcular promedio y DE con tapply
dat.mean <- tapply(db.new$Hg,
list(db.new$region, db.new$sexo),
mean)
dat.mean
## macho hembra
## Pacifico Norte 20.90759 21.35300
## Pacifico Central 18.28596 22.59425
## Pacifico Sur 22.89831 22.34527
# Desviación estándar variable "Hg"
sd.mean <- tapply(db.new$Hg,
list(db.new$region, db.new$sexo),
sd)
sd.mean
## macho hembra
## Pacifico Norte 4.880898 3.970369
## Pacifico Central 4.000474 4.565868
## Pacifico Sur 4.804634 4.715683
# ¿Cómo calcular el promedio y desviación estándar simultáneamente con tapply?
# Solución 1
dat.summary1 <- data.frame(cbind(mean = tapply(db.new$Hg,
list(db.new$region,
db.new$sexo), mean),
sd = tapply(db.new$Hg,
list(db.new$region,
db.new$sexo), sd)))
names(dat.summary1) <- c("mean.Hg.H", "mean.Hg.M",
"sd.Hg.H", "sd.Hg.M")
# Solución 2
dat.summary2 <- data.frame(rbind(mean = tapply(db.new$Hg,
list(db.new$region,
db.new$sexo), mean),
sd = tapply(db.new$Hg,
list(db.new$region,
db.new$sexo), sd)))
rownames(dat.summary2) <- c("mean.P.Norte", "mean.P.Central", "mean.P.Sur",
"sd.P.Norte", "sd.P.Central", "sd.P.Sur")
Función ddply
La función ddply
es otra función versatil para manipular y resumir grandes bases de datos. Está función pertenece al paquete o librería plyr
, el cual deberá cargar antes de usarlo.
Para más información de las aplicaciones de está función ver los siguientes enlances:
library(plyr)
# Crear data frame
db.new <- data.frame(region = sample(factor(rep(c("Pacifico Norte",
"Pacifico Central",
"Pacifico Sur"),
times = 1000),
levels = c("Pacifico Norte",
"Pacifico Central",
"Pacifico Sur")), 81),
sexo = sample(factor(rep(c("macho",
"hembra"),
times = 1000),
levels = c("macho",
"hembra")), 81),
Hg = rep(runif(n = 27, min = 15, max = 28), times = 3),
peso = rnorm(n = 81, mean = 75, sd = 4.5))
# Calcular promedio de la concentración de Hg por región y sexo
d <- ddply(db.new, .(region, sexo),
plyr::summarise,
mean.Hg = round(mean(Hg), 2),
sd.Hg = round(sd(Hg), 2),
se.Hg = round(sd(Hg) / sqrt(length(Hg)), 2),
n.Hg = length(Hg),
mean.peso = round(mean(peso), 2),
sd.peso = round(sd(peso), 2),
se.peso = round(sd(peso) / sqrt(length(peso)), 2))
d
## region sexo mean.Hg sd.Hg se.Hg n.Hg mean.peso sd.peso se.peso
## 1 Pacifico Norte macho 21.41 3.15 0.81 15 74.94 4.96 1.28
## 2 Pacifico Norte hembra 21.50 3.28 1.09 9 74.00 3.08 1.03
## 3 Pacifico Central macho 21.11 3.31 0.85 15 75.52 4.96 1.28
## 4 Pacifico Central hembra 20.88 2.86 0.95 9 74.80 2.78 0.93
## 5 Pacifico Sur macho 21.80 3.73 0.88 18 74.39 5.24 1.24
## 6 Pacifico Sur hembra 22.56 3.61 0.93 15 74.51 3.52 0.91
Ya con los ejemplos que hemos cubierto tenemos un mejor conocimiento de algunas funciones útiles para manipular y resumir bases de datos. Estas son herramientas básicas, pero esenciales para poder enfrentarnos a bases de datos más complejos con muchas variables. Nuestro fin siempre debe ser tratar de resumir la información que tenemos para analizar y presentarla (por medio de cuadros y figuras) a una audiencia específica. En la siguiente sección cubriremos algunas funciones que nos permitirán visualizar bases de datos con diferente estructura.
Métodos de Visualización en R
En esta sección usaremos algunos de los ejemplos anteriores para hacer gráficos que nos permitan resumir y presentar visualmente la información. Volviendo al ejemplo de la concentración de calcio de pacientes con cáncer y el peso corporal, a continuación, vamos a visualizar un poco la distribución de los datos.
Histogramas
Una de las funciones más útiles e importantes cuando tenemos una variable numérica es la función hist
que genera un histograma de la distribución de los datos.
# Crear data frame
db.new <- data.frame(region = sample(factor(rep(c("Pacifico Norte",
"Pacifico Central",
"Pacifico Sur"),
times = 1000),
levels = c("Pacifico Norte",
"Pacifico Central",
"Pacifico Sur")), 81),
sexo = sample(factor(rep(c("macho",
"hembra"),
times = 1000),
levels = c("macho",
"hembra")), 81),
Hg = rep(runif(n = 27, min = 15, max = 28), times = 3),
peso = rnorm(n = 81, mean = 75, sd = 4.5))
# Histograma mercurio
hist(db.new$Hg)
Podemos accesar los comandos de ayuda para tener un mejor conocimiento de todos los parámetros asociados a la función hist
, la cual es una función compleja en donde se pueden especificar muchas opciones. Podemos manipular mejor esta función para mejorar la presentación de nuestros gráficos.
Por ejemplo, podemos cambiar el nombre a los ejes (axes
) y agregar un título.
hist(db.new$Hg, xlab = "Concentración de Hg (mg Hg/100 ml)",
ylab = "Frecuencia",
main = "Histograma de la concentración de Hg")
hist(db.new$peso, xlab = "Peso corporal (kg)",
ylab = "Frecuencia",
main = "Histograma del peso corporal")
hist(db.new$Hg, xlab = "Concentración de Hg (mg Hg/100 ml)",
ylab = "Frecuencia (%)",
main = "", freq = FALSE)
Podemos usar otras opciones con la función hist
para cambiar/mejorar aún más la presentación. Podemos hacer la letra más grande, usar expresiones en letra itálica o negrita, cambiar el color de las barras, etc.
Por ejemplo, las opciones cex.axis
y cex.lab
cambian el tamaño de los números en los ejes y del texto/nombre de los ejes, respectivamente. Valores más altos aumentan más el tamaño del texto. La expresión col
controla el color de las barras, mientras que la opción border
puede cambiar el color de los bordes de las barras. Para más información acerca de la gama de colores disponible en R y opciones de como especificar colores consulten los siguientes links:
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T, cex.axis = 0.8, cex.lab = 1.2)
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T, cex.axis = 0.8, cex.lab = 0.95)
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T,
cex.axis = 1.2, cex.lab = 1.2,
col = "#43B2FC85")
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T,
cex.axis = 1.2, cex.lab = 1.2,
col = "lightblue")
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T,
cex.axis = 1.2, cex.lab = 1.2,
col = "yellow")
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T, cex.axis = 1.2, cex.lab = 1.2,
col = "#1D70AF")
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T, cex.axis = 1.2, cex.lab = 1.2,
col = "#1D70AF90")
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T, cex.axis = 1.2, cex.lab = 1.2,
col = "#90EE90")
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T, cex.axis = 1.2, cex.lab = 1.2,
col = "#90EE90", border = "#43B2FC")
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T, cex.axis = 1.2, cex.lab = 1.2,
col ="black", border = "black", density = 10)
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T, cex.axis = 1.2, cex.lab = 1.2,
col = "blue", border = "red", density = 5, angle = 90)
Cuando presentamos o evaluamos nuestros datos mediante gráficos de histogramas a veces nos interesa también manipular el número de barras o categorías. Esto requiere un poco más de esfuerzo, pero una vez que entendemos el trasfondo, resulta muy sencillo.
Por ejemplo, podemos variar el número de categorías/barras mediante la opción “breaks”,
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T, cex.axis = 1.2, cex.lab = 1.2,
col ="grey90", border = "black",
breaks = 50)
hist(db.new$peso, xlab = "Peso (kg)",
ylab = "Frecuencia",
main = "Histograma del peso de peces",
freq = T, cex.axis = 1.2, cex.lab = 1.2,
col ="grey90", border = "black",
breaks = 15)
Boxplot-density plots
Otros gráficos que podemos hacer para evaluar la distribución de nuestros datos son gráficos de density
y boxplot
.
Por ejemplo, siguiendo nuestro ejemplo del tamaño de los parásitos podemos generar facílmente un gráfico de densidad y un boxplot de la siguiente forma:
plot(density(db.new$peso), ylab = "Frecuencia",
col = "#FFBC0050", main = "El titulo que quieren poner...",
lwd = 6)
plot(density(db.new$peso), xlab = "Frecuencia",
col = "blue", cex.axis = 1.2, cex.lab = 1.4,
main = "", lwd = 5, lty = 2)
## [1] "Pacifico Norte" "Pacifico Central" "Pacifico Sur"
col.g1 <- c("green", "blue", "grey80") # definir colores
col.g2 <- c("GREEN", "blue", "grey80") # definir colores
boxplot(db.new$peso ~ db.new$region,
xlab = "Frecuencia", col = col.g2, horizontal = T,
cex.axis = 1.2, cex.lab = 1.4,
main = "El mejor grafico del mundo")
boxplot(peso ~ region, data = db.new,
xlab = "Frecuencia", col = "yellow", horizontal = T,
cex.axis = 1.2, cex.lab = 1.4)
boxplot(peso ~ sexo, data = db.new,
xlab = "Frecuencia", col = "yellow", horizontal = T,
cex.axis = 1.2, cex.lab = 1.4,
names = c("ABB", "BAA"))
boxplot(peso ~ region, data = db.new,
xlab = "Frecuencia",
col = c("yellow", "blue", "forestgreen"),
horizontal = T,
cex.axis = 1.2, cex.lab = 1.4,
names = c("PN", "Central", "Sur"))
# Editar elementos del gráfico
boxplot(peso ~ region, data = db.new,
col = "gray95", ylim = c(60, 100), xlab = "", ylab = "",
xaxt = "n", yaxt = "n", frame.plot = F)
axis(1, at = seq(1, 3, by = 1),
labels = c("Pacifico Norte",
"Pacifico Central",
"Pacifico Sur"),
cex.axis = 1.2)
axis(2, at = seq(60, 100, by = 20), las = 1) # agregar axis 2 (las = 1, posici?n horizontal vs. las = 2, posición vertical)
# Crear títulos de ejes
mtext("Region", side = 1, line = 2.5, cex = 2.5)
mtext("Frecuencia", side = 2, line = 2.6, cex = 1.5)
box(bty = "l", lwd = 2)
R
también permite ordenar y visualizar varios gráficos en una misma página. Por ejemplo, si quisiéramos visualizar un gráfico de boxplot
que muestre el tamaño de los parásitos en un panel y el tamaño de los peces en otro podemos usar la función par
. Esta función permite manipular las opciones de los márgenes de página y del número de gráficos por página y las dimensiones del gráfico. Existen varios recursos disponibles en donde podemos obtener más información acerca de la función par
:
Por ahora veremos ejemplos específicos en donde solo vamos a controlar algunos de los parámetros más comunes: mar
. Este parámetro permite ajustar los márgenes de la página. Existen 4 márgenes que hay que especificar de acuerdo a su posición (abajo, izquierda, arriba y derecha) en la página. Entre más pequeño es el valor que se le asigna al margen, más cerca del borde (inferior, derecho, superior e izquierdo) de la página estará el gráfico.
# Establecer margenes
par(mfcol = c(1, 1))
par(mar = c(6, 5, 1.5, 0))
boxplot(peso ~ region, data = db.new,
col = "gray95",
xlab = "", ylab = "",
type = "n",xaxt = "n", yaxt = "n",
frame.plot = F, main = "Ejemplo 1")
axis(1, at = seq(1, 3, by = 1),
labels = c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
cex.axis = 1.2)
axis(2, las = 1)
mtext("Region", side = 1, line = 3, cex = 1.5)
mtext("Frecuencia", side = 2, line = 2.6, cex = 1.5)
box(bty="l",lwd=1.1)
# Establecer margenes
par(mfcol = c(1, 1))
par(mar = c(6, 5, 3, 3))
boxplot(peso ~ region, data = db.new, col = "gray95",
xlab = "", ylab = "",
type = "n", xaxt = "n", yaxt = "n", frame.plot = F,
main = "Ejemplo 2")
axis(1, at = seq(1, 3, 1),
labels = c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
cex.axis = 1.2)
axis(2, las = 1)
mtext("Region", side = 1, line = 3, cex = 1.5)
mtext("Frecuencia", side = 2, line = 2.6, cex = 1.5)
box(bty = "l",lwd = 1.1)
# Establecer margenes
par(mfcol = c(1, 1))
par(mar = c(8, 5, 8, 3))
boxplot(peso ~ region, data = db.new, col = "gray95",
xlab = "", ylab = "",
type = "n", xaxt= "n", yaxt = "n", frame.plot = F, main = "Ejemplo 3")
axis(1, at = seq(1, 3, 1),
labels = c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
cex.axis = 1.2)
axis(2, las = 1)
mtext("Region", side = 1, line = 3, cex = 1.5)
mtext("Frecuencia", side = 2, line = 2.6, cex = 1.5)
box(bty = "l",lwd = 1.1)
# Establecer margenes
par(mfcol = c(1, 1))
par(mar = c(5, 12, 5, 12))
boxplot(peso ~ region, data = db.new, col = "gray95",
xlab = "", ylab = "",
type = "n", xaxt = "n", yaxt = "n", frame.plot = F, main = "Ejemplo 4")
axis(1, at = seq(1, 3, 1),
labels = c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
cex.axis = 1.2)
axis(2, las = 1)
mtext("Region", side = 1, line = 3, cex = 1.5)
mtext("Frecuencia", side = 2, line = 2.6, cex = 1.5)
box(bty = "l",lwd = 1.1)
Los siguientes ejemplos nos ayudarán a entender como posicionar/colocar 2 o más figuras en una página. Para eso debemos ajustar los márgenes y también tenemos que dividir la página en filas y/o columnas. El parámetro que controla el número de figuras que vamos a visualizar en una página es par(mfcol)
o par(mfrow)
. El primero ordena las figuras de acuerdo a columnas, el segundo de acuerdo a filas.
# Establecer margenes
par(mfcol = c(2, 1))
par(mar = c(5, 6, 1.5, 4))
# Gráfico 1
boxplot(peso ~ region, data = db.new, xlab = "", ylab = "",
col = c("yellow", "red", "blue"),
type = "n", xaxt = "n", yaxt = "n", frame.plot = F)
axis(1, at = seq(1, 3, 1),
labels = c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
cex.axis = 1)
axis(2, las=1)
mtext("Region", side = 1, line = 3, cex = 1.25)
mtext("Frecuencia", side = 2, line = 2.6, cex = 1.25)
box(bty = "l", lwd = 1.1)
# Gráfico 2
boxplot(Hg ~ region, data = db.new, xlab = "", ylab = "",
col = c("gray95", "gray50", "gray25"),
type = "n", xaxt = "n", yaxt = "n", frame.plot = F)
axis(1, at = seq(1, 3, 1),
labels = c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
cex.axis = 1)
axis(2, las = 1)
mtext("Region", side = 1, line = 3, cex = 1.25)
mtext("Frecuencia", side = 2, line = 2.6, cex = 1.25)
box(bty = "l",lwd = 1.1)
# Ojo el cambio entre mfcol y mfrow!
par(mfrow = c(2, 2))
par(mar = c(5, 6, 1.5, 4))
# Gráfico 1
boxplot(peso ~ region, data = db.new, col = "gray95",
xlab = "", ylab = "",
type = "n", xaxt = "n", yaxt = "n", frame.plot = F)
axis(1, at = seq(1, 3, 1),
labels = c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
cex.axis = 1)
axis(2, las = 1)
mtext("Region", side = 1, line = 3, cex = 1.25)
mtext("Frecuencia", side = 2, line = 2.6, cex = 1.25)
box(bty = "l", lwd = 1.1)
# Gráfico 2
boxplot(Hg ~ region, data = db.new, col = "gray95",
xlab = "", ylab = "",
type = "n", xaxt = "n", yaxt = "n", frame.plot = F)
axis(1, at = seq(1, 3, 1),
labels = c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
cex.axis = 1)
axis(2, las = 1)
mtext("Region", side = 1, line = 3, cex = 1.25)
mtext("Frecuencia", side = 2, line = 2.6, cex = 1.25)
box(bty = "l",lwd = 1.1)
# Gráfico 3
hist(db.new$peso, xlab = "", ylab = "", col = "grey90",
xaxt = "n", yaxt = "n", main = "",
border = "black", breaks = 10)
# Sobreponer un gráfico sobre otro
par(new = T)
plot(density(db.new$peso), xaxt = "n", yaxt = "n",
main = "", col = "red", ylab = "", xlab = "",
lwd = 4, frame.plot = F)
axis(1, cex.axis = 1)
axis(2, las = 1)
mtext("Frecuencia", side = 1, line = 3, cex = 1.25)
mtext("Densidad", side = 2, line = 3, cex = 1.25)
box(bty = "l",lwd = 1.1)
# Gráfico 4
hist(db.new$Hg, xlab = "", ylab = "", col = "#FFBC00",
xaxt = "n", yaxt = "n", main = "",
border = "black", breaks = 10)
# Sobreponer un gráfico sobre otro
par(new = T)
plot(density(db.new$Hg), xaxt = "n", yaxt = "n",
main = "", col = "#003366", ylab = "", xlab = "",
lwd = 3, lty = 2, frame.plot = F)
axis(1, cex.axis = 1)
axis(2, las = 1)
mtext("Frecuencia", side = 1, line = 3, cex = 1.25)
mtext("Densidad", side = 2, line = 3, cex = 1.25)
box(bty = "l",lwd = 1.1)
Para terminar esta sección, veremos cómo podemos generar y exportar figuras de alta calidad usando R
. Este programa nos permite exportar figuras en múltiples formatos. A continuación, se presentarán dos formatos de alta resolución en los cuales podemos generar figuras para una publicación.
# Exportar gráfico en formato de PNG
png("Boxplot-Histograms por sitio.png", width = 10, height = 8,
units = "in", res = 600)
# Parámetros de los márgenes
par(mfrow = c(2, 2))
par(mar = c(3, 4, 2, 2), oma = c(3, 2, 0, 1))
# Gráfico 1
boxplot(peso ~ region, data = db.new, col = "gray95",
xlab = "", ylab = "",
type = "n", xaxt = "n", yaxt = "n", frame.plot = F)
axis(1, at = seq(1, 3, 1),
labels = c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
cex.axis = 1)
axis(2, las = 1)
mtext("Region", side = 1, line = 3, cex = 1.25)
mtext("Frecuencia", side = 2, line = 2.6, cex = 1.25)
box(bty = "l", lwd = 1.1)
# Gráfico 2
boxplot(peso ~ region, data = db.new, col = "gray95",
xlab = "", ylab = "",
type = "n", xaxt = "n", yaxt = "n", frame.plot = F)
axis(1, at = seq(1, 3, 1),
labels = c("Pacifico Norte", "Pacifico Central", "Pacifico Sur"),
cex.axis = 1)
axis(2, las = 1)
mtext("Region", side = 1, line = 3, cex = 1.25)
mtext("Frecuencia", side = 2, line = 2.6, cex = 1.25)
box(bty = "l",lwd = 1.1)
# Gráfico 3
hist(db.new$peso, col = "grey90",
xlab = "", ylab = "",
xaxt = "n", yaxt = "n", main = "",
border = "black", breaks = 10)
# Sobreponer un gráfico sobre otro
par(new = T)
plot(density(db.new$peso), xaxt = "n", yaxt = "n",
main = "", col = "red", ylab = "", xlab = "",
lwd = 3, frame.plot = F)
axis(1, cex.axis = 1)
axis(2, las = 1)
mtext("Frecuencia", side = 1, line = 3, cex = 1.25)
mtext("Densidad", side = 2, line = 3, cex = 1.25)
box(bty = "l",lwd = 1.1)
# Gráfico 4
hist(db.new$Hg, xlab = "", ylab = "", col = "#FFBC00",
xaxt = "n", yaxt = "n", main = "",
border = "black", breaks = 10)
# Sobreponer un gráfico sobre otro
par(new = T)
plot(density(db.new$Hg), xaxt = "n", yaxt = "n",
main = "", col = "#003366", ylab = "", xlab = "",
lwd = 4, lty = 2, frame.plot = F)
axis(1, cex.axis = 1)
axis(2, las = 1)
mtext("Frecuencia", side = 1, line = 3, cex = 1.25)
mtext("Densidad", side = 2, line = 3, cex = 1.25)
box(bty = "l",lwd = 1.1)
# Cerrar "device"
dev.off()
Otros formato muy empleado es el siguiente:
### Formato de PNG ###
png("Boxplot-sitios2.png", width = 8.5, height = 11, units = "in", res = 600)
# Insertar código del gráfico aquí!
dev.off()
Importar y Exportar Datos
En esta sección se pretende mostrar algunas formas en las que podemos importar y exportar datos en R
. Muchas veces tenemos bases de datos externas en diversos formatos (csv, txt, excel, SPSS, etc.) y nos interesa poder accesar a esas bases de datos desde R
. Los formatos csv
y txt
son de los más usados. Estos formatos también pueden ser accesados desde programas como Excel
, lo cual permite cierta manipulación y editaje previo a ser importados en R
.
Especificar folder de trabajo
Cuando empezamos a trabajar en R
lo primero de que deberíamos hacer es especificar el folder de trabajo. Este sería el folder donde vamos a guardar todos nuestros resultados, donde vamos a importar/exportar archivos o simplemente el folder que estará unido a nuestro código de trabajo.
Para eso debemos usar los siguientes comandos:
# Especificar el folder de trabajo
setwd(choose.dir())
# Especificar folder de trabajo
wd <- getwd()
setwd(wd)
A continuación, emplearemos tres métodos para importar el set de datos “peakquinn” que fue guardado en el directorio de trabajo con los formatos csv
, txt
y xls
. NOTA: Es muy importante que sepamos cual es el directorio en donde estamos trabando y que tengamos nuestros archivos (“bases de datos”) en ese mismo directorio. Para eso podemos usar la función getwd()
que significa “get the working directory”.
# Especificar el folder de trabajo
setwd("/Users/macbookpro/Dropbox/Curso R-abierto/Manuales del Curso/Manual Introductorio/")
# Seleccionar folder de trabajo
wd <- getwd()
setwd(wd)
# Importar datos - formato "csv"
inv <- read.csv("peakquinn.csv", header = T, sep = ",")
# Resumir base de datos
head(inv)
str(inv)
summary(inv)
Ahora vamos a importar la misma base de datos que fue guardada como txt
.
# Seleccionar folder de trabajo
setwd(wd)
# Importar datos - formato "txt"
inv.txt <- read.table("peakquinn.txt", header = T, sep = "")
head(inv.txt)
str(inv.txt)
# Seleccionar las primeras 10 filas de la base de datos
inv.sel <- inv.txt[1:10, ]
inv.sel
A continuación vamos a importar un set de datos que guardamos en excel. Para esto vamos a usar la función read_excel
del paquete readxl
.
# Seleccionar folder de trabajo
setwd(wd)
# Instalar/cargar librerías o paquetes
library(readxl)
# Importar datos - formato "excel"
inv.excel <- read_excel("peakquinn.xlsx", sheet = 1)
head(inv)
str(inv)
Por último, vamos a usar un método más dinámico para importar datos. Este método nos permite seleccionar manualmente el archivo que queremos importar.
Para exportar nuestras bases de datos y/o resultados como archivos csv
o txt
podemos usar los siguientes códigos:
# Especificar el folder de trabajo
setwd("/Users/macbookpro/Dropbox/Curso R-abierto/Manuales del Curso/Manual Introductorio/")
wd <- getwd()
setwd(wd)
# Importar datos - formato "csv"
escuelas <- read.csv("escuelas.csv", header = T, sep = ",")
# Resumir base de datos
head(escuelas)
## location school type subtype zone year year2 score
## 1 Cartago Anglo americano Privado ACAD.DIUR. URB 10 10 9.50
## 2 Cartago Anglo americano Privado ACAD.DIUR. URB 10 10 4.00
## 3 Cartago Anglo americano Privado ACAD.DIUR. URB 11 11 7.00
## 4 Cartago Anglo americano Privado ACAD.DIUR. URB 11 11 1.00
## 5 Cartago Anglo americano Privado ACAD.DIUR. URB 11 11 7.75
## 6 Cartago Anglo americano Privado ACAD.DIUR. URB 11 11 6.25
## 'data.frame': 859 obs. of 8 variables:
## $ location: Factor w/ 12 levels "Alajuela","C. Neily",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ school : Factor w/ 118 levels "Anglo americano",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ type : Factor w/ 3 levels "Cientifico","Privado",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ subtype : Factor w/ 3 levels "","ACAD.DIUR.",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ zone : Factor w/ 3 levels "NR","RUR","URB": 3 3 3 3 3 3 3 3 3 3 ...
## $ year : int 10 10 11 11 11 11 11 11 11 11 ...
## $ year2 : int 10 10 11 11 11 11 11 11 11 11 ...
## $ score : num 9.5 4 7 1 7.75 6.25 6.75 6.5 3.5 3 ...
## location school
## San Jose:131 Colegio Cientifico Sede Guanacaste : 39
## Heredia :107 Cientifico Costarricense Sede Atlantico : 38
## Cartago : 94 NR : 31
## Liberia : 93 Colegio Marista : 18
## Alajuela: 76 Colegio Cientifico Costarricense Sede Puntarenas: 17
## Limon : 71 Colegio Cientifico de Alajuela : 17
## (Other) :287 (Other) :699
## type subtype zone year year2
## Cientifico:174 : 23 NR : 31 Min. : 7.00 Min. : 8.0
## Privado :349 ACAD.DIUR. :792 RUR:155 1st Qu.:10.00 1st Qu.:10.0
## Publico :336 T\x83C.DIUR.: 44 URB:673 Median :10.00 Median :10.0
## Mean :10.11 Mean :10.1
## 3rd Qu.:11.00 3rd Qu.:11.0
## Max. :12.00 Max. :11.0
##
## score
## Min. : 0.000
## 1st Qu.: 4.500
## Median : 6.500
## Mean : 6.432
## 3rd Qu.: 8.500
## Max. :12.500
##
## [1] 859 8
# Seleccionar sola los colegios cientificos
cientificos <- escuelas[escuelas$type == "Cientifico", ]
head(cientificos)
## location school type subtype zone year
## 61 Cartago Cientifico Costarricense Cartago Cientifico ACAD.DIUR. URB 10
## 62 Cartago Cientifico Costarricense Cartago Cientifico ACAD.DIUR. URB 10
## 63 Cartago Cientifico Costarricense Cartago Cientifico ACAD.DIUR. URB 10
## 64 Cartago Cientifico Costarricense Cartago Cientifico ACAD.DIUR. URB 11
## 65 Cartago Cientifico Costarricense Cartago Cientifico ACAD.DIUR. URB 11
## 66 Cartago Cientifico Costarricense Cartago Cientifico ACAD.DIUR. URB 11
## year2 score
## 61 10 9.00
## 62 10 11.00
## 63 10 6.75
## 64 11 11.25
## 65 11 4.50
## 66 11 9.50
## 'data.frame': 174 obs. of 8 variables:
## $ location: Factor w/ 12 levels "Alajuela","C. Neily",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ school : Factor w/ 118 levels "Anglo americano",..: 9 9 9 9 9 9 9 9 9 9 ...
## $ type : Factor w/ 3 levels "Cientifico","Privado",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ subtype : Factor w/ 3 levels "","ACAD.DIUR.",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ zone : Factor w/ 3 levels "NR","RUR","URB": 3 3 3 3 3 3 3 3 3 3 ...
## $ year : int 10 10 10 11 11 11 11 11 11 11 ...
## $ year2 : int 10 10 10 11 11 11 11 11 11 11 ...
## $ score : num 9 11 6.75 11.25 4.5 ...
## [1] 174 8
# Remover los niveles vacios de un factor
cientificos$type <- factor(cientificos$type)
str(cientificos)
## 'data.frame': 174 obs. of 8 variables:
## $ location: Factor w/ 12 levels "Alajuela","C. Neily",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ school : Factor w/ 118 levels "Anglo americano",..: 9 9 9 9 9 9 9 9 9 9 ...
## $ type : Factor w/ 1 level "Cientifico": 1 1 1 1 1 1 1 1 1 1 ...
## $ subtype : Factor w/ 3 levels "","ACAD.DIUR.",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ zone : Factor w/ 3 levels "NR","RUR","URB": 3 3 3 3 3 3 3 3 3 3 ...
## $ year : int 10 10 10 11 11 11 11 11 11 11 ...
## $ year2 : int 10 10 10 11 11 11 11 11 11 11 ...
## $ score : num 9 11 6.75 11.25 4.5 ...
# Seleccionar colegios privados, y solo el año 11
priv.11 <- escuelas[escuelas$type == "Privado" &
escuelas$year2 == 11, ]
# Exportar base de colegios científicos y colegios privados (11 año)
name1 <- "cientificos.csv"
write.csv(cientificos, file = name1, row.names = FALSE)
name2 <- "priv11.txt"
write.table(priv.11, file = name2, row.names = FALSE, sep="\t")
Ejercicios
- Importe la base de datos
temp.co2.csv
y realice un gráfico tipoboxplot
en donde la temperatura este en el ejex
y el CO2 producido en el ejey
. Nota: Debe tratar la temperatura como un factor con varios niveles.
R/ (no mirar…)
- Importe la base de datos
escuelas.csv
y realice un gráfico tipoboxplot
para examinar la relación entre el tipo de colegio (“type” = privado, cientifico y publico) y la evaluación (“score”). Nota: Coloree cada nivel del factor tipo de colegio con un color distinto.
R/ (no mirar…)
Graficación: II parte
En esta sección continuaremos abordando el tema de graficación, y mostraremos otros ejemplos en los que podemos generar gráficos más complejos en R
. A continuación, discutiremos gráficos de puntos (scatter plots), gráficos circulares (“pie charts”) y gráficos de barras (barplot). Estos gráficos usan las funciones plot
, pie
y barplot
, respectivamente. Estos gráficos se usan mucho cuando queremos mostrar visualmente los resultados de pruebas estadísticas univariadas como Regresión (simple y múltiple), Análisis de Varianza (ANDEVA), “General Linear Models (GLMs)”, “Generalized Linear Models (GLMM)”, etc. Muchas de las opciones de las funciones para graficar en R
son similares, sin embargo, también veremos algunas opciones o parámetros que son específicas de cada una de las funciones.
Gráficos de puntos
El siguiente ejemplo proviene de un set de datos de Peake and Quinn (1993), en el cual los autores querían investigar la relación entre el número de invertebrados que se encontraban en parches de mejillones en una zona rocosa intermareal y el área de esos parches (mm2).
Para examinar la relación entre el número de invertebrados y el área de los parches de mejillones podemos usar un gráfico scatterplot
con la función plot
. Para esta función tenemos que especificar los valores/coordenadas de x
y y
.
Primero, vamos a importar nuestra base de datos “peakquinn.csv”:
# Especificar el folder de trabajo
setwd("/Users/macbookpro/Dropbox/Curso R-abierto/Manuales del Curso/Manual Introductorio/")
wd <- getwd()
setwd(wd)
# Importar base de datos
peakquinn <- read.csv("peakquinn.csv", header = T, sep = ",")
# Gráfico de puntos (x/y)
dev.off()
## null device
## 1
# Establecer márgenes
par(mfrow = c(1, 1))
# Gráfico 1
plot(x = peakquinn$AREA, y = peakquinn$INDIV)
# Gráfico 2
plot(peakquinn$AREA, peakquinn$INDIV)
# Gráfico 3
plot(INDIV ~ AREA, peakquinn)
Cuando usamos la función plot
podemos especificar diferentes tipos de gráficos mediante el parámetro type
. Para más información acerca de la función plot
y los tipos de gráficos asociados consultar la documentación en R
. Por ejemplo,
# Especificar el folder de trabajo
setwd("/Users/macbookpro/Dropbox/Curso R-abierto/Manuales del Curso/Manual Introductorio/")
wd <- getwd()
setwd(wd)
# Importar base de datos
peakquinn <- read.csv("peakquinn.csv", header = T, sep = ",")
# Gráfico 4
plot(INDIV ~ AREA, data = peakquinn, type = "l", main = "Gráfico 1")
A través de R
podemos editar/modificar todas las opciones de un gráfico para mejorar la presentación. Esto nos da un control muy grande cuando queremos personalizar uno o varios gráficos. Por ejemplo,
# Especificar el folder de trabajo
setwd("/Users/macbookpro/Dropbox/Curso R-abierto/Manuales del Curso/Manual Introductorio/")
wd <- getwd()
setwd(wd)
# Importar base de datos
peakquinn <- read.csv("peakquinn.csv", header = T, sep = ",")
# Base de datos
head(peakquinn)
## AREA INDIV
## 1 516.00 18
## 2 469.06 60
## 3 462.25 57
## 4 938.60 100
## 5 1357.15 48
## 6 1773.66 118
# Seleccionar un subset aleatorio de ambas variables
area1 <- sample(peakquinn$AREA, size = (length(peakquinn$AREA)-10))
ind1 <- sample(peakquinn$INDIV, size = (length(peakquinn$INDIV)-10))
# Gráfico
par(mar = c(5, 5, 3, 2))
plot(INDIV ~ AREA, data = peakquinn,
ann = FALSE, axes = F, type = "n")
points(INDIV ~ AREA, data = peakquinn, pch = 21,
col = "blue", bg = "yellow", cex = 3, lwd = 1.8)
points(ind1 ~ area1, pch = 22,
col = "black", bg = "#ff000090",cex = 3)
axis(1)
mtext(expression(paste("Area del parche (",mm^2,")")), 1,
line = 3, cex = 1.2)
axis(2, las = 1)
mtext("Número de invertebrados", 2, line = 3.5, cex = 1.2)
box(bty = "l", lwd = 2)
Sospechamos que una transformación logarítmica podría mejorar la relación lineal entre el número de invertebrados y el área del parche de mejillones. Por lo tanto, vamos a transformar ambas variables para ver si mejora esta relación.
# Especificar el folder de trabajo
setwd("/Users/macbookpro/Dropbox/Curso R-abierto/Manuales del Curso/Manual Introductorio/")
wd <- getwd()
setwd(wd)
# Importar base de datos
peakquinn <- read.csv("peakquinn.csv", header = T, sep = ",")
# Transformación logarítmica de ambas variables
logArea <- log(peakquinn$AREA)
logInd <- log (peakquinn$INDIV)
# Agregar variables trasformadas a la base de datos
head(peakquinn)
## AREA INDIV
## 1 516.00 18
## 2 469.06 60
## 3 462.25 57
## 4 938.60 100
## 5 1357.15 48
## 6 1773.66 118
peakquinn$logArea <- logArea
peakquinn$logInd <- logInd
peakquinn2 <- peakquinn[, c(1:4)]
peakquinn <- peakquinn2
head(peakquinn)
## AREA INDIV logArea logInd
## 1 516.00 18 6.246107 2.890372
## 2 469.06 60 6.150731 4.094345
## 3 462.25 57 6.136106 4.043051
## 4 938.60 100 6.844389 4.605170
## 5 1357.15 48 7.213142 3.871201
## 6 1773.66 118 7.480800 4.770685
# Graficar la relación de las variables transformadas
par(mar = c(5,5,3,2))
plot(logInd ~ logArea, data = peakquinn,
ann = F, axes = F, type = "n")
points(logInd ~ logArea, data = peakquinn, pch = 23,
col = "black", bg = "green",
cex = 2)
axis(1)
mtext(expression(paste("Log área (",mm^2,")", sep = "")), 1,
line = 3, cex = 1.2)
axis(2, las = 1)
mtext("Log Número de invertebrados", 2, line = 3.5, cex = 1.2)
box(bty = "l")
# Parámetros de los gráficos
par(mfrow = c(1, 2))
par(mar = c(5,5,5,1))
# Gráfico sin las variables transformación
plot(INDIV ~ AREA, data = peakquinn, ann = F, axes = F, type = "n")
points(INDIV ~ AREA, data = peakquinn, pch = 21,
col = "black", bg = "yellow",cex = 1.3)
axis(1)
mtext(expression(paste("Area del parche (",mm^2,")", sep = "")), 1,
line = 3, cex = 1)
axis(2,las = 1)
mtext("Número de invertebrados", 2, line = 3.5, cex = 1)
box(bty = "l")
### Graficar con las variables transformadas ###
plot(logInd ~ logArea, data = peakquinn, ann = F, axes = F, type = "n")
points(logInd ~ logArea, data = peakquinn, pch = 21,
col = "black", bg = "tomato",cex = 1.3)
axis(1)
mtext(expression(paste("Log Area (",mm^2,")", sep = "")), 1,
line = 3, cex = 1)
axis(2,las=1)
mtext("Log Número de invertebrados", 2, line = 3.5, cex = 1)
box(bty="l")
Gráficos circulares
El uso de gráficos circulares o pasteles es bastante común para resumir datos de porcentajes. A veces se presenta un gráfico circular para mostrar, por ejemplo, que en una muestra el 50% de la población son machos y el 50% hembras. En este caso realmente este es un gráfico multivariable que puede utilizarse para comparar diferencias o similitudes y realizar agrupamientos.
En R
podemos generar un gráfico circular con la función pie
. Pensemos en un set de datos en donde medimos el peso de pacientes con uan enfermedad degenerativa, clasificamos el peso como: bajo (<60 kg), medio (60-90 kg), alto (90-120 kg) y sobre-peso (>120 kg).
# Crear un vector de 1000 pesos
peso.kg <- c("bajo", "medio", "alto", "sobre-peso")
peso.df <- rep(peso.kg, 1000)
# Seleccionar solo 100 pesos
peso.sel <- factor(sample(peso.df, 100, replace = F))
# Ordenar los niveles del factor temperatura
levels(peso.sel)
## [1] "alto" "bajo" "medio" "sobre-peso"
## [1] "bajo" "medio" "alto" "sobre-peso"
# Estimar la frecuencia de cada temperatura
frec.peso <- table(peso.sel)
# Generar un gráfico circular
par(mfrow = c(1, 1))
par(mar = c(1, 1, 1, 1))
pie(frec.peso, col = c("yellow", "forestgreen", "skyblue", "pink"))
# Escoger colores usando paletas predefinidas
pie(frec.peso, col = rainbow(4), radius = 1) # 4 colores
## Loading required package: viridisLite
library(wesanderson)
pie(frec.peso, col = viridis(4),
labels = c("<60 kg", "60-90 kg", "90-120 kg", ">120 kg"),
radius = 1)
pie(frec.peso, col = wes_palette(name = "FantasticFox1"),
labels = c("<60 kg", "60-90 kg", "90-120 kg", ">120 kg"),
radius = 1)
pie(frec.peso, col = wes_palette(name = "Zissou1"),
labels = c("<60 kg", "60-90 kg", "90-120 kg", ">120 kg"),
radius = 1)
pie(frec.peso, col = wes_palette(name = "GrandBudapest1"),
labels = c("<60 kg", "60-90 kg", "90-120 kg", ">120 kg"),
radius = 1)
Gráficos de barras
La función Barplot
produce gráficos de mucha utilidad para resumir y comparar visualmente promedios entre niveles de factores. A continuación vamos a usar el set de datos “ElasmosCR.csv” para ilustrar como se hacen los gráficos de barras. Para ello vamos a graficar la variable d15N (concentración del isótopo de nitrógeno 15), y ver variaciones entre especies.
# Especificar el folder de trabajo
setwd("/Users/macbookpro/Dropbox/Curso R-abierto/Manuales del Curso/Manual Introductorio/")
wd <- getwd()
setwd(wd)
# Importar datos - formato "csv"
elasmos.cr <- read.csv("ElasmosCR.csv", header = T, sep = ",")
# Resumir base de datos
head(elasmos.cr)
## Zone Area X Y season lat long depth
## 1 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 2 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 3 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 4 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 5 2-Central Pacific III 494270 986031.6 Summer 8.52032 -83.88766 252.45
## 6 2-Central Pacific III 494270 986031.6 Summer 8.52032 -83.88766 252.45
## order family species sex stage TL weight
## 1 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.6 420
## 2 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.5 380
## 3 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 52.9 400
## 4 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.4 340
## 5 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 47.3 320
## 6 Carcharhiniformes Triakidae Mustelus henlei Male 1-Immature 31.7 81
## d13C d15N
## 1 -16.37962 15.37705
## 2 -16.13817 15.49575
## 3 -15.73031 15.13844
## 4 -16.20531 15.28515
## 5 -16.40551 15.45999
## 6 -16.70021 14.66036
## 'data.frame': 294 obs. of 17 variables:
## $ Zone : Factor w/ 3 levels "1-North Pacific",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ Area : Factor w/ 4 levels "I","II","III",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ X : num 494270 494270 494270 494270 494270 ...
## $ Y : num 986032 986032 986032 986032 986032 ...
## $ season : Factor w/ 2 levels "Summer","Winter": 2 2 2 2 1 1 1 1 1 1 ...
## $ lat : num 9.31 9.31 9.31 9.31 8.52 ...
## $ long : num -84.2 -84.2 -84.2 -84.2 -83.9 ...
## $ depth : num 89.8 89.8 89.8 89.8 252.4 ...
## $ order : Factor w/ 4 levels "Carcharhiniformes",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ family : Factor w/ 4 levels "Rajidae","Rhinobatidae",..: 4 4 4 4 4 4 4 4 4 4 ...
## $ species: Factor w/ 4 levels "Mustelus henlei",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ sex : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 1 1 2 1 ...
## $ stage : Factor w/ 2 levels "1-Immature","2-Mature": 2 2 2 2 2 1 1 1 1 1 ...
## $ TL : num 50.6 50.5 52.9 50.4 47.3 31.7 35.6 29.1 25.5 31.7 ...
## $ weight : num 420 380 400 340 320 81 156 66 53.4 114 ...
## $ d13C : num -16.4 -16.1 -15.7 -16.2 -16.4 ...
## $ d15N : num 15.4 15.5 15.1 15.3 15.5 ...
## [1] "Mustelus henlei" "Raja velezi" "Torpedo peruana" "Zapteryx xyster"
# Agregar base de datos para calcular el promedio
db <- aggregate(d15N ~ species, data = elasmos.cr, FUN = mean)
# Importar librerías
library(wesanderson)
# Altura de las barras
xx <- db$d15N
# Niveles del factor
v <- as.character(levels(db$species))
# Barplot 1
par(mfrow = c(1, 1))
par(mar = c(5, 5, 3, 2))
barplot(xx, col = wes_palette(4),
xlab = "Especie", ylab = "d15N",
names.arg = v, las = 1)
box(bty="l")
# Barplot 2
barplot(xx, col = wes_palette(4),
xlab = "Especie", ylab = "d15N",
ylim = c(0, 30),
names.arg=v, las = 1)
box(bty="l")
# Barplot 3
barplot(xx, col = wes_palette(4),
xlab = "Especie", ylab = "d15N",
ylim = c(14, 16),
names.arg = v, las = 1, xpd = F)
box(bty="l")
# Importar librería
library(viridis)
# Barplot
par(mfrow = c(1, 1))
par(mar = c(5, 8, 3, 2))
# Gráfico 1
barplot(xx, col = c("black", "White", "grey35", "grey95"),
ylab = "",
xlab = "d15N",
xlim = c(14, 16), horiz = T,
names.arg = v,
las = 1, yaxs = "i", xpd = F)
# Gráfico 2
barplot(xx, col = viridis(4),
ylab = "",
xlab = "d15N",
xlim = c(14, 16), horiz = T,
names.arg = v,
las = 1, xpd = F)
box(bty="l")
A continuación, veremos otras situaciones en donde tenemos dos factores en lugar de uno. Por ejemplo, ahora nos interesa ver la concentración del isótopo d15N por especie y estadio de madurez (juvenil / inmaduro y adulto / maduro). Además, vamos a calcular la desviación estándard (y error estándard) y graficar ambos (promedio +/- SD).
En este ejemplo vamos a usar una función muy útil para agrupar datos de acuerdo a uno o más factores, la función tapply
. Esta función pertenece a una familia muy diversa de funciones denominada apply
dentro del paquete plyr
: (eapply
, lapply
, sapply
, vapply
, mapply
, rapply
, tapply
). Durante las siguientes prácticas trataremos de cubrir algunas de estas funciones. Para más información acerca de las funciones de la familia apply
consultar los siguientes recursos disponibles:
https://nsaunders.wordpress.com/2010/08/20/a-brief-introduction-to-apply-in-r
http://blog.datacamp.com/r-tutorial-apply-family
# Especificar el folder de trabajo
setwd("/Users/macbookpro/Dropbox/Curso R-abierto/Manuales del Curso/Manual Introductorio/")
wd <- getwd()
setwd(wd)
# Importar datos - formato "csv"
elasmos.cr <- read.csv("ElasmosCR.csv", header = T, sep = ",")
# Resumir base de datos
head(elasmos.cr)
## Zone Area X Y season lat long depth
## 1 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 2 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 3 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 4 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 5 2-Central Pacific III 494270 986031.6 Summer 8.52032 -83.88766 252.45
## 6 2-Central Pacific III 494270 986031.6 Summer 8.52032 -83.88766 252.45
## order family species sex stage TL weight
## 1 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.6 420
## 2 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.5 380
## 3 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 52.9 400
## 4 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.4 340
## 5 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 47.3 320
## 6 Carcharhiniformes Triakidae Mustelus henlei Male 1-Immature 31.7 81
## d13C d15N
## 1 -16.37962 15.37705
## 2 -16.13817 15.49575
## 3 -15.73031 15.13844
## 4 -16.20531 15.28515
## 5 -16.40551 15.45999
## 6 -16.70021 14.66036
## 'data.frame': 294 obs. of 17 variables:
## $ Zone : Factor w/ 3 levels "1-North Pacific",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ Area : Factor w/ 4 levels "I","II","III",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ X : num 494270 494270 494270 494270 494270 ...
## $ Y : num 986032 986032 986032 986032 986032 ...
## $ season : Factor w/ 2 levels "Summer","Winter": 2 2 2 2 1 1 1 1 1 1 ...
## $ lat : num 9.31 9.31 9.31 9.31 8.52 ...
## $ long : num -84.2 -84.2 -84.2 -84.2 -83.9 ...
## $ depth : num 89.8 89.8 89.8 89.8 252.4 ...
## $ order : Factor w/ 4 levels "Carcharhiniformes",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ family : Factor w/ 4 levels "Rajidae","Rhinobatidae",..: 4 4 4 4 4 4 4 4 4 4 ...
## $ species: Factor w/ 4 levels "Mustelus henlei",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ sex : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 1 1 2 1 ...
## $ stage : Factor w/ 2 levels "1-Immature","2-Mature": 2 2 2 2 2 1 1 1 1 1 ...
## $ TL : num 50.6 50.5 52.9 50.4 47.3 31.7 35.6 29.1 25.5 31.7 ...
## $ weight : num 420 380 400 340 320 81 156 66 53.4 114 ...
## $ d13C : num -16.4 -16.1 -15.7 -16.2 -16.4 ...
## $ d15N : num 15.4 15.5 15.1 15.3 15.5 ...
# Cambiar 1-Immature a juvenile y 2-Mature a adulto
elasmos.cr$stage2 <- elasmos.cr$stage
levels(elasmos.cr$stage2) <- c("Juvenil", "Adulto")
head(elasmos.cr)
## Zone Area X Y season lat long depth
## 1 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 2 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 3 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 4 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 5 2-Central Pacific III 494270 986031.6 Summer 8.52032 -83.88766 252.45
## 6 2-Central Pacific III 494270 986031.6 Summer 8.52032 -83.88766 252.45
## order family species sex stage TL weight
## 1 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.6 420
## 2 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.5 380
## 3 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 52.9 400
## 4 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.4 340
## 5 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 47.3 320
## 6 Carcharhiniformes Triakidae Mustelus henlei Male 1-Immature 31.7 81
## d13C d15N stage2
## 1 -16.37962 15.37705 Adulto
## 2 -16.13817 15.49575 Adulto
## 3 -15.73031 15.13844 Adulto
## 4 -16.20531 15.28515 Adulto
## 5 -16.40551 15.45999 Adulto
## 6 -16.70021 14.66036 Juvenil
# Separar variables de acuerdo a "x", "y" y "z"
x <- elasmos.cr$species
y <- elasmos.cr$d15N
z <- elasmos.cr$stage2
# Altura de las barras
xx <- tapply(y, list(z, x), mean)
# Desviación estándard
yy <- tapply(y, list(z, x), sd)
# Número de replicas
zz <- tapply(y, list(z, x), length)
# Error estándard
er <- (yy / sqrt(zz))
# Nombres de especies
spp <- as.character(levels(elasmos.cr$species))
# Crear gráfico
par(mfrow = c(1, 1))
par(mar = c(5, 5, 3, 2))
barx <- barplot(xx, col = c("tomato", "skyblue2"), beside = T,
xlab = "Especies", ylab = "d15N",
ylim = c(14, 16.5),
names.arg = spp, las = 1, yaxs = "i", xpd = F)
# Barras de error
arrows(barx, xx + yy, barx, xx, angle = 90, code = 1, length = 0.05)
box(bty = "l")
¿Qué tal si quisiéramos poner una leyenda dentro del gráfico? Existen varias formas de poner una leyenda asociada a un gráfico. En el próximo ejemplo veremos cómo poner una leyenda con la función legend
. En esta función tenemos que especificar las coordenadas (x,y) dentro del gráfico (también se puede poner leyendas fuera del gráfico) en donde queremos ubicar la leyenda. Esto generalmente es un proceso de prueba/error. Sin embargo, también se pueden usar algunas las funciones asociadas como grconvertX
y grconvertY
que tienen un mayor control del espacio dentro de un gráfico.
# Especificar el folder de trabajo
setwd("/Users/macbookpro/Dropbox/Curso R-abierto/Manuales del Curso/Manual Introductorio/")
wd <- getwd()
setwd(wd)
# Importar datos - formato "csv"
elasmos.cr <- read.csv("ElasmosCR.csv", header = T, sep = ",")
# Resumir base de datos
head(elasmos.cr)
## Zone Area X Y season lat long depth
## 1 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 2 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 3 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 4 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 5 2-Central Pacific III 494270 986031.6 Summer 8.52032 -83.88766 252.45
## 6 2-Central Pacific III 494270 986031.6 Summer 8.52032 -83.88766 252.45
## order family species sex stage TL weight
## 1 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.6 420
## 2 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.5 380
## 3 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 52.9 400
## 4 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.4 340
## 5 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 47.3 320
## 6 Carcharhiniformes Triakidae Mustelus henlei Male 1-Immature 31.7 81
## d13C d15N
## 1 -16.37962 15.37705
## 2 -16.13817 15.49575
## 3 -15.73031 15.13844
## 4 -16.20531 15.28515
## 5 -16.40551 15.45999
## 6 -16.70021 14.66036
## 'data.frame': 294 obs. of 17 variables:
## $ Zone : Factor w/ 3 levels "1-North Pacific",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ Area : Factor w/ 4 levels "I","II","III",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ X : num 494270 494270 494270 494270 494270 ...
## $ Y : num 986032 986032 986032 986032 986032 ...
## $ season : Factor w/ 2 levels "Summer","Winter": 2 2 2 2 1 1 1 1 1 1 ...
## $ lat : num 9.31 9.31 9.31 9.31 8.52 ...
## $ long : num -84.2 -84.2 -84.2 -84.2 -83.9 ...
## $ depth : num 89.8 89.8 89.8 89.8 252.4 ...
## $ order : Factor w/ 4 levels "Carcharhiniformes",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ family : Factor w/ 4 levels "Rajidae","Rhinobatidae",..: 4 4 4 4 4 4 4 4 4 4 ...
## $ species: Factor w/ 4 levels "Mustelus henlei",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ sex : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 1 1 2 1 ...
## $ stage : Factor w/ 2 levels "1-Immature","2-Mature": 2 2 2 2 2 1 1 1 1 1 ...
## $ TL : num 50.6 50.5 52.9 50.4 47.3 31.7 35.6 29.1 25.5 31.7 ...
## $ weight : num 420 380 400 340 320 81 156 66 53.4 114 ...
## $ d13C : num -16.4 -16.1 -15.7 -16.2 -16.4 ...
## $ d15N : num 15.4 15.5 15.1 15.3 15.5 ...
# Cambiar 1-Immature a juvenile y 2-Mature a adulto
elasmos.cr$stage2 <- elasmos.cr$stage
levels(elasmos.cr$stage2) <- c("Juvenil", "Adulto")
head(elasmos.cr)
## Zone Area X Y season lat long depth
## 1 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 2 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 3 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 4 2-Central Pacific III 494270 986031.6 Winter 9.31405 -84.21855 89.76
## 5 2-Central Pacific III 494270 986031.6 Summer 8.52032 -83.88766 252.45
## 6 2-Central Pacific III 494270 986031.6 Summer 8.52032 -83.88766 252.45
## order family species sex stage TL weight
## 1 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.6 420
## 2 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.5 380
## 3 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 52.9 400
## 4 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 50.4 340
## 5 Carcharhiniformes Triakidae Mustelus henlei Male 2-Mature 47.3 320
## 6 Carcharhiniformes Triakidae Mustelus henlei Male 1-Immature 31.7 81
## d13C d15N stage2
## 1 -16.37962 15.37705 Adulto
## 2 -16.13817 15.49575 Adulto
## 3 -15.73031 15.13844 Adulto
## 4 -16.20531 15.28515 Adulto
## 5 -16.40551 15.45999 Adulto
## 6 -16.70021 14.66036 Juvenil
# Separar variables de acuerdo a "x", "y" y "z"
x <- elasmos.cr$species
y <- elasmos.cr$d15N
z <- elasmos.cr$stage2
# Altura de las barras
xx <- tapply(y, list(z, x), mean)
# Desviación estándard
yy <- tapply(y, list(z, x), sd)
# Número de replicas
zz <- tapply(y, list(z, x), length)
# Error estándard
er <- (yy / sqrt(zz))
# Nombres de especies
spp <- as.character(levels(elasmos.cr$species))
# Crear gráfico
par(mfrow = c(1, 1))
par(mar = c(5, 5, 3, 2))
barx <- barplot(xx, col = c("tomato", "skyblue2"), beside = T,
xlab = "Especies", ylab = "d15N",
ylim = c(14, 16.5),
names.arg = spp, las = 1, yaxs = "i", xpd = F)
# Barras de error
arrows(barx, xx + yy, barx, xx, angle = 90, code = 1, length = 0.05)
# Coordenadas de leyenda
X1 <- grconvertX(0.82, "npc") # controla la ubicación en el eje "X"
Y1 <- grconvertY(1, "npc") # controla la ubicación en el eje "y"
# Generar una leyenda
legend(X1, Y1, fill = c("tomato", "skyblue2"), bty = "n",
cex = 1.1,legend = c("Baja","Alta"))
box(bty = "l")