How to rank a vector inside a matrix? in R - r

I have made a matrix where each element in the matrix is a vector of two numbers.
Now I want to rank all the vectors inside, so I get the rank of the vectors as the new vector elements of the matrix.
Here is an example of the code:
listwvectors <- vector("list")
t=1
for (i in 1:3) {
for (j in 1:5) {
listwvectors[[t]] <- c(i,j)
t=t+1
}
}
print(listwvectors)
testmatrix <- matrix(data=listwvectors, nrow=5, ncol=3)
print(testmatrix)
rank(testmatrix[1,1])
The last part ("rank(testmatrix[1,1])") just give 1.
Why is that? I want it to print the ranked vector.
So in fact, I want to make a new matrix that has the same mode as the testmatrix but the vectors inside is the ranked vectors of the testmatrix.
Hope you understand what I am trying to ask.
Thanks in advance!:)

minimal example data:
m <- matrix(list(c(1,3), c(2,1), c(2,2), c(1,2)), ncol=2)
[, 1] [, 2]
[1, ] c(1, 3) c(2, 2)
[2, ] c(2, 1) c(1, 2)
Solution 1 using apply (returns '3d matrix'):
apply(apply(m, c(1,2), function(x) rank(x[[1]]))
Solution 2 using loop (returns '2d matrix' of lists):
result <- m # copy original matrix as template to recieve rankings
for (i in seq_along(m[, 1])) {
for (j in seq_along(m[1, ])) {
result[i, j][[1]] <- rank(m[i, j][[1]])
}
}

since there is only one vector inside a matrix, you can use rank(my_matrix)

Related

for loop question in r :number of items to replace is not a multiple of replacement length

all
I'm new to R. I try many ways and still cannot solve it. Can anyone help to check??
I am trying to produce 3 times 100 random values that follow a chisquare distribution. Console says ''number of items to replace is not a multiple of replacement length''. Any hint to fix it??
for(i in 1:3) {
x1[i] <- rchisq(100, df=2)
n1[i] <- length(x1[i])
}
As an explanation for your problem: You are trying to store a vector of 100 elements into a single element, the ith element, of a vector, x1. To illustrate, you could put a vector of values into a vector of the same length:
x <- rnorm(6, 0, 1)
x[1:3] <- c(1,2,3)
x
## [1] 1.0000000 2.0000000 3.0000000 -0.8652300 1.3776699 -0.8817483
You could to store them into a list, each element of a list is a vector that can be of any length. You will need double square brackets.
x1 <- list()
for(i in 1:3) {
x1[[i]] <- rchisq(100, df=2)
n1[i] <- length(x1[[i]])
}
Lists and vectors are different types of data structures in R, you can read a lot about them in advanced R.
It depends on what containers you want to use. There are two containers that come to mind, either a list or matrix.
# list format
x1 = list();
n1 = vector();
for(i in 1:3) {
x1[[i]] <- rchisq(100, df=2)
n1[i] <- length(x1[[i]])
}
note the double brackets [[i]] as mentioned in the comments
# matrix format
x1 = matrix(NA, nrow = 100, ncol = 3)
n1 = vector();
for(i in 1:3) {
x1[,i] <- rchisq(100, df=2)
n1[i] <- length(x1[,i])
}

Is there another way to write the following function without the for loop in R?

I am trying to write the following function without the for loop. Note that I am trying to replicate the function diag().
selfdiag <- function(a) {
j <- c()
for (i in 1:ncol(a)) {
j[i] <- a[i, i]
}
return(j)
}
Consider that:
mat <- matrix(rnorm(4), ncol = 2)
The function selfdiag() should create the same result as diag().
Thanks for any help on this.
You can create a data frame with the row and column indices for the diagonal and use it to extract the diagonal values from the matrix.
mat <- matrix(rnorm(4), ncol = 2)
The diag() way to do it -
diag(mat)
[1] -0.5004046 -0.8785558
The other way to do it -
rows_cols <- data.frame(rows = c(1:ncol(mat)), cols = c(1:ncol(mat)))
mat2 <- mat[as.matrix(rows_cols)]
mat2
[1] -0.5004046 -0.8785558
Hope this helps!

R - Given a matrix and a power, produce multiple matrices containing all combinations of matrix columns

Given a matrix mat (of size N by M) and a power, p (e.g., 4), produce p matrices, where each p-th matrix contains all possible combinations of the columns in mat at that degree.
In my current approach, I generate the p-th matrix and then use it in the next call to produce the p+1th matrix. Can this be 'automated' for a given power p, rather than done manually?
I am a novice when it comes to R and understand that there is likely a more efficient and elegant way to achieve this solution than the following attempt...
N = 5
M = 3
p = 4
mat = matrix(1:(N*M),N,M)
mat_1 = mat
mat_2 = t(sapply(1:N, function(i) tcrossprod(mat_1[i, ], mat[i, ])))
mat_3 = t(sapply(1:N, function(i) tcrossprod(mat_2[i, ], mat[i, ])))
mat_4 = t(sapply(1:N, function(i) tcrossprod(mat_3[i, ], mat[i, ])))
Can anyone provide some suggestions? My goal is to create a function for a given matrix mat and power p that outputs the p different matrices in a more 'automated' fashion.
Related question that got me started: How to multiply columns of two matrix with all combinations
This solves your problem.
N = 5
M = 3
p = 4
mat = matrix(1:(N*M),N,M)
f=function(x) matrix(apply(x,2,"*",mat),nrow(x))
rev(Reduce(function(f,x)f(x), rep(c(f), p-1), mat, T,T))
You can do something like this
N = 5
M = 3
p = 4
mat = matrix(1:(N*M),N,M)
res_mat <- list()
res_mat[[1]] <- mat
for(i in 2:p) {
res_mat[[i]] <- t(sapply(1:N, function(j) tcrossprod(res_mat[[i-1]][j, ], res_mat[[1]][j, ])))
}

R: Efficient way to convert factor into binary matrix

I'd like to convert a size n factor into a n×n binary matrix whose (i, j) element is 1 if i-th and j-th element of factor are same and 0 otherwise.
The following is a naive way to implement what I want to do but this code is quite slow. Is there any more efficient way to do the same thing?
size <- 100
id <- factor(sample(3, size, replace=TRUE))
mat <- matrix(0, nrow=size, ncol=size)
for(i in 1:size){
for(j in 1:size){
if(id[i] == id[j]){
mat[i, j] <- 1
}
}
}
Another alternative, which should be relatively fast
tcrossprod(model.matrix( ~ id + 0))
Similarly to Hong Ooi's answer you can use also sparse matrices
library(Matrix)
tcrossprod(sparse.model.matrix( ~ id + 0))
outer can be used for this.
mat <- outer(id, id, "==")
Since the output is a binary matrix, and O(N^2) objects are kind of large, this is a good use case for sparse matrices:
library(Matrix)
mat <- Matrix(nrow=100, ncol=100)
mat[] <- outer(id, id, "==") # [] means to assign into the existing 'mat' matrix

R applying a function to a sub-matrix [duplicate]

If I have an array A
A <- array(0, c(4, 3, 5))
for(i in 1:5) {
set.seed(i)
A[, , i] <- matrix(rnorm(12), 4, 3)
}
and if I have matrix B
set.seed(6)
B <- matrix(rnorm(12), 4, 3)
The code to subtract B from the each matrix of the array A would be:
d<-array(0, c(4,3,5))
for(i in 1:5){
d[,,i]<-A[,,i]-B
}
However, what would be the code to perform the same calculation using a function from "apply" family?
This is what sweep is for.
sweep(A, 1:2, B)
Maybe not very intuitive:
A[] <- apply(A, 3, `-`, B)
Because you are looping on the last array dimension, you can simply do:
d <- A - as.vector(B)
and it will be much faster. It is the same idea as when you subtract a vector from a matrix: the vector is recycled so it is subtracted to each column.

Resources