Introduccion a R: matrices

David Montaner (2014-03-31)

Script que introduce los comandos mas basicos de R relacionados con matrices.


# rm (list = ls ())

Vectores

vector1 <- 1:4
vector2 <- c (12,34,56,34)

vector1
#> [1] 1 2 3 4
vector2
#> [1] 12 34 56 34

Se pueden agrupar en estructuras mas complejas

cbind (vector1, vector2) #column bind
#>      vector1 vector2
#> [1,]       1      12
#> [2,]       2      34
#> [3,]       3      56
#> [4,]       4      34
rbind (vector1, vector2) #row bind
#>         [,1] [,2] [,3] [,4]
#> vector1    1    2    3    4
#> vector2   12   34   56   34

Como en otras operaciones o calculos, vectores de diferentes tamaños se reciclan

vector3 <- 1:2

cbind (vector3, vector2) #column bind
#>      vector3 vector2
#> [1,]       1      12
#> [2,]       2      34
#> [3,]       1      56
#> [4,]       2      34
rbind (vector3, vector2) #row bind
#>         [,1] [,2] [,3] [,4]
#> vector3    1    2    1    2
#> vector2   12   34   56   34

Uniendo por filas o columnas generamos una nueva clase de objetos

class (cbind (vector3, vector2)) #es una matriz
#> [1] "matrix"

MATRICES

La funcion matrix define matrices por columnas (por defecto)

M <- matrix (c (vector1, vector2), nrow = 4)
M
#>      [,1] [,2]
#> [1,]    1   12
#> [2,]    2   34
#> [3,]    3   56
#> [4,]    4   34
class (M)
#> [1] "matrix"

Funciones utiles definidas sobre matrices

nrow (M) #numero de filas
#> [1] 4
ncol (M) #numero de columnas
#> [1] 2
dim (M)  #dimension
#> [1] 4 2

no estan definidas para otros tipos de objetos

dim (vector1)
#> NULL

Operaciones con matrices

M
#>      [,1] [,2]
#> [1,]    1   12
#> [2,]    2   34
#> [3,]    3   56
#> [4,]    4   34
M*2
#>      [,1] [,2]
#> [1,]    2   24
#> [2,]    4   68
#> [3,]    6  112
#> [4,]    8   68
M+1
#>      [,1] [,2]
#> [1,]    2   13
#> [2,]    3   35
#> [3,]    4   57
#> [4,]    5   35
M
#>      [,1] [,2]
#> [1,]    1   12
#> [2,]    2   34
#> [3,]    3   56
#> [4,]    4   34
M+(0:1)  #reciclado del vector 0:1 por columnas
#>      [,1] [,2]
#> [1,]    1   12
#> [2,]    3   35
#> [3,]    3   56
#> [4,]    5   35
t (M) #traspuesta
#>      [,1] [,2] [,3] [,4]
#> [1,]    1    2    3    4
#> [2,]   12   34   56   34

Las columnas de las matrices se pueden nombrar

colnames (M) <- c ("v1", "v2")
M
#>      v1 v2
#> [1,]  1 12
#> [2,]  2 34
#> [3,]  3 56
#> [4,]  4 34

y los nombres se pueden recuperar

nombres <- colnames (M)
nombres
#> [1] "v1" "v2"

en un vector de caracteres (colnames devuelve un vector)

class (nombres) 
#> [1] "character"
length (nombres)
#> [1] 2

Tambien estan definidos los nombres de las filas aunque por defecto puedan ser un elemento nulo

rownames (M)
#> NULL
rn <- rownames (M) #es un elemento NULL
rn
#> NULL
length (rn)
#> [1] 0
class (rn)  #tiene clase propia diferente de la de vector
#> [1] "NULL"

Asignamos estos nombres a las filas de la matriz

c ("row1", "row2", "row3", "row4")
#> [1] "row1" "row2" "row3" "row4"
paste ("row", 1:4, sep = "") #otra forma de escribir los nombres
#> [1] "row1" "row2" "row3" "row4"
rownames (M) <- c ("row1", "row2", "row3", "row4") #ASIGNANDO nombres a las filas
M
#>      v1 v2
#> row1  1 12
#> row2  2 34
#> row3  3 56
#> row4  4 34
rownames (M)
#> [1] "row1" "row2" "row3" "row4"

cambiando los nombres

