Una matriz es un objeto multidimensional. Las dimensiones de una matriz se especifican por su atributo dim, que proporciona los índices máximos en cada dimensión. Entonces, para una matriz tridimensional que consta de 24 números en una secuencia 1:24, con dimensiones 2×4×3, escribimos:
y <- 1:24
dim(y) <- c(2,4,3)
y## , , 1
##
## [,1] [,2] [,3] [,4]
## [1,] 1 3 5 7
## [2,] 2 4 6 8
##
## , , 2
##
## [,1] [,2] [,3] [,4]
## [1,] 9 11 13 15
## [2,] 10 12 14 16
##
## , , 3
##
## [,1] [,2] [,3] [,4]
## [1,] 17 19 21 23
## [2,] 18 20 22 24
Esto produce tres tablas bidimensionales, porque la tercera dimensión es 3. Esto es lo que sucede cuando cambias las dimensiones:
dim(y) <- c(3,2,4)
y## , , 1
##
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
##
## , , 2
##
## [,1] [,2]
## [1,] 7 10
## [2,] 8 11
## [3,] 9 12
##
## , , 3
##
## [,1] [,2]
## [1,] 13 16
## [2,] 14 17
## [3,] 15 18
##
## , , 4
##
## [,1] [,2]
## [1,] 19 22
## [2,] 20 23
## [3,] 21 24
Ahora tenemos cuatro tablas bidimensionales, cada una de tres filas y dos columnas. Siga observando estos dos ejemplos hasta que esté seguro de que comprende exactamente lo que sucedió aquí.
Una matriz es un arreglo bidimensional que contiene números. Un marco de datos es una lista bidimensional que contiene potencialmente una combinación de números, texto o variables lógicas en diferentes columnas. Cuando hay dos subíndices [5,3] para un objeto como una matriz o un marco de datos, el primer subíndice se refiere al número de fila (5 en este ejemplo; las filas se definen como número de margen 1) y el segundo subíndice se refiere al número de columna (3 en este ejemplo; las columnas son el margen número 2). Hay una convención importante y poderosa en R, de modo que cuando un subíndice aparece como un espacio en blanco, se entiende que significa “todo de”. De este modo:
[,4] significa todas las filas en la columna 4 de un objeto.
[2,] significa todas las columnas en la fila 2 de un objeto.
Hay varias formas de hacer una matriz. Puedes crear uno directamente como este:
X <- matrix(c(1,0,0,0,1,0,0,0,1),nrow=3)
X## [,1] [,2] [,3]
## [1,] 1 0 0
## [2,] 0 1 0
## [3,] 0 0 1
donde, por defecto, los números se ingresan en forma de columna. La clase y atributos de indican que es una matriz de tres filas y tres columnas (estos son sus atributos):
class(X)[1] ## [1] "matrix"
attributes(X)## $dim
## [1] 3 3
En el siguiente ejemplo, los datos en el vector aparecen por filas, por lo que indicamos esto con byrow=T:
vector <- c(1,2,3,4,4,3,2,1)
V <- matrix(vector,byrow=T,nrow=2)
V## [,1] [,2] [,3] [,4]
## [1,] 1 2 3 4
## [2,] 4 3 2 1
Otra forma de convertir un vector en una matriz es proporcionar al objeto vectorial dos dimensiones (filas y columnas) usando la función como esta:
dim(vector) <- c(4,2)Podemos comprobar que el vector ahora se ha convertido en una matriz:
is.matrix(vector)## [1] TRUE
Sin embargo, debemos tener cuidado porque no hemos tenido en cuenta en esta etapa el hecho de que los datos se ingresaron por filas en el vector:
vector## [,1] [,2]
## [1,] 1 4
## [2,] 2 3
## [3,] 3 2
## [4,] 4 1
La matriz que queremos es la transpuesta,t, de esta matriz:
(vector <- t(vector))## [,1] [,2] [,3] [,4]
## [1,] 1 2 3 4
## [2,] 4 3 2 1
Al principio, las matrices tienen números que nombran sus filas y columnas (ver arriba). Aquí hay una matriz de 4 × 5 de números enteros aleatorios de una distribución de Poisson con media 1.5:
X <- matrix(rpois(20,1.5),nrow=4)
X## [,1] [,2] [,3] [,4] [,5]
## [1,] 0 1 1 2 0
## [2,] 1 4 2 3 0
## [3,] 2 1 4 0 1
## [4,] 3 3 0 1 2
Suponga que las filas se refieren a cuatro ensayos diferentes y queremos etiquetar las filas como ‘Prueba.1’, etc. Empleamos la función Rownames para hacer esto. Podríamos usar la función paste (ver p. 87) pero aquí aprovechamos la opción de prefix:
rownames(X) <- rownames(X,do.NULL=FALSE,prefix="Trial.")
X## [,1] [,2] [,3] [,4] [,5]
## Trial.1 0 1 1 2 0
## Trial.2 1 4 2 3 0
## Trial.3 2 1 4 0 1
## Trial.4 3 3 0 1 2
Para las columnas, queremos proporcionar un vector de diferentes nombres para los cinco medicamentos involucrados en el ensayo, y usar esto para especificar los colnames (X):
drug.names <- c("aspirin", "paracetamol", "nurofen", "hedex", "placebo")
colnames(X) <- drug.names
X## aspirin paracetamol nurofen hedex placebo
## Trial.1 0 1 1 2 0
## Trial.2 1 4 2 3 0
## Trial.3 2 1 4 0 1
## Trial.4 3 3 0 1 2
Alternativamente, puede usar la función dimnames para dar nombres a las filas y/o columnas de una matriz. En este ejemplo, queremos que las filas no estén etiquetadas (NULL) y que los nombres de las columnas tengan la forma ‘drug.1’, ‘drug .2’, etc. El argumento para dimnames tiene que ser una list (filas primero, columnas segundo, como de costumbre) con los elementos de la lista de exactamente las longitudes correctas (4 y 5 en este caso particular):
dimnames(X) <- list(NULL,paste("drug.",1:5,sep=""))
X## drug.1 drug.2 drug.3 drug.4 drug.5
## [1,] 0 1 1 2 0
## [2,] 1 4 2 3 0
## [3,] 2 1 4 0 1
## [4,] 3 3 0 1 2
Podríamos usar subíndices para seleccionar partes de la matriz, con un espacio en blanco que significa “todas las filas” o “todas las columnas”. Aquí está la media de la columna más a la derecha (número 5), calculada sobre todas las filas (en blanco y luego coma),
mean (X [,5])## [1] 0.75
o la varianza de la fila inferior, calculada sobre todas las columnas (un espacio en blanco en la segunda posición),
var(X[4,])## [1] 1.7
Hay algunas funciones especiales para calcular estadísticas de resumen en matrices:
rowSums(X)## [1] 4 10 8 9
colSums(X)## drug.1 drug.2 drug.3 drug.4 drug.5
## 6 9 7 6 3
rowMeans(X)## [1] 0.8 2.0 1.6 1.8
colMeans(X)## drug.1 drug.2 drug.3 drug.4 drug.5
## 1.50 2.25 1.75 1.50 0.75
Estas funciones están diseñadas para la velocidad y desdibujan algunas de las sutilezas de tratar con NA o NaN. Si tal sutileza es un problema, utilice apply en su lugar (p. 61). Recuerde que las columnas son el margen número 2 y las filas son el margen número 1:
apply(X,2,mean)## drug.1 drug.2 drug.3 drug.4 drug.5
## 1.50 2.25 1.75 1.50 0.75
Es posible que desee sumar grupos de filas dentro de columnas, y rowsum (singular y todo en minúsculas, en contraste con rowSums, arriba) es una función muy eficiente para esto. En este ejemplo, queremos agrupar la fila 1 y la fila 4 (como grupo A) y la fila 2 y la fila 3 (grupo B). Tenga en cuenta que el vector de agrupación debe tener una longitud igual al número de filas:
group=c("A","B","B","A")
rowsum(X, group)## drug.1 drug.2 drug.3 drug.4 drug.5
## A 3 4 1 3 2
## B 3 5 6 3 1
Podría lograr los mismos fines (pero más lentamente) con tapply o aggregate
tapply(X, list(group[row(X)], col(X)), sum)## 1 2 3 4 5
## A 3 4 1 3 2
## B 3 5 6 3 1
Tenga en cuenta el uso de Row(X) y Col(X), con la Row(X) utilizada como subíndice en el group.
aggregate(X,list(group),sum)Supongamos que queremos barajar los elementos de cada columna de una matriz de forma independiente. Aplicamos la función muestra a cada columna (margen número 2) así:
apply(X,2,sample)## drug.1 drug.2 drug.3 drug.4 drug.5
## [1,] 1 3 0 1 0
## [2,] 2 1 4 0 0
## [3,] 0 1 1 2 2
## [4,] 3 4 2 3 1
apply(X,2,sample)## drug.1 drug.2 drug.3 drug.4 drug.5
## [1,] 3 1 0 2 2
## [2,] 0 3 2 0 1
## [3,] 2 4 1 1 0
## [4,] 1 1 4 3 0
y así sucesivamente, para tantas muestras mezcladas como necesite.
En este caso particular, se nos ha pedido que agreguemos una fila en la parte inferior que muestre las medias de la columna y una columna a la derecha que muestre las varianzas de la fila:
X <- rbind(X,apply(X,2,mean))
X <- cbind(X,apply(X,1,var))
X## drug.1 drug.2 drug.3 drug.4 drug.5
## [1,] 0.0 1.00 1.00 2.0 0.00 0.70000
## [2,] 1.0 4.00 2.00 3.0 0.00 2.50000
## [3,] 2.0 1.00 4.00 0.0 1.00 2.30000
## [4,] 3.0 3.00 0.00 1.0 2.00 1.70000
## [5,] 1.5 2.25 1.75 1.5 0.75 0.29375
Tenga en cuenta que el número de lugares decimales varía según las columnas, con uno en las columnas 1 y 2, dos en las columnas 3 y 4, ninguno en la columna 5 (enteros) y cinco en la columna 6. El valor predeterminado en R es imprimir el número mínimo de lugares decimales. coherente con el contenido de la columna en su conjunto.
A continuación, debemos etiquetar la sexta columna como “varianza” y la quinta fila como “media”:
colnames(X) <- c(1:5,"variance")
rownames(X) <- c(1:4,"mean")
X## 1 2 3 4 5 variance
## 1 0.0 1.00 1.00 2.0 0.00 0.70000
## 2 1.0 4.00 2.00 3.0 0.00 2.50000
## 3 2.0 1.00 4.00 0.0 1.00 2.30000
## 4 3.0 3.00 0.00 1.0 2.00 1.70000
## mean 1.5 2.25 1.75 1.5 0.75 0.29375
Cuando se crea una matriz con una sola fila o columna mediante una operación de subíndice, por ejemplo, Row <- V[1,] , se convierte de forma predeterminada en un vector. De manera similar, si se crea una matriz con una dimensión, digamos, 2 × 3 × 1 × 4 subíndice, se convertirá en una matriz de 2 × 3 × 4, perdiendo la dimensión innecesaria. Después de mucha discusión, se ha determinado que esto es una feature de R. Para evitar que esto suceda, agregue la opción drop = FALSE al subíndice. Por ejemplo:
V[1, , drop = FALSE]## [,1] [,2] [,3] [,4]
## [1,] 1 2 3 4
La opción drop = FALSE debe usarse a la defensiva al programar.
La función de barrido se utiliza para “barrer” resúmenes de matrices de vectores, matrices, matrices o marcos de datos. En este ejemplo queremos expresar una matriz en términos de las salidas de cada valor de la media de su columna.
Primero, debe crear un vector que contenga los parámetros que desea eliminar de la matriz. En este caso, queremos calcular las medias de las cuatro columnas en V:
(cols <- apply(V,2,mean))## [1] 2.5 2.5 2.5 2.5
Ahora es sencillo expresar todos los datos en V como desviaciones de la columna correspondiente significa:
sweep(V,2,cols)## [,1] [,2] [,3] [,4]
## [1,] -1.5 -0.5 0.5 1.5
## [2,] 1.5 0.5 -0.5 -1.5
Tambien podemos jugar con el dataset de mtcars
sweep(mtcars,2,cols)## Warning in sweep(mtcars, 2, cols): STATS does not recycle exactly across MARGIN
Tenga en cuenta el uso de margin = 2 como segundo argumento para indicar que queremos que el barrido se realice en las columnas (en lugar de en las filas). Una función relacionada, scale, se usa para centrar y escalar datos en términos de desviaciones estándar (p. 254).
Puede ver lo que ha hecho el barrido haciendo el cálculo a mano alzada. La operación de este barrido particular es simplemente una de resta. El único problema es que el objeto sustraído debe tener las mismas dimensiones que la matriz a barrer (en este ejemplo, 10 filas de 4 columnas). Por lo tanto, para barrer las medias de la columna, el objeto que se va a restar de matdata debe tener la media de cada columna repetida en cada una de las 10 filas de 4 columnas:
(col.means <- matrix(rep(cols,rep(10,4)),nrow=10))## [,1] [,2] [,3] [,4]
## [1,] 2.5 2.5 2.5 2.5
## [2,] 2.5 2.5 2.5 2.5
## [3,] 2.5 2.5 2.5 2.5
## [4,] 2.5 2.5 2.5 2.5
## [5,] 2.5 2.5 2.5 2.5
## [6,] 2.5 2.5 2.5 2.5
## [7,] 2.5 2.5 2.5 2.5
## [8,] 2.5 2.5 2.5 2.5
## [9,] 2.5 2.5 2.5 2.5
## [10,] 2.5 2.5 2.5 2.5
Luego, el mismo resultado que obtuvimos de barrido se obtiene simplemente por
mtcars-col.meansSuponga que desea obtener los subíndices para un barrido de datos por columnas o por filas. Aquí están los subíndices de fila repetidos en cada columna:
apply(mtcars,2,function (x) 1:10)## mpg cyl disp hp drat wt qsec vs am gear carb
## [1,] 1 1 1 1 1 1 1 1 1 1 1
## [2,] 2 2 2 2 2 2 2 2 2 2 2
## [3,] 3 3 3 3 3 3 3 3 3 3 3
## [4,] 4 4 4 4 4 4 4 4 4 4 4
## [5,] 5 5 5 5 5 5 5 5 5 5 5
## [6,] 6 6 6 6 6 6 6 6 6 6 6
## [7,] 7 7 7 7 7 7 7 7 7 7 7
## [8,] 8 8 8 8 8 8 8 8 8 8 8
## [9,] 9 9 9 9 9 9 9 9 9 9 9
## [10,] 10 10 10 10 10 10 10 10 10 10 10
Aquí están los subíndices de columna repetidos en cada fila:
t(apply(mtcars,1,function (x) 1:4))## [,1] [,2] [,3] [,4]
## Mazda RX4 1 2 3 4
## Mazda RX4 Wag 1 2 3 4
## Datsun 710 1 2 3 4
## Hornet 4 Drive 1 2 3 4
## Hornet Sportabout 1 2 3 4
## Valiant 1 2 3 4
## Duster 360 1 2 3 4
## Merc 240D 1 2 3 4
## Merc 230 1 2 3 4
## Merc 280 1 2 3 4
## Merc 280C 1 2 3 4
## Merc 450SE 1 2 3 4
## Merc 450SL 1 2 3 4
## Merc 450SLC 1 2 3 4
## Cadillac Fleetwood 1 2 3 4
## Lincoln Continental 1 2 3 4
## Chrysler Imperial 1 2 3 4
## Fiat 128 1 2 3 4
## Honda Civic 1 2 3 4
## Toyota Corolla 1 2 3 4
## Toyota Corona 1 2 3 4
## Dodge Challenger 1 2 3 4
## AMC Javelin 1 2 3 4
## Camaro Z28 1 2 3 4
## Pontiac Firebird 1 2 3 4
## Fiat X1-9 1 2 3 4
## Porsche 914-2 1 2 3 4
## Lotus Europa 1 2 3 4
## Ford Pantera L 1 2 3 4
## Ferrari Dino 1 2 3 4
## Maserati Bora 1 2 3 4
## Volvo 142E 1 2 3 4
Aquí está el mismo procedimiento usando barrido:
sweep(mtcars,1,1:10,function(a,b) b)## Warning in sweep(mtcars, 1, 1:10, function(a, b) b): STATS does not recycle
## exactly across MARGIN
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
## [1,] 1 3 5 7 9 1 3 5 7 9 1
## [2,] 2 4 6 8 10 2 4 6 8 10 2
## [3,] 3 5 7 9 1 3 5 7 9 1 3
## [4,] 4 6 8 10 2 4 6 8 10 2 4
## [5,] 5 7 9 1 3 5 7 9 1 3 5
## [6,] 6 8 10 2 4 6 8 10 2 4 6
## [7,] 7 9 1 3 5 7 9 1 3 5 7
## [8,] 8 10 2 4 6 8 10 2 4 6 8
## [9,] 9 1 3 5 7 9 1 3 5 7 9
## [10,] 10 2 4 6 8 10 2 4 6 8 10
## [11,] 1 3 5 7 9 1 3 5 7 9 1
## [12,] 2 4 6 8 10 2 4 6 8 10 2
## [13,] 3 5 7 9 1 3 5 7 9 1 3
## [14,] 4 6 8 10 2 4 6 8 10 2 4
## [15,] 5 7 9 1 3 5 7 9 1 3 5
## [16,] 6 8 10 2 4 6 8 10 2 4 6
## [17,] 7 9 1 3 5 7 9 1 3 5 7
## [18,] 8 10 2 4 6 8 10 2 4 6 8
## [19,] 9 1 3 5 7 9 1 3 5 7 9
## [20,] 10 2 4 6 8 10 2 4 6 8 10
## [21,] 1 3 5 7 9 1 3 5 7 9 1
## [22,] 2 4 6 8 10 2 4 6 8 10 2
## [23,] 3 5 7 9 1 3 5 7 9 1 3
## [24,] 4 6 8 10 2 4 6 8 10 2 4
## [25,] 5 7 9 1 3 5 7 9 1 3 5
## [26,] 6 8 10 2 4 6 8 10 2 4 6
## [27,] 7 9 1 3 5 7 9 1 3 5 7
## [28,] 8 10 2 4 6 8 10 2 4 6 8
## [29,] 9 1 3 5 7 9 1 3 5 7 9
## [30,] 10 2 4 6 8 10 2 4 6 8 10
## [31,] 1 3 5 7 9 1 3 5 7 9 1
## [32,] 2 4 6 8 10 2 4 6 8 10 2
sweep(mtcars,2,1:4,function(a,b) b)## Warning in sweep(mtcars, 2, 1:4, function(a, b) b): STATS does not recycle
## exactly across MARGIN
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
## [1,] 1 2 3 4 1 2 3 4 1 2 3
## [2,] 4 1 2 3 4 1 2 3 4 1 2
## [3,] 3 4 1 2 3 4 1 2 3 4 1
## [4,] 2 3 4 1 2 3 4 1 2 3 4
## [5,] 1 2 3 4 1 2 3 4 1 2 3
## [6,] 4 1 2 3 4 1 2 3 4 1 2
## [7,] 3 4 1 2 3 4 1 2 3 4 1
## [8,] 2 3 4 1 2 3 4 1 2 3 4
## [9,] 1 2 3 4 1 2 3 4 1 2 3
## [10,] 4 1 2 3 4 1 2 3 4 1 2
## [11,] 3 4 1 2 3 4 1 2 3 4 1
## [12,] 2 3 4 1 2 3 4 1 2 3 4
## [13,] 1 2 3 4 1 2 3 4 1 2 3
## [14,] 4 1 2 3 4 1 2 3 4 1 2
## [15,] 3 4 1 2 3 4 1 2 3 4 1
## [16,] 2 3 4 1 2 3 4 1 2 3 4
## [17,] 1 2 3 4 1 2 3 4 1 2 3
## [18,] 4 1 2 3 4 1 2 3 4 1 2
## [19,] 3 4 1 2 3 4 1 2 3 4 1
## [20,] 2 3 4 1 2 3 4 1 2 3 4
## [21,] 1 2 3 4 1 2 3 4 1 2 3
## [22,] 4 1 2 3 4 1 2 3 4 1 2
## [23,] 3 4 1 2 3 4 1 2 3 4 1
## [24,] 2 3 4 1 2 3 4 1 2 3 4
## [25,] 1 2 3 4 1 2 3 4 1 2 3
## [26,] 4 1 2 3 4 1 2 3 4 1 2
## [27,] 3 4 1 2 3 4 1 2 3 4 1
## [28,] 2 3 4 1 2 3 4 1 2 3 4
## [29,] 1 2 3 4 1 2 3 4 1 2 3
## [30,] 4 1 2 3 4 1 2 3 4 1 2
## [31,] 3 4 1 2 3 4 1 2 3 4 1
## [32,] 2 3 4 1 2 3 4 1 2 3 4
La función Aplicar se utiliza para aplicar funciones a las filas o columnas de matrices o marcos de datos. Por ejemplo, hay una matriz con cuatro filas y seis columnas:
(X <- matrix(1:24,nrow=4))## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 5 9 13 17 21
## [2,] 2 6 10 14 18 22
## [3,] 3 7 11 15 19 23
## [4,] 4 8 12 16 20 24
Tenga en cuenta que colocar la expresión a evaluar entre paréntesis (como se indica arriba) hace que el valor del resultado se imprima en la pantalla. A menudo desea aplicar una función en uno de los márgenes de una matriz. El margen 1 se refiere a las filas y el margen 2 a las columnas. Aquí están los totales de las filas (cuatro de ellos):
apply(X,1,sum)## [1] 66 72 78 84
Y aquí están los totales de columna (seis de ellas):
apply(X,2,sum)## [1] 10 26 42 58 74 90
Tenga en cuenta que en ambos casos, la respuesta producida por aplicar es un vector en lugar de una matriz. Puede aplicar funciones a los elementos individuales de la matriz en lugar de a los márgenes. El margen que especifique solo influye en la forma de la matriz resultante.
apply(X,1,sqrt)## [,1] [,2] [,3] [,4]
## [1,] 1.000000 1.414214 1.732051 2.000000
## [2,] 2.236068 2.449490 2.645751 2.828427
## [3,] 3.000000 3.162278 3.316625 3.464102
## [4,] 3.605551 3.741657 3.872983 4.000000
## [5,] 4.123106 4.242641 4.358899 4.472136
## [6,] 4.582576 4.690416 4.795832 4.898979
apply(X,2,sqrt)## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1.000000 2.236068 3.000000 3.605551 4.123106 4.582576
## [2,] 1.414214 2.449490 3.162278 3.741657 4.242641 4.690416
## [3,] 1.732051 2.645751 3.316625 3.872983 4.358899 4.795832
## [4,] 2.000000 2.828427 3.464102 4.000000 4.472136 4.898979
Aquí están los números barajados de cada una de las filas, usando muestra sin reemplazo:
apply(X,1,sample)## [,1] [,2] [,3] [,4]
## [1,] 9 18 11 16
## [2,] 1 14 23 20
## [3,] 13 10 7 4
## [4,] 21 2 3 12
## [5,] 17 6 15 8
## [6,] 5 22 19 24
Si desea aplicar una función a un vector (en lugar de al margen de una matriz), entonces use aplicar. Este es el código para generar una lista de secuencias desde 1:3 hasta 1:7 (consulte la página 30):
sapply(3:7, seq)## [[1]]
## [1] 1 2 3
##
## [[2]]
## [1] 1 2 3 4
##
## [[3]]
## [1] 1 2 3 4 5
##
## [[4]]
## [1] 1 2 3 4 5 6
##
## [[5]]
## [1] 1 2 3 4 5 6 7
La función sapply es más útil con cálculos iterativos complicados.
install.packages("data.table")## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.2'
## (as 'lib' is unspecified)
library("data.table") La tarea es determinar el número de parcelas en las que una observacion es dominante en el marco de datos. Esto implica escanear cada fila de una matriz e informar sobre el número de columna que contiene el valor máximo.
attach(mtcars)
names(mtcars)## [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear"
## [11] "carb"
Los nombres de las observaciones están representados por los codigos de la tabla anterior. Definimos la OBS mas eficiente como aquel que tiene mayor numero de parcelas. La primera tarea es crear un marco de datos que contenga solo estas observaciones (no queremos los números de parcela, ni los tratamientos, ni los valores de ninguna covariable). Para los datos, las primeras 11 columnas contienen valores de distintas observaciones de automoviles, por lo que seleccionamos todas las filas en las primeras 11 columnas de esta manera:
mpg <- mtcars[,1:11]Ahora usamos la función max.col para recorrer las 32 filas, y para cada fila devuelve el número de columna que contiene la mayor observacion:
max.col(mtcars)## [1] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 3 4 4 3
Para obtener la identidad de la mejor observacion en cada auto en ese sentido, extraemos el nombre de esta columna, utilizando el índice devuelto por max.col como subíndice del objeto llamado names(mtcars):
names(mtcars)[max.col(mtcars)]## [1] "disp" "disp" "disp" "disp" "disp" "disp" "disp" "disp" "disp" "disp"
## [11] "disp" "disp" "disp" "disp" "disp" "disp" "disp" "disp" "disp" "disp"
## [21] "disp" "disp" "disp" "disp" "disp" "disp" "disp" "hp" "disp" "hp"
## [31] "hp" "disp"
Finalmente, usamos la tabla para contar el número total de parcelas en las que cada observacion es dominante. El código se ve así:
table(names(mtcars)[max.col(mtcars)])##
## disp hp
## 29 3
Entonces, disp fue dominante en más parcelas que cualquier otra observacion, con hp en segundo lugar. El número total de observaciones que fueron dominantes en una o más parcelas se obtiene determinando la longitud de esta tabla:
length(table(names(mtcars)[max.col(mtcars)]))## [1] 2
Hay circunstancias en las que es posible que desee reordenar las dimensiones de una matriz. He aquí un ejemplo de una matriz con tres dimensiones: dos sexos, tres edades y cuatro grupos de ingresos. Para simplificar y facilitar la ilustración, los valores en la matriz son solo los números del 1 al 24 en orden (2 × 3 × 4 = 24):
data <- array(1:24, 2:4)El segundo argumento de la función matriz especifica el número de niveles en las dimensiones 1, 2 y 3 usando el generador de secuencias 2:4 para producir los números 2, 3 y 4. Así es como se ve la matriz:
data## , , 1
##
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
##
## , , 2
##
## [,1] [,2] [,3]
## [1,] 7 9 11
## [2,] 8 10 12
##
## , , 3
##
## [,1] [,2] [,3]
## [1,] 13 15 17
## [2,] 14 16 18
##
## , , 4
##
## [,1] [,2] [,3]
## [1,] 19 21 23
## [2,] 20 22 24
Hay cuatro subtablas, cada una con 2 filas y 3 columnas. Ahora damos nombres a los niveles de los factores en cada una de las tres dimensiones: estos se denominan los atributos de los dimnames y se asignan en listas como esta:
dimnames(data)[[1]] <- list("male","female")
dimnames(data)[[2]] <- list("young","mid","old")
dimnames(data)[[3]] <- list("A","B","C","D")
dimnames(data)## [[1]]
## [1] "male" "female"
##
## [[2]]
## [1] "young" "mid" "old"
##
## [[3]]
## [1] "A" "B" "C" "D"
Puede ver la ventaja de nombrar las dimensiones comparando la salida de la matriz con (abajo) y sin nombres (arriba):
data## , , A
##
## young mid old
## male 1 3 5
## female 2 4 6
##
## , , B
##
## young mid old
## male 7 9 11
## female 8 10 12
##
## , , C
##
## young mid old
## male 13 15 17
## female 14 16 18
##
## , , D
##
## young mid old
## male 19 21 23
## female 20 22 24
Sin embargo, suponga que queremos que los cuatro grupos de ingresos (A–D) sean las columnas en cada una de las subtablas y que las subtablas separadas representen los dos géneros. Este es un trabajo parapermanente. Necesitamos especificar el orden ‘edad, luego ingresos, luego género’ en términos del orden de sus dimensiones (fila, columna, subtabla, a saber, 2 luego 3 luego 1) de esta manera:
new.data <- aperm(data,c(2,3,1))
new.data## , , male
##
## A B C D
## young 1 7 13 19
## mid 3 9 15 21
## old 5 11 17 23
##
## , , female
##
## A B C D
## young 2 8 14 20
## mid 4 10 16 22
## old 6 12 18 24
Esto será difícil de ver al principio, pero debes perseverar, porque aperm es una función muy útil.