4 + 8
## [1] 12
2 * 5 / 6
## [1] 1.666667
(2 * 5) / 6
## [1] 1.666667
2 * (5 / 6)
## [1] 1.666667
2 + 5 / 6
## [1] 2.833333
(2 + 5) / 6
## [1] 1.166667
2 + (5 / 6)
## [1] 2.833333
3 ^ 2
## [1] 9
3 ** 2
## [1] 9
4 + 5 ^ 2
## [1] 29
4 + 5 ** 2
## [1] 29
(4 + 5) ^ 2
## [1] 81
(4 + 5) ** 2
## [1] 81
10 / 3
## [1] 3.333333
round(10 / 3, 2)
## [1] 3.33
round(10 / 3, 1)
## [1] 3.3
round(10 / 3, 0)
## [1] 3
sqrt(2)
## [1] 1.414214
sqrt(9)
## [1] 3
sqrt(81)
## [1] 9
exp(0)
## [1] 1
exp(1)
## [1] 2.718282
exp(7)
## [1] 1096.633
pi
## [1] 3.141593
suma <- 4 + 8
suma
## [1] 12
suma1 <- 5 + 9
suma1
## [1] 14
producto <- 4 * 3
producto
## [1] 12
potencia <- suma ** producto
potencia
## [1] 8.9161e+12
8’916.100’000.000
entero <- 7
class(entero)
## [1] "numeric"
genero0 <- "masculino"
class(genero0)
## [1] "character"
genero1 <- factor("femenino", levels = c("femenino","masculino"))
genero2 <- factor("masculino", levels = c("femenino","masculino"))
genero1
## [1] femenino
## Levels: femenino masculino
genero2
## [1] masculino
## Levels: femenino masculino
verdadero <- TRUE
falso <- FALSE
class(verdadero)
## [1] "logical"
genero1 == "masculino"
## [1] FALSE
vector <- c(15, 23 ,45, 67, 78, 90)
seq(from = 3, to = 6)
## [1] 3 4 5 6
seq(from = 9, by = -1, length.out = 3)
## [1] 9 8 7
3:6
## [1] 3 4 5 6
LETTERS
## [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
## [20] "T" "U" "V" "W" "X" "Y" "Z"
letters
## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
vector[2]
## [1] 23
vector[3:5]
## [1] 45 67 78
vector[c(1,3,4,5)]
## [1] 15 45 67 78
LETTERS[3:6]
## [1] "C" "D" "E" "F"
letters[-(2:25)]
## [1] "a" "z"
sum(vector)
## [1] 318
length(vector)
## [1] 6
exp(1/vector)
## [1] 1.068939 1.044437 1.022471 1.015037 1.012903 1.011173
round(exp(1/vector), 3)
## [1] 1.069 1.044 1.022 1.015 1.013 1.011
library()
install.packages("dplyr", dependencies = TRUE)
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
.libPaths()
## [1] "/home/rstudio-user/R/x86_64-pc-linux-gnu-library/4.0"
## [2] "/opt/R/4.0.3/lib/R/library"
search()
## [1] ".GlobalEnv" "package:dplyr" "package:stats"
## [4] "package:graphics" "package:grDevices" "package:utils"
## [7] "package:datasets" "package:methods" "Autoloads"
## [10] "package:base"
paquetes <- library(help = "datasets")
head(paquetes$info2[[2]])
## NULL
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
Para saber en que directorio de trabajo esta guardando y buscando los archivos su sesión de R la instrucción es la siguiente:
getwd()
## [1] "/cloud/project"
el siguiente comando despliega una lista de todos los archivos que tiene actualmente en su directorio de trabajo.
ls()
## [1] "entero" "falso" "genero0" "genero1" "genero2" "paquetes"
## [7] "potencia" "producto" "suma" "suma1" "vector" "verdadero"
Si asigna un valor númerico a un objeto x en este caso, y luego usa el comando ls() la lista de elementos se actualizará.
x <- 9
ls()
## [1] "entero" "falso" "genero0" "genero1" "genero2" "paquetes"
## [7] "potencia" "producto" "suma" "suma1" "vector" "verdadero"
## [13] "x"
Liste todos los archivos en el directorio de trabajo usando “list.files()” o dir().
list.files()
## [1] "mytest2.R" "mytest3.R" "project.Rproj" "r basico.Rmd"
## [5] "r-basico.html" "r-basico.Rmd" "rsconnect" "testdir"
dir()
## [1] "mytest2.R" "mytest3.R" "project.Rproj" "r basico.Rmd"
## [5] "r-basico.html" "r-basico.Rmd" "rsconnect" "testdir"
A medida que avanzamos con la leccion, puede ir consultando la pagina de ayuda de las funciones. Eche un vistazo a la pagina de ayuda para list.files con el comando “?list.files”. La seccion de See Also muestra funciones complementarias.
?list.files
Use la funcion args() con el nombre de una funcion list.files para conocer que argumentos necesita o require la funcion.
args(list.files)
## function (path = ".", pattern = NULL, all.files = FALSE, full.names = FALSE,
## recursive = FALSE, ignore.case = FALSE, include.dirs = FALSE,
## no.. = FALSE)
## NULL
Ahora, asigne el valor del directorio de trabajo actual a una nueva variable llamada “old.dir”. Al final de la leccion, usaremos old.dir para regresar al directorio original de trabajo.
old.dir <- getwd()
Use dir.create() para crear un directorio llamado “testdir” en el directorio de trabajo actual.
dir.create("testdir")
## Warning in dir.create("testdir"): 'testdir' already exists
A partir de ahora, usaremos este nuevo directorio de trabajo, y finalmente lo borraremos. Por ello, establece como directorio de trabajo el directorio “testdir” con el comando setwd().
setwd("testdir")
Cree un archivo en el directorio de trabajo llamado “mytest.R” usando la funcion file.create(). Este archivo sera el unico en el directorio creado. Revise esto listando todos los archivos del directorio de trabajo. Finalmente, revisa si “mytest.R” existe en el directorio de trabajo usando la funcion file exists().
file.create("mytest.R")
## [1] TRUE
list.files()
## [1] "mytest.R" "mytest2.R" "mytest3.R" "project.Rproj"
## [5] "r basico.Rmd" "r-basico.html" "r-basico.Rmd" "rsconnect"
## [9] "testdir"
file.exists("mytest.R")
## [1] TRUE
Este tipo de funciones son excesivas para el uso interactivo. Pero, si esta ejecutando un programa que recorre una serie de archivos y hace algunos procesamiento en cada uno, tendra que comprobar que cada uno existe antes intentar procesarlo.
Observa informacion sobre el archivo “mytest.R” usando file.info(). Puede usar el operador $ — por ejemplo, file.info(“mytest.R”)$mode — para acceder a items especificos.
file.info("mytest.R")
## size isdir mode mtime ctime
## mytest.R 0 FALSE 664 2020-11-19 12:23:04 2020-11-19 12:23:04
## atime uid gid uname grname
## mytest.R 2020-11-19 12:23:04 10001 10001 rstudio-user rstudio-user
Cambie el nombre del archivo “mytest.R” a “mytest2.R” con file.rename().
file.rename("mytest.R", "mytest2.R")
## [1] TRUE
Su sistema operativo proporciona herramientas mas sencillas para este tipo de tareas, pero tener la capacidad de manipular archivos mediante programacion es util. Puede elimine mytest.R usando file.remove(‘mytest.R’). Tenga en cuenta que esto no funcionara con mytest.R ya que el archivo no existe. Usted ya lo ha cambiado.
Haga una copia de “mytest2.R” a un nuevo archivo llamado “mytest3.R” usando file.copy().
file.copy("mytest2.R", "mytest3.R")
## [1] FALSE
Ahora tiene dos archivos en el directorio de trabajo. Ello no parece muy interesante, pero piense que estuviera trabajando con decenas, cientos o millones de archivos? En este caso, sera absolutamente necesario acceder de forma automatica a los archivos.
Utilice el camino relativo (relative path) al archivo “mytest3.R” usando file.path(). Puede usar file.path para construir caminos a archivos y directorios que sean independientes al sistema operativo. Utilice ‘folder1’y ’folder2’ como argumentos en file.path para hacer que el camino sea independiente a la plataforma.
file.path("mytest3.R")
## [1] "mytest3.R"
ruta <- file.path("folder1", "folder2")
Observe la documentacion de dir.create con “?dir.create”. Note el argumento ‘recursive’ que se utiliza para craear directorios anidados (nested). En este caso ‘recursive’ debe ser TRUE. Ahora cree un directorio en el directorio de trabajo actual llamado “testdir2” y un subdirectorio llamado “testdir3”, todo en un solo comando usando dir.create() y file.path().
?dir.create dir.create(file.path(“testdir2”, “testdir3”), recursive = TRUE)
Para borrar un directorio tiene que utilizar el argumento recursive = TRUE con la funcion unlink(). Si no se usa recursive = TRUE, R no sabra que desea borrar el directorio con todo su contenido. Borre el directorio “testdir2” usando unlink().
unlink(“testdir2”, recursive = TRUE)
Vuelva al directorio de trabajo original usando setwd(). Recuerde que este directorio se almaceno en la variable old.dir.
setwd(old.dir)
Borre el directorio ‘testdir’ con todo su contenido
unlink(“testdir”, recursive = TRUE)
La información que manipulamos en R se estructura en forma de objetos. Para trabajar con R resulta importante conocer los principales tipos de objetos y sus propiedades básicas. En general, cada tipo de objeto viene definido por una serie de atributos. Las funciones genéricas (como por ejemplo summary o plot) reconocen estos atributos y llevan a cabo distintos tipos de acciones en función del tipo de objeto. Aquí nos vamos a centrar solo en los objetos más utilizados: vectores, matrices, listas, data frames y factores.
Algunos comandos para generar vectores
Para encadenar dos vectores podemos usar el comando c(). Los escalares son, a todos los efectos, vectores de longitud 1:
x <- c(2, 4, 6)
y <- c(3, 7)
c(x, y)
## [1] 2 4 6 3 7
Para generar sucesiones o vectores de valores repetidos podemos usar los siguientes comandos:
a <- 100:500
seq(2, 10, 2)
## [1] 2 4 6 8 10
seq(2, 10, 3)
## [1] 2 5 8
rep(c(1, 2, 3), 4)
## [1] 1 2 3 1 2 3 1 2 3 1 2 3
rep(1:5,5)
## [1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
Es muy importante para operar con vectores tener en cuenta la regla del reciclaje: si usamos vectores que no alcanzan la dimensión adecuada para ciertas operaciones, R automáticamente recicla el vector (repite los valores) hasta llegar a la dimensión requerida.
100 + c(1, 2, 3)
## [1] 101 102 103
c(1, 2) + c(7, 8, 9)
## Warning in c(1, 2) + c(7, 8, 9): longer object length is not a multiple of
## shorter object length
## [1] 8 10 10
Por una parte, esta propiedad es peligrosa ya que podemos cometer errores sin darnos cuenta. La parte positiva es que muchas veces permite ahorrar código. En el segundo de los ejemplos anteriores vemos que si la dimensión del vector no es un divisor de la dimensión adecuada, recibimos un mensaje de aviso (pero se sigue aplicando el reciclaje y la operación se lleva a cabo).
Las expresiones NA, NaN, Inf, NULL están reservadas para los valores especiales Not Available, Not a Number, Infinity y Null, respectivamente. Para entender cómo opera R con estos valores, observa los ejemplos siguientes:
x <- c(NA, NaN, Inf, 0, 3, NULL)
1/x
## [1] NA NaN 0.0000000 Inf 0.3333333
x - x
## [1] NA NaN NaN 0 0
1/x - (x - x)
## [1] NA NaN NaN Inf 0.3333333
El valor Null corresponde a vacío y es ignorado. Puede ser útil sin embargo si queremos crear un objeto que luego vamos a ir completando poco a poco.
Se usan corchetes para generar subvectores formados por algunas de las coordenadas de un vector:
x <- (1:5)^2
x
## [1] 1 4 9 16 25
x <- (1:500)**2
x
## [1] 1 4 9 16 25 36 49 64 81 100
## [11] 121 144 169 196 225 256 289 324 361 400
## [21] 441 484 529 576 625 676 729 784 841 900
## [31] 961 1024 1089 1156 1225 1296 1369 1444 1521 1600
## [41] 1681 1764 1849 1936 2025 2116 2209 2304 2401 2500
## [51] 2601 2704 2809 2916 3025 3136 3249 3364 3481 3600
## [61] 3721 3844 3969 4096 4225 4356 4489 4624 4761 4900
## [71] 5041 5184 5329 5476 5625 5776 5929 6084 6241 6400
## [81] 6561 6724 6889 7056 7225 7396 7569 7744 7921 8100
## [91] 8281 8464 8649 8836 9025 9216 9409 9604 9801 10000
## [101] 10201 10404 10609 10816 11025 11236 11449 11664 11881 12100
## [111] 12321 12544 12769 12996 13225 13456 13689 13924 14161 14400
## [121] 14641 14884 15129 15376 15625 15876 16129 16384 16641 16900
## [131] 17161 17424 17689 17956 18225 18496 18769 19044 19321 19600
## [141] 19881 20164 20449 20736 21025 21316 21609 21904 22201 22500
## [151] 22801 23104 23409 23716 24025 24336 24649 24964 25281 25600
## [161] 25921 26244 26569 26896 27225 27556 27889 28224 28561 28900
## [171] 29241 29584 29929 30276 30625 30976 31329 31684 32041 32400
## [181] 32761 33124 33489 33856 34225 34596 34969 35344 35721 36100
## [191] 36481 36864 37249 37636 38025 38416 38809 39204 39601 40000
## [201] 40401 40804 41209 41616 42025 42436 42849 43264 43681 44100
## [211] 44521 44944 45369 45796 46225 46656 47089 47524 47961 48400
## [221] 48841 49284 49729 50176 50625 51076 51529 51984 52441 52900
## [231] 53361 53824 54289 54756 55225 55696 56169 56644 57121 57600
## [241] 58081 58564 59049 59536 60025 60516 61009 61504 62001 62500
## [251] 63001 63504 64009 64516 65025 65536 66049 66564 67081 67600
## [261] 68121 68644 69169 69696 70225 70756 71289 71824 72361 72900
## [271] 73441 73984 74529 75076 75625 76176 76729 77284 77841 78400
## [281] 78961 79524 80089 80656 81225 81796 82369 82944 83521 84100
## [291] 84681 85264 85849 86436 87025 87616 88209 88804 89401 90000
## [301] 90601 91204 91809 92416 93025 93636 94249 94864 95481 96100
## [311] 96721 97344 97969 98596 99225 99856 100489 101124 101761 102400
## [321] 103041 103684 104329 104976 105625 106276 106929 107584 108241 108900
## [331] 109561 110224 110889 111556 112225 112896 113569 114244 114921 115600
## [341] 116281 116964 117649 118336 119025 119716 120409 121104 121801 122500
## [351] 123201 123904 124609 125316 126025 126736 127449 128164 128881 129600
## [361] 130321 131044 131769 132496 133225 133956 134689 135424 136161 136900
## [371] 137641 138384 139129 139876 140625 141376 142129 142884 143641 144400
## [381] 145161 145924 146689 147456 148225 148996 149769 150544 151321 152100
## [391] 152881 153664 154449 155236 156025 156816 157609 158404 159201 160000
## [401] 160801 161604 162409 163216 164025 164836 165649 166464 167281 168100
## [411] 168921 169744 170569 171396 172225 173056 173889 174724 175561 176400
## [421] 177241 178084 178929 179776 180625 181476 182329 183184 184041 184900
## [431] 185761 186624 187489 188356 189225 190096 190969 191844 192721 193600
## [441] 194481 195364 196249 197136 198025 198916 199809 200704 201601 202500
## [451] 203401 204304 205209 206116 207025 207936 208849 209764 210681 211600
## [461] 212521 213444 214369 215296 216225 217156 218089 219024 219961 220900
## [471] 221841 222784 223729 224676 225625 226576 227529 228484 229441 230400
## [481] 231361 232324 233289 234256 235225 236196 237169 238144 239121 240100
## [491] 241081 242064 243049 244036 245025 246016 247009 248004 249001 250000
x[496]
## [1] 246016
x[c(2, 496)]
## [1] 4 246016
Pueden utilizarse valores negativos dentro del corchete para eliminar coordenadas:
x[-c(200:500)]
## [1] 1 4 9 16 25 36 49 64 81 100 121 144
## [13] 169 196 225 256 289 324 361 400 441 484 529 576
## [25] 625 676 729 784 841 900 961 1024 1089 1156 1225 1296
## [37] 1369 1444 1521 1600 1681 1764 1849 1936 2025 2116 2209 2304
## [49] 2401 2500 2601 2704 2809 2916 3025 3136 3249 3364 3481 3600
## [61] 3721 3844 3969 4096 4225 4356 4489 4624 4761 4900 5041 5184
## [73] 5329 5476 5625 5776 5929 6084 6241 6400 6561 6724 6889 7056
## [85] 7225 7396 7569 7744 7921 8100 8281 8464 8649 8836 9025 9216
## [97] 9409 9604 9801 10000 10201 10404 10609 10816 11025 11236 11449 11664
## [109] 11881 12100 12321 12544 12769 12996 13225 13456 13689 13924 14161 14400
## [121] 14641 14884 15129 15376 15625 15876 16129 16384 16641 16900 17161 17424
## [133] 17689 17956 18225 18496 18769 19044 19321 19600 19881 20164 20449 20736
## [145] 21025 21316 21609 21904 22201 22500 22801 23104 23409 23716 24025 24336
## [157] 24649 24964 25281 25600 25921 26244 26569 26896 27225 27556 27889 28224
## [169] 28561 28900 29241 29584 29929 30276 30625 30976 31329 31684 32041 32400
## [181] 32761 33124 33489 33856 34225 34596 34969 35344 35721 36100 36481 36864
## [193] 37249 37636 38025 38416 38809 39204 39601
También se pueden usar operaciones lógicas para seleccionar las coordenadas que cumplen cierta condición. El comando which se usa para saber los índices de las coordenadas que cumplen la condición:
x <- (10:100)^2
x
## [1] 100 121 144 169 196 225 256 289 324 361 400 441
## [13] 484 529 576 625 676 729 784 841 900 961 1024 1089
## [25] 1156 1225 1296 1369 1444 1521 1600 1681 1764 1849 1936 2025
## [37] 2116 2209 2304 2401 2500 2601 2704 2809 2916 3025 3136 3249
## [49] 3364 3481 3600 3721 3844 3969 4096 4225 4356 4489 4624 4761
## [61] 4900 5041 5184 5329 5476 5625 5776 5929 6084 6241 6400 6561
## [73] 6724 6889 7056 7225 7396 7569 7744 7921 8100 8281 8464 8649
## [85] 8836 9025 9216 9409 9604 9801 10000
x[x > 5000]
## [1] 5041 5184 5329 5476 5625 5776 5929 6084 6241 6400 6561 6724
## [13] 6889 7056 7225 7396 7569 7744 7921 8100 8281 8464 8649 8836
## [25] 9025 9216 9409 9604 9801 10000
which(x > 5000)
## [1] 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
## [26] 87 88 89 90 91
Las matrices son también vectores pero con dos atributos adicionales: número de filas y número de columnas. Sin embargo, los vectores no son matrices con una fila o con una columna. Para crear una matriz:
matrix(1:3, nrow = 2, ncol = 3, byrow = FALSE)
## [,1] [,2] [,3]
## [1,] 1 3 2
## [2,] 2 1 3
El primer argumento es un vector que incluye los elementos de la matriz y los otros dos corresponden al número de filas y columnas. Los elementos se van colocando por columnas. Observa cómo se ha aplicado la regla del reciclaje en el ejemplo anterior.
Veamos qué ocurre al sumar un vector y una matriz:
matrix(1:9, 3, 3)
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
c(1, 2, 3) + matrix(1:9, 3, 3)
## [,1] [,2] [,3]
## [1,] 2 5 8
## [2,] 4 7 10
## [3,] 6 9 12
Tal vez es conveniente explicar paso a paso el resultado de la operación anterior:
La matriz es considerada como un vector. El vector que resulta de apilar sus columnas una sobre otra.
Los vectores se suman, aplicando la regla de reciclaje ya que las dimensiones no coinciden.
El vector resultante de la suma hereda los atributos (número de filas y columnas) de la matriz.
En el ejemplo siguiente, la matriz es de nuevo considerada como un vector. Se seleccionan todas las entradas de la matriz mayores que seis y se devuelven en forma de vector. Los índices correspondientes se refieren también a la matriz considerada como vector.
x <- matrix(5:8, 3, 4)
x
## [,1] [,2] [,3] [,4]
## [1,] 5 8 7 6
## [2,] 6 5 8 7
## [3,] 7 6 5 8
x[x > 6]
## [1] 7 8 7 8 7 8
which(x < 6)
## [1] 1 5 9
Usando corchetes es posible extraer submatrices. Dentro del corchete, separadas por una coma, se indican las filas y columnas que queremos extraer (o eliminar si usamos números negativos). Si no se pone nada antes o después de la coma se extraen todas las filas o columnas, respectivamente:
x
## [,1] [,2] [,3] [,4]
## [1,] 5 8 7 6
## [2,] 6 5 8 7
## [3,] 7 6 5 8
x[1,]
## [1] 5 8 7 6
x[2,]
## [1] 6 5 8 7
x[3,]
## [1] 7 6 5 8
x[,1]
## [1] 5 6 7
x[,2]
## [1] 8 5 6
x[,3]
## [1] 7 8 5
x[,4]
## [1] 6 7 8
x[1,1]
## [1] 5
x[1, 2]
## [1] 8
x[1:2,3]
## [1] 7 8
x[3, -1]
## [1] 6 5 8
x[3, -(1:3)]
## [1] 8
Con los comandos cbind y rbind se pueden pegar varios vectores para formar una matriz. Si usamos cbind cada vector será una columna de la matriz formada. Con rbind será una fila:
y <- 1:3
z <- 4:6
A <- cbind(y, z)
A
## y z
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
A[2,"z"]
## z
## 5
B <-rbind(y, z)
B
## [,1] [,2] [,3]
## y 1 2 3
## z 4 5 6
B["z",1]
## z
## 4
colnames(B) <- c("a","b","c")
B
## a b c
## y 1 2 3
## z 4 5 6
B["y","a"]
## [1] 1
B["y",]
## a b c
## 1 2 3
B[,"a"]
## y z
## 1 4
Resulta bastante frecuente la necesidad de aplicar una función a cada una de las filas o columnas de una matriz. Para ello se usa el comando apply(). Este comando tiene tres argumentos:
El primer argumento es la matriz sobre la que se desea operar.
El segundo argumento es un 1 (si queremos operar sobre las filas) o un 2 (si queremos hacerlo sobre las columnas).
El tercer argumento es el nombre de la función que se desea aplicar a cada fila o columna.
En el siguiente ejemplo se calculan las medias de cada columna de x. Compara el resultado de apply con el de aplicar directamente el comando sobre la matriz. ¿Qué ocurre en este útimo caso? Como mean opera sobre vectores, al escribir mean(x) se considera la matriz como un vector y se calcula el promedio de todas sus entradas.
x
## [,1] [,2] [,3] [,4]
## [1,] 5 8 7 6
## [2,] 6 5 8 7
## [3,] 7 6 5 8
mean(x)
## [1] 6.5
mean(x[1,])
## [1] 6.5
apply(x, 1, mean)
## [1] 6.5 6.5 6.5
apply(x, 2, mean)
## [1] 6.000000 6.333333 6.666667 7.000000
mean(x[,1])
## [1] 6
En el ejemplo siguiente se ordenan de menor a mayor cada una de las filas de una matriz. Observa con atención la dimensión de la matriz resultante:
x
## [,1] [,2] [,3] [,4]
## [1,] 5 8 7 6
## [2,] 6 5 8 7
## [3,] 7 6 5 8
apply(x, 1, sort)
## [,1] [,2] [,3]
## [1,] 5 5 5
## [2,] 6 6 6
## [3,] 7 7 7
## [4,] 8 8 8
apply(x, 2, sort)
## [,1] [,2] [,3] [,4]
## [1,] 5 5 5 6
## [2,] 6 6 7 7
## [3,] 7 8 8 8
Si al aplicar la función sobre una columna o fila el resultado es otro vector, el resultado de apply será una matriz. En este caso, los resultados de la aplicación a cada columna o fila son las columnas de la matriz resultante.
En este apartado se resumen los comandos necesarios para llevar a cabo la operaciones con matrices más habituales:
A %*% B
## a b c
## [1,] 17 22 27
## [2,] 22 29 36
## [3,] 27 36 45
A*A;B*B;x*x
## y z
## [1,] 1 16
## [2,] 4 25
## [3,] 9 36
## a b c
## y 1 4 9
## z 16 25 36
## [,1] [,2] [,3] [,4]
## [1,] 25 64 49 36
## [2,] 36 25 64 49
## [3,] 49 36 25 64
t(A*A);t(B*B);t(x*x)
## [,1] [,2] [,3]
## y 1 4 9
## z 16 25 36
## y z
## a 1 16
## b 4 25
## c 9 36
## [,1] [,2] [,3]
## [1,] 25 36 49
## [2,] 64 25 36
## [3,] 49 64 25
## [4,] 36 49 64
det(A%*%t(A));det(B%*%t(B));det(x%*%t(x))
## [1] 0
## [1] 54
## [1] 21696
diag(A%*%t(A));diag(B%*%t(B));diag(x%*%t(x))
## [1] 17 29 45
## y z
## 14 77
## [1] 174 174 174
A <- matrix(c(1,2,1,1,3,-5,1,5,6), ncol=3)
b <- c(2,11,29)
x <- solve(A,b)
A%*%c(1,-2,3)
## [,1]
## [1,] 2
## [2,] 11
## [3,] 29
solve(B%*%t(B));solve(A)
## y z
## y 1.4259259 -0.5925926
## z -0.5925926 0.2592593
## [,1] [,2] [,3]
## [1,] 1.8695652 -0.4782609 0.08695652
## [2,] -0.3043478 0.2173913 -0.13043478
## [3,] -0.5652174 0.2608696 0.04347826
A%*%solve(A)
## [,1] [,2] [,3]
## [1,] 1.000000e+00 -5.551115e-17 -2.081668e-17
## [2,] 0.000000e+00 1.000000e+00 0.000000e+00
## [3,] 4.440892e-16 0.000000e+00 1.000000e+00
eigen(x%*%t(x));eigen(B%*%t(B));eigen(A%*%t(A))
## eigen() decomposition
## $values
## [1] 1.400000e+01 3.552714e-15 0.000000e+00
##
## $vectors
## [,1] [,2] [,3]
## [1,] 0.2672612 0.9636241 0.0000000
## [2,] -0.5345225 0.1482499 0.8320503
## [3,] 0.8017837 -0.2223748 0.5547002
## eigen() decomposition
## $values
## [1] 90.4026725 0.5973275
##
## $vectors
## [,1] [,2]
## [1,] 0.3863177 -0.9223658
## [2,] 0.9223658 0.3863177
## eigen() decomposition
## $values
## [1] 71.416257 31.347447 0.236296
##
## $vectors
## [,1] [,2] [,3]
## [1,] -0.09484464 -0.2612512 0.96059997
## [2,] -0.47378819 -0.8368090 -0.27436357
## [3,] -0.87551656 0.4811428 0.04441089
Una lista es un vector de objetos de tipos distintos, que conviene agrupar en la misma estructura por diversas razones (por ejemplo, son un conjunto de resultados de un análisis estadístico de un conjunto de datos). Intuitivamente, es como una caja en la que se ponen objetos relacionados. Es importante comprender sus propiedades porque muchas funciones de R devuelven los resultados en forma de lista. Para crearlas se usa el comando list. En el siguiente ejemplo creamos una lista llamada milista con tres elementos llamados nombre, no.hijos y edades.hijos (este último es un vector de longitud 3):
milista <- list(nombre = "Pepe", no.hijos = 3, edades.hijos = c(4, 7, 9))
La estructura de una lista (los objetos que contiene la caja y de qué tipo son) se puede conocer con el comando str():
str(milista)
## List of 3
## $ nombre : chr "Pepe"
## $ no.hijos : num 3
## $ edades.hijos: num [1:3] 4 7 9
Para extrer un elemento de una lista se usa nombre_lista$nombre_objeto si los elementos de la lista tienen nombre. También se puede usar un doble corchete y el número de orden del objeto dentro de la lista:
milista$nombre
## [1] "Pepe"
milista$no.hijos
## [1] 3
milista$edades.hijos
## [1] 4 7 9
milista[[1]]
## [1] "Pepe"
milista[[2]]
## [1] 3
milista[[3]]
## [1] 4 7 9
milista$edades.hijos[1]
## [1] 4
milista$edades.hijos[2]
## [1] 7
milista$edades.hijos[3]
## [1] 9
En el último ejemplo anterior hemos extraído el último elemento (que era un vector) y, dentro de este, la segunda coordenada. Para reflexionar sobre la diferencia entre un único corchete y un doble corchete:
¿Cuál es la diferencia entre milista[1] y milista[[1]]?
milista[1];milista[[1]]
## $nombre
## [1] "Pepe"
## [1] "Pepe"
¿Cuál es el resultado de milista[2:3]?
milista[2:3]
## $no.hijos
## [1] 3
##
## $edades.hijos
## [1] 4 7 9
¿Y el resultado de milista[[2:3]]?
#milista[[2:3]]
Un data frame es la estructura que se usa en R para los ficheros de datos correspondientes a una serie de variables medidas en cada sujeto o unidad bajo estudio. Intuitivamente podemos ver un data frame como una matriz con entradas que pueden ser de distintos tipos (números, palabras, etc.). Técnicamente son listas cuyos elementos son vectores de la misma longitud.
Para crearlos se utiliza el comando data.frame. En el siguiente ejemplo creamos uno llamado mifichero con dos vectores llamados edad y grupo. Los vectores (variables) son de la misma longitud pero son heterogéneos en el sentido de que el primero contiene números y el segundo letras.
x <- 7:9
y <- c("a", "b", "c")
mifichero <- data.frame(edad = x, grupo = y)
mifichero
## edad grupo
## 1 7 a
## 2 8 b
## 3 9 c
Dado que los data frames son un tipo particular de listas, podemos aplicarles todos los comandos que hemos introducido en la sección anterior:
str(mifichero)
## 'data.frame': 3 obs. of 2 variables:
## $ edad : int 7 8 9
## $ grupo: chr "a" "b" "c"
mifichero$edad
## [1] 7 8 9
mifichero$grupo
## [1] "a" "b" "c"
mifichero[[2]]
## [1] "a" "b" "c"
Al mismo tiempo, también admiten algunos de los comandos que se aplican a las matrices. Para extraer todas las variables correspondientes a la segunda observación (la segunda fila del fichero) podemos escribir:
mifichero[1, ]
## edad grupo
## 1 7 a
mifichero[2, ]
## edad grupo
## 2 8 b
mifichero[3, ]
## edad grupo
## 3 9 c
mifichero[ ,1]
## [1] 7 8 9
mifichero[ ,2]
## [1] "a" "b" "c"
Si queremos aplicar el mismo comando a todas las variables de un fichero podemos usar dos comandos, lapply y sapply, que difieren en la estructura que tiene el resultado:
lapply para aplicar una función a cada elemento de una lista (el resultado es otra lista),
sapply actúa igual, pero el resultado es un vector o una matriz.
Como ejemplo tomamos el fichero faithful que contiene datos de duración y tiempo de espera entre erupciones del geyser Old faithful en Yellowstone. Si queremos obtener las principales medidas descriptivas de cada una de las dos variables del fichero:
sapply(faithful, summary)
## eruptions waiting
## Min. 1.600000 43.00000
## 1st Qu. 2.162750 58.00000
## Median 4.000000 76.00000
## Mean 3.487783 70.89706
## 3rd Qu. 4.454250 82.00000
## Max. 5.100000 96.00000
lapply(faithful, summary)
## $eruptions
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.600 2.163 4.000 3.488 4.454 5.100
##
## $waiting
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 43.0 58.0 76.0 70.9 82.0 96.0
Los factores son las estructuras que se utilizan para manejar las variables cualitativas en los análisis estadísticos. Se pueden contemplar como un vector al que se añade un poco más de información consistente en los distintos valores presentes en el vector, llamados niveles. Se crean usando el comando factor(). Veamos un ejemplo:
x <- c(2, 2, 3, 4, 2, 5)
x
## [1] 2 2 3 4 2 5
xfactor <- factor(x)
xfactor
## [1] 2 2 3 4 2 5
## Levels: 2 3 4 5
El fichero iris contiene los famosos datos de lirios de Fisher con medidas de la longitud y anchura del sépalo y pétalo de 150 lirios correspondientes a tres especies. Veamos las primeras observaciones del fichero:
head(iris)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
La última variable es un factor que indica la especie a la que corresponde cada observación:
iris$Species
## [1] setosa setosa setosa setosa setosa setosa
## [7] setosa setosa setosa setosa setosa setosa
## [13] setosa setosa setosa setosa setosa setosa
## [19] setosa setosa setosa setosa setosa setosa
## [25] setosa setosa setosa setosa setosa setosa
## [31] setosa setosa setosa setosa setosa setosa
## [37] setosa setosa setosa setosa setosa setosa
## [43] setosa setosa setosa setosa setosa setosa
## [49] setosa setosa versicolor versicolor versicolor versicolor
## [55] versicolor versicolor versicolor versicolor versicolor versicolor
## [61] versicolor versicolor versicolor versicolor versicolor versicolor
## [67] versicolor versicolor versicolor versicolor versicolor versicolor
## [73] versicolor versicolor versicolor versicolor versicolor versicolor
## [79] versicolor versicolor versicolor versicolor versicolor versicolor
## [85] versicolor versicolor versicolor versicolor versicolor versicolor
## [91] versicolor versicolor versicolor versicolor versicolor versicolor
## [97] versicolor versicolor versicolor versicolor virginica virginica
## [103] virginica virginica virginica virginica virginica virginica
## [109] virginica virginica virginica virginica virginica virginica
## [115] virginica virginica virginica virginica virginica virginica
## [121] virginica virginica virginica virginica virginica virginica
## [127] virginica virginica virginica virginica virginica virginica
## [133] virginica virginica virginica virginica virginica virginica
## [139] virginica virginica virginica virginica virginica virginica
## [145] virginica virginica virginica virginica virginica virginica
## Levels: setosa versicolor virginica
Supongamos que queremos calcular la media de las lóngitudes de los pétalos para cada una de las tres especies. Para ello podemos usar la funcion tapply(), que tiene tres argumentos:
El primero, la variable a la que queremos aplicar la función;
el segundo, el factor para cada uno de cuyos niveles vamos a calcular la función;
el tercero, la función que queremos calcular (en nuestro ejemplo, la media)
tapply(iris$Petal.Length, iris$Species, mean)
## setosa versicolor virginica
## 1.462 4.260 5.552