colnames (M) <- c ("col1", "col2")
M
#>      col1 col2
#> row1    1   12
#> row2    2   34
#> row3    3   56
#> row4    4   34

R comprueba que las dimensiones son correctas y si no lo son devuelve ERRORES

# colnames (M) <- c ("col1", "col2", "col3") 

Acceso a los elementos de la matriz segun su posicion

M
#>      col1 col2
#> row1    1   12
#> row2    2   34
#> row3    3   56
#> row4    4   34
M[2, 1] #fila 2, columna 1
#> [1] 2
M[ , 1] #toda la columna 1
#> row1 row2 row3 row4 
#>    1    2    3    4
M[2,  ] #toda la fila 2
#> col1 col2 
#>    2   34
class (M)
#> [1] "matrix"
class (M[,1])  ##recuperamos los vectores (columna)
#> [1] "numeric"
class (M[2,])  ##recuperamos los vectores (fila)
#> [1] "numeric"
dim (M)         #la matriz tiene dimension
#> [1] 4 2
dim (M[,1])     #un vector no tiene dimension
#> NULL
dim (M[2,])
#> NULL
length (M[,1])  #un vector tiene longitud
#> [1] 4
length (M[2,])
#> [1] 2

Podemos acceder a varias filas o columnas a la vez

M
#>      col1 col2
#> row1    1   12
#> row2    2   34
#> row3    3   56
#> row4    4   34
M[1:2,]
#>      col1 col2
#> row1    1   12
#> row2    2   34
M[c(1,3),]
#>      col1 col2
#> row1    1   12
#> row3    3   56
M[c(1,3),1]
#> row1 row3 
#>    1    3
M[c(1,3),2]
#> row1 row3 
#>   12   56

El resultado es entonces una matriz

class (M[1:2,])
#> [1] "matrix"

Se puede utilizar este tipo de acceso para reordenar filas y columnas de la matriz

M[,c(2,1)] #reordenar la matriz. Cambiamos las columnas.
#>      col2 col1
#> row1   12    1
#> row2   34    2
#> row3   56    3
#> row4   34    4
M[c(1,3), 2] #es un vector con nombres
#> row1 row3 
#>   12   56

Podemos acceder a los elementos de las matrices tambien para modificar su valor

M
#>      col1 col2
#> row1    1   12
#> row2    2   34
#> row3    3   56
#> row4    4   34
M[1, 1] <- 1000
M
#>      col1 col2
#> row1 1000   12
#> row2    2   34
#> row3    3   56
#> row4    4   34
M[,2] <- M[,2] * 10
M
#>      col1 col2
#> row1 1000  120
#> row2    2  340
#> row3    3  560
#> row4    4  340

Seleccion de filas y columnas utilizando sus nombres

Hemos visto como podemos acceder a las posiciones (filas y columnas) de las matrices segun su posicion, pero tambien se puede acceder a ellos utilizando sus nombres, si los tienen

M
#>      col1 col2
#> row1 1000  120
#> row2    2  340
#> row3    3  560
#> row4    4  340
M[2,2]
#> [1] 340
M["row2","col2"]
#> [1] 340
M[,c("col2", "col1")]
#>      col2 col1
#> row1  120 1000
#> row2  340    2
#> row3  560    3
#> row4  340    4
M[c("row3", "row1"),]
#>      col1 col2
#> row3    3  560
#> row1 1000  120
M[c("row3", "row1"), 1] #se pueden combinar las dos notaciones
#> row3 row1 
#>    3 1000

El acceso nos permite no solo obtener el valor sino modificarlo

M[c("row3", "row1"), 1]
#> row3 row1 
#>    3 1000
M[c("row3", "row1"), 1] <- 0
M[c("row3", "row1"), 1]
#> row3 row1 
#>    0    0

Seleccion de filas y columnas utilizando variables booleanas (o indicadores)

Se pueden usar vectores logicos para “recortar” las filas y columnas de una matriz

M
#>      col1 col2
#> row1    0  120
#> row2    2  340
#> row3    0  560
#> row4    4  340
M[c(TRUE, FALSE, FALSE, TRUE), c(FALSE, TRUE)]
#> row1 row4 
#>  120  340

Se pueden combinar las formas de acceso

M[c(1, 4), c(FALSE, TRUE)]
#> row1 row4 
#>  120  340

Y se pueden usar para reasignar valores

