Crear una matriz aleatoria con sumas de filas constantes en R
En este artículo, veremos cómo crear una matriz con valores no negativos elegidos al azar en cada fila de modo que la suma sea constante para todas las filas.
Para simplificar, tomaremos el caso en el que todas las filas suman 1. Los vectores de fila se pueden multiplicar por cualquier número para obtener ese número como la suma de filas.
Crear una matriz aleatoria con sumas de filas constantes en R
Supongamos que queremos que cada fila tenga 4 elementos. Puede ser cualquier número entero positivo mayor que 1.
Comenzaremos con el rango de 0 a 100, que representa los percentiles. Dividiremos este rango en 4 partes usando 3 puntos de corte elegidos al azar.
Para ello, elegimos aleatoriamente 3 puntos de dicho rango. Para simplificar, elegiremos 3 números separados.
Ordenaremos los puntos de corte elegidos en orden descendente. Estos son los percentiles en los que cortaremos el rango.
Dividiremos los puntos de corte por 100. Esto nos da los puntos de corte como decimales de 0 a 1.
Obtenemos nuestras cuatro secciones de 1 de la siguiente manera:
- Obtenemos el primer elemento restando el primer punto de corte (el más grande) de 1.
- Obtenemos el segundo elemento restando el segundo punto de corte del primer punto de corte.
- Obtenemos el tercer elemento restando el tercer punto de corte (el más pequeño) del segundo punto de corte.
- Obtenemos el cuarto elemento restando 0 del tercer punto de corte.
Estos números constituyen una fila; suman 1. Debemos repetir este proceso tantas veces como filas sean necesarias.
Código para la matriz
Ahora veremos el código para obtener una matriz aleatoria con 5 filas y 4 columnas donde la suma de cada fila es 1.
Código de ejemplo:
# The final matrix.
# It begins as an empty matrix. It has 4 columns in our example.
Mx = matrix(byrow= TRUE, ncol = 4, nrow = 0)
# The number of rows. 5 rows in our example.
# We will repeat the code as many times as the number of rows we need.
for(RowNum in 1:5) {
# Cut points. With 3 cuts, we will get 4 elements.
# Randomly choose 3 different integers from the sequence 0 to 100.
cuts = sample(0:100, 3, replace = FALSE)
# Sort the cut points in descending order.
cuts.sort = sort(cuts, decreasing = TRUE)
# Convert the sorted cut points to decimals from 0 to 1.
cuts.dec = cuts.sort/100
# An empty vector to hold the current row that we will build.
Elements = c()
# The starting point for each cut.
# The first cut starts at 1. Then resets this to its value.
ElementStart = 1
# Create each element.
for(Cut in cuts.dec){
Elements = c(Elements, (ElementStart-Cut))
ElementStart = Cut
}
# Append the last element to get the full row.
# This is from the last (smallest) cut value to 0.
# (This vector can be multiplied by any number to get that number as the row sum.)
Elements = c(Elements, cuts.dec[3])
# Add the row to the matrix.
Mx = rbind(Mx, Elements)
rownames(Mx) = NULL
}
# Print the matrix.
print(Mx)
# Check that all 5 rows sum to 1.
table(apply(Mx, 1, sum))
Producción :
> # Print the matrix.
> print(Mx)
[,1] [,2] [,3] [,4]
[1,] 0.38 0.36 0.16 0.10
[2,] 0.41 0.15 0.03 0.41
[3,] 0.08 0.50 0.35 0.07
[4,] 0.17 0.15 0.06 0.62
[5,] 0.07 0.09 0.23 0.61
>
> # Check that all 5 rows sum to 1.
> table(apply(Mx, 1, sum))
1
5