When I have an array with the dimension (i,j,k) and a matrix with the dimension (j,q). How could I multiply each (,,k) with that matrix. An example makes more sense.
A <- array(c(rep(1,20), rep(2,20), rep(3,20)),dim = c(10,2,3))
B <- matrix(c(1:10), nrow = 2)
# multiply each A[,,i]%*%B
C <- array(NA, dim=c(nrow(A), ncol(B), 3))
C[] <- apply(A, 3, function(x) x%*%B)
I could get the results in this way, but I am looking for a more efficient way, for example with the ATensor package. I hope someone could help me with this problem.
Related
I have a list that includes 20 matrices. I want to calculate Pearson's correlation betweeen all matrices. but I can not find any possible code or functions? Could you please give some tips for doing so.
something like:
a=matrix(1:8100, ncol = 90)
b=matrix(8100:16199, ncol = 90)
c=matrix(sample(16200:24299),ncol = 90)
z=list(a,b,c)
I find this:
https://rdrr.io/cran/lineup/man/corbetw2mat.html and try it:
library(lineup)
corbetw2mat(z[a], z[b], what = "all")
I've got the following error:
Error in corbetw2mat(z[a], z[b], what = "all") :
(list) object cannot be coerced to type 'double'
I want a list like this for the result:
a & b
correlations
a & c
correlations
b & c
correlations
Thanks
I will create a smaller data set to illustrate the solution below.
To get pairwise combinations the best option is to compute a matrix of combinations with combn and then loop through it, in this case a lapply loop.
set.seed(1234) # Make the results reproducible
a <- matrix(1:9, ncol = 3)
b <- matrix(rnorm(9), ncol = 3)
c <- matrix(sample(1:9), ncol = 3)
sample_list <- list(a, b, c)
cmb <- combn(3, 2)
res <- lapply(seq.int(ncol(cmb)), function(i) {
cor(sample_list[[ cmb[1, i] ]], sample_list[[ cmb[2, i] ]])
})
The results are in the list res.
Note that sample is a base r function, so I changed the name to sample_list.
Consider a simple toy problem.
#build array, A, with its last dimension filled with randomly selected rows from matrix G
set.seed(1)
n=2
G = matrix(c(0,1,0,1,1,1,1,1,0), 3, 3)
inds = matrix( ceiling( 3 * runif( n^2 ) ), n, n )
A = array(0, dim = c(n, n, 3))
for(i in 1:n){
for(j in 1:n){
A[i, j, ] = G[inds[i,j],]
}
}
I would like to create a matrix, R, with each entry R[i,j] containing the row r of G such that A[i,j,] == G[r,].
Thes answer to the above is
R =[1, 2;
2, 3]
There are lots of questions here on matching rows of a matrix to a vector, but thought I'd ask the more general question.
Using row.match from the package prodsim I came up with the following, which I believe could be generalized to find any subarray of an array equal to a specified array
apply(A, c(1,2), function(x) row.match(x,G))
But perhaps there are other, better ways?
When trying to multiply the first dimension of an array by each index of a vector by the second dimension, my array is converted to a matrix and things get squirrelly. I can only do the proper multiplication long-hand.
What a mouth full...
It's easier to explain with code...
Arr <- array(runif(10*5*3), dim = c(10,5,3))
dim(Arr)
Vect <- c(1:5)
Arr[,1,1] <- Arr[,1,1]*Vect[1]
Arr[,1,2] <- Arr[,1,2]*Vect[1]
Arr[,1,3] <- Arr[,1,3]*Vect[1]
Arr[,2,1] <- Arr[,2,1]*Vect[2]
Arr[,2,2] <- Arr[,2,2]*Vect[2]
Arr[,2,3] <- Arr[,2,3]*Vect[2]
Arr[,3,1] <- Arr[,3,1]*Vect[3]
Arr[,3,2] <- Arr[,3,2]*Vect[3]
Arr[,3,3] <- Arr[,3,3]*Vect[3]
Arr[,4,1] <- Arr[,4,1]*Vect[4]
Arr[,4,2] <- Arr[,4,2]*Vect[4]
Arr[,4,3] <- Arr[,4,3]*Vect[4]
Arr[,5,1] <- Arr[,5,1]*Vect[5]
Arr[,5,2] <- Arr[,5,2]*Vect[5]
Arr[,5,3] <- Arr[,5,3]*Vect[5]
How do I clean this up to be one command?
Try:
sweep(Arr,2,Vect,FUN="*")
Cast Vect into an array first, then element multiply:
varr <- aperm(array(Vect, dim = c(5L, 10L, 3L)), perm = c(2L, 1L, 3L))
Arr <- varr * Arr
(of course we don't need to store varr if you want this in one command)
(also, turns out this is basically what sweep does under the hood...)
The aaply() function from the plyr package does exactly what you're looking for. It can operate on arrays of any dimension and split them however you like. In this case you're splitting by rows so:
library(plyr)
Arr2 <- aaply(Arr, 1, function(x,y){x*y}, Vect)
We can also replicate the 'Vect' and multiply with 'Arr'. The col is a convenient function that gives the numeric index of columns.
res1 <- Arr * Vect[col(Arr[,,1])]
Or we explicitly do the rep
res2 <- Arr* rep(Vect, each=dim(Arr)[1])
identical(res1, res2)
#[1] TRUE
Suppose I have an array of dimension (i,j,k) and I want to loop through the dimension k and calculate for each matrix(i,j) the row max and the row indices. How could I avoid a double apply function. The problem of the double apply is that it is slow because it does not handle efficient the creation of the result matrices, for example:
Array <- rnorm(10000000)
dim(Array) <- c(1, 10000000,1)
system.time(apply(Array, 3, function(x)apply(x,1,function(y)c(min(y), max(y), which.min(y), which.max(y)))))
system.time(apply(Array, 3, rowRanges))
system.time(apply(Array, 3, function(y)c(min(y), max(y), which.min(y), which.max(y))))
How could I avoid the double apply function, and is it possible to calculate the position of the min and max in a more efficient way? In this example the array is an vector but in real life it is a real array
The example was more to prove that the apply function causes overhead. The range function only calculates the min and the max and not the indices. Here the real example that I want to optimise(Notice that the first indices 10 in the example is in reallife around 1500 but then the array is around 16 gb)
Array <- rnorm(35000*36*10)
dim(Array) <- c(10, 35000,36)
test1 <- apply(Array, 3, function(x)apply(x,1,function(y)c(min(y), max(y), which.min(y), which.max(y))))
dim(test1) <- c(4, 10,36)
test2 <- apply(Array, 3, rowRanges)
dim(test2) <- c(10,2,36)
test2 <- aperm(test2, c(2,1,3))
sum(!test2 == test1[1:2,,])
I want to make array in 3 dimension.
Here is what I tried:
z<-c(160,720,420)
first_data_set <-array(dim = length(file_1), dimnames = z)
Data that I am reading is in one level. (only x and y)
There are other data in the same format, and I need to put them in the same array with the first data. So once I finish reading all data, all of them are in the same array but there is no overwriting.
So I think array has to be 3 dimensions; otherwise I cannot keep all data that I read in loop.
Say that you have two matrices of size 3x4:
m1 <- matrix(rnorm(12), nrow = 3, ncol = 4)
m2 <- matrix(rnorm(12), nrow = 3, ncol = 4)
If you want to place them in an array, first make an array of NA's:
A <- array(as.numeric(NA), dim = c(3,4,2))
Then populate the layers with data:
A[,,1] <- m1
A[,,2] <- m2
As suggested by #Justin, you could also just put the matrices together in a list:
A2 <- list()
A2[['m1']] <- m1
A2[['m2']] <- m2
To read matrices from files: using a list makes it easier to get these matrices from files in a directory, without having to specify the dimensions in advance. Assume you want all files with extension csv:
myfiles <- dir(pattern = ".csv")
for (i in 1:length(myfiles)){
A2[[myfiles[i]]] <- read.table(myfiles[i], sep = ',')
}