M[c(1, 4), c(FALSE, TRUE)]
#> row1 row4 
#>  120  340
M[c(1, 4), c(FALSE, TRUE)] <- M[c(4, 1), c(FALSE, TRUE)]
M[c(1, 4), c(FALSE, TRUE)]
#> row1 row4 
#>  340  120

Tipo o clase de los elementos de una matriz

Todos los elementos de una matriz son de la misma clase. Esto la diferencia de un data.frame (ver mas adelante)

class (M)
#> [1] "matrix"
class (M[1,])
#> [1] "numeric"
class (M[,1])
#> [1] "numeric"
class (M[1,1])
#> [1] "numeric"

Se pueden añadir filas o columnas a la matriz sobre escribiendo el objeto

M
#>      col1 col2
#> row1    0  340
#> row2    2  340
#> row3    0  560
#> row4    4  120
M <- cbind (M,c (-5,-10)) 
M
#>      col1 col2    
#> row1    0  340  -5
#> row2    2  340 -10
#> row3    0  560  -5
#> row4    4  120 -10
class (M)
#> [1] "matrix"
class (M[1,])
#> [1] "numeric"
class (M[,1])
#> [1] "numeric"
class (M[1,1])
#> [1] "numeric"

Se puede replicar todo el objeto para utilizarlo mas adelante

N <- M

R cambia automaticamente el tipo de toda la matriz cuando es necesario

M <- cbind (M, "hola") 

M
#>      col1 col2              
#> row1 "0"  "340" "-5"  "hola"
#> row2 "2"  "340" "-10" "hola"
#> row3 "0"  "560" "-5"  "hola"
#> row4 "4"  "120" "-10" "hola"
class (M)
#> [1] "matrix"
class (M[1,])
#> [1] "character"
class (M[,1])
#> [1] "character"
class (M[1,1])
#> [1] "character"

OBS: las nuevas no tienen nombre

M[,3:4]
#>                  
#> row1 "-5"  "hola"
#> row2 "-10" "hola"
#> row3 "-5"  "hola"
#> row4 "-10" "hola"

o mejor dicho, lo tienen vacio

colnames (M)  # "" idica un texto de longitud 0
#> [1] "col1" "col2" ""     ""

pero podemos incluirlos

colnames (M)[3] <- "COL3"
colnames (M)[4] <- "COL4"

o mas rapido

colnames (M)[3:4] <- c ("col3", "col4")

LOOPS con matrices

Se puede iterar en las dos dimensiones de la matriz utilizando indices, o nombres

for (i in 1:nrow (M)) {
  for (j in colnames (M)) {
    cat ("\n") #linea nueva
    ##
    print (i)
    print (j)
    dato <- M[i, j]
    print (dato)
  }
}
#> 
#> [1] 1
#> [1] "col1"
#> [1] "0"
#> 
#> [1] 1
#> [1] "col2"
#> [1] "340"
#> 
#> [1] 1
#> [1] "col3"
#> [1] "-5"
#> 
#> [1] 1
#> [1] "col4"
#> [1] "hola"
#> 
#> [1] 2
#> [1] "col1"
#> [1] "2"
#> 
#> [1] 2
#> [1] "col2"
#> [1] "340"
#> 
#> [1] 2
#> [1] "col3"
#> [1] "-10"
#> 
#> [1] 2
#> [1] "col4"
#> [1] "hola"
#> 
#> [1] 3
#> [1] "col1"
#> [1] "0"
#> 
#> [1] 3
#> [1] "col2"
#> [1] "560"
#> 
#> [1] 3
#> [1] "col3"
#> [1] "-5"
#> 
#> [1] 3
#> [1] "col4"
#> [1] "hola"
#> 
#> [1] 4
#> [1] "col1"
#> [1] "4"
#> 
#> [1] 4
#> [1] "col2"
#> [1] "120"
#> 
#> [1] 4
#> [1] "col3"
#> [1] "-10"
#> 
#> [1] 4
#> [1] "col4"
#> [1] "hola"

Aunque existen funciones que simplifican la sintaxis (y la velocidad)

N
#>      col1 col2    
#> row1    0  340  -5
#> row2    2  340 -10
#> row3    0  560  -5
#> row4    4  120 -10
apply (N, 1, sum)  #suma de las filas
#> row1 row2 row3 row4 
#>  335  332  555  114
apply (N, 2, min)  #minimo de las columnas
#> col1 col2      
#>    0  120  -10