Array - vector multiplication in R - arrays

I need a simple matrix-algebra or Kronicker product type operation to multiply an array and a vector in R to get to a specific result. Let's say I have the array:
ar<-array(c(rep(1,9),rep(10,9),rep(100,9)),dim=c(3,3,3))
And the vector c(1,2,3). Multiplying both by * multiplies each row on each slide of the array by 1,2, and 3 respectively. However, I need an operation to get to array
ar2<-array(c(rep(1,9),rep(20,9),rep(300,9)),dim=c(3,3,3))
instead. That is, is there a simple operation that would allow me to transform ar to ar2 using the vector I specified above? Thanks!

ar * rep(1:3, each=9) should work...
For an arbitrary sized array and an arbitrary set of multipliers, you know the dimensions of your array and the axis along which you want to perform your elementwise multiplication (in this case, the z axis):
each_arg <- prod(dim(ar)[1:2])
multipliers <- sample(1:10, 3)
ar2 <- ar * rep(multipliers, each=each_arg)
You can also look at the tensorA package

Related

Save and Access Vectors in a 3D-Matrix

For my project I need to save vectors in a matrix, thus creating a multidimensional array (3D-Matrix).
Now I'm wondering on how to access my vectors.
Lets say I have a lot of vectors stored in an array c. I could access all vectors with c(i,:).
I can also perform vector operations and use buit in fuctions like norm(c(1,:))and it gives me the absolute value of the vector. Everythings fine
Now if I store a vector v in a 2D-matrix M, i can still access every element of the vector, but M(i,j,:) doesnt give me the output [vx;vy;vz]I'm looking for. Instead matlab gives three outputs resulting in problems using the built in vector operations.
Is there any way around this?
Or do I have to implement my own functions to operate on a 3d-matrix?
Edit:
If z is a vector, the output is: z = [zx zy zz]
If this vetor is stored in a 2x2x3 matrix M(2,2,3), lets say in M(1,1), the output when accessing the vector by M(1,1,:)isnt [zx zy zz].
Instead the output is: M(:,:,1) = zx M(:,:,2) = zy M(:,:,3) = zz
Thanks for pointing out to change the direction the vector is stored in the matrix.
M(i,j,:) returns a 1×1×3 array, which Matlab understand is not exactly a vector v as you want, but a three-dimensional array, which happens to have only one element with respect to the first and second indices.
You can easily remove the dimensions of length 1 with the built-in function squeeze:
A = zeros(1,1,3);
A(:,:,1:3) = [1 2 3]
A =
A(:,:,1) =
1
A(:,:,2) =
2
A(:,:,3) =
3
B = squeeze(A)
B = 3×1
1
2
3

How to get the mean of first values in arrays in matrix in Matlab

If I have a square matrix of arrays such as:
[1,2], [2,3]
[5,9], [1,4]
And I want to get the mean of the first values in the arrays of each row such:
1.5
3
Is this possible in Matlab?
I've used the mean(matrix, 2) command to do this with a matrix of single values, but I'm not sure how to extend this to deal with the arrays.
Get the first elements in all arrays of matrix, then call mean function
mean(matrix(:,:,1))
maybe you need to reshape before call mean
a = matrix(:,:,1);
mean(a(:))
You can apply mean function inside mean function to get the total mean value of the 2D array at index 1. You can do similary with array at index 2. Consider the following snapshot.
After staring at your problem for a long time, it looks like your input is a 3D matrix where each row of your formatting corresponds to a 2D matrix slice. Therefore, in proper MATLAB syntax, your matrix is actually:
M = cat(3, [1,2; 2,3], [5,9; 1,4]);
We thus get:
>> M = cat(3, [1,2; 2,3], [5,9; 1,4])
M(:,:,1) =
1 2
2 3
M(:,:,2) =
5 9
1 4
The first slice is the matrix [1,2; 2,3] and the second slice is [5,9; 1,4]. From what it looks like, you would like the mean of only the first column of every slice and return this as a single vector of values. Therefore, use the mean function and index into the first column for all rows and slices. This will unfortunately become a singleton 3D array so you'll need to squeeze out the singleton dimensions.
Without further ado:
O = squeeze(mean(M(:,1,:)))
We thus get:
>> O = squeeze(mean(M(:,1,:)))
O =
1.5000
3.0000

Creating diagonal matrix from array of matrices in MATLAB

I am interested how to create a diagonal matrix from an array of matrices.
I created an array of matrices in MATLAB:
X<62x62x1000> it consists of 1000 matrices with dimensions 62x62
I want to create a matrix of dimensions 62000x62000 with 1000 sub matrices from array X along main diagonal.
Do you have any clue how to do this, except M=blkdiag(X(:,:,1), X(:,:,2), X(:,:,3)...) because that would be to much writing.
A possible solution
M = kron(speye(1000),ones(62));
M(logical(M)) = X(:);
With kron a 62000*62000 sparse matrix M is created that contains 1000 blocks of ones on its diagonal, then replace ones with elements of X.
You can flatten out your input matrix into a column vector using (:) indexing and then pass it to diag to place these elements along the diagonal of a new matrix.
result = diag(X(:))
This will order the elements along the diagonal in column-major order (the default for MATLAB). If you want a different ordering, you can use permute to re-order the dimensions prior to flattening.
It's important to note that your resulting matrix is going to be quite large. You could use spdiags instead to create a sparse diagonal matrix
spdiags(X(:), 0, numel(X), numel(X))
A very controversial eval call can solve this very lazily, although I suspect there is a much better way to do this:
evalstring = ['M=blkdiag('];
for i = 1:999
evalstring = [evalstring, 'X(:,:,', num2str(i),'),'];
end
evalstring = [evalstring, 'X(:,:,1000));'];
eval(evalstring);

"Diagonalize" each row of a matrix

I have an n x p matrix that looks like this:
n = 100
p = 10
x <- matrix(sample(c(0,1), size = p*n, replace = TRUE), n, p)
I want to create an n x p x p array A whose kth item along the 1st dimension is a p x p diagonal matrix containing the elements of x[k,]. What is the most efficient way to do this in R? I'm looking for a way that uses outer (or some other vectorized approach) rather than one of the apply functions.
Solution using lapply:
A <- aperm(simplify2array(lapply(1:nrow(x), function(i) diag(x[i,]))), c(3,2,1))
I'm looking for something more efficient than this.
Thanks.
As a starting point, here is a humble for loop method with pre-allocation of the matrix.
# pre-allocate matrix of desired size
myArray <- array(0, dim=c(ncol(x), ncol(x), nrow(x)))
# fill in array
for(i in seq_len(nrow(x))) myArray[,,i] <- diag(x[i,])
It should run relatively fast. On my machine, for a 1000 X 100 matrix, the lapply method took 0.87 seconds, while the for loop (including the array pre-allocation) took 0.25 seconds to transform the matrix into to your desired array. So the for loop was about 3.5 times faster.
transpose your original matrix
Note also that row operations on R matrices tend to be slower than column operations. This is because matrices are stored in memory by column. If you transpose your matrix, and perform the operation this way, the time to complete the operation on 100X1000 matrix drops to 0.14, half that of the first for loop, and 7 times faster than the lapply method.

Multiplying array columns by vector

I'm new to R and I am certain that this is simple yet I can't seem to find an answer. I have an array [36,21,12012], and I need to multiply all of the columns by a vector of the same length to create a new array of the same dimensions.
If v is your vector and a is your array, in your case it would be as simple as v * a, because arrays are built column-wise. But in general, you would use sweep. For example to multiply along the rows, sweep(a, MARGIN=2, STATS=v, FUN='*').

Resources