create 3D (n:m:k) matrix in matlab using array 2D (i:3) - matlab

I need a 3D matrix in matlab, I have another 2D matrix (7570x3) too,
The 3D matrix should have zero number except of all dimensions in 2D matrix that should have 1 value. How can I do that.
i.e. 2D matrix (1,:) = 28,64,27 then 3d(27,64,27) should be 1
how can i do that?

Assuming a is your 2-d matrix, and b is the 3-d one, use sub2ind as follows:
b=false(max(a)); % preallocate memory for a logical zeros matrix b
b(sub2ind(size(b),a(:,1),a(:,2),a(:,3))) = 1;
Check to see what max(a) gives you to see if you can host a 3-d matrix of size(max(a) to begin with. Since you are interested in a logcial matrix (ones and zeros), the size of that matrix in memory is the same as the # of elements, n*m*l, so a 1000x1000x1000 will take 1 GB.
Note, it very well may be that b is very sparse, if that is the case you can refer to this thread to see how to deal with it. Know that at the moment, and to the best of my knowledge, matlab doesn't support 3d sparse matrices. So you may want to check this option from the FEX. When I think of it, you already have a sparse look-up table of the 3D matrix! it is just your 2D matrix you started with...

Thanks a lot #natan
for non-integer matrix also can use:
b=false(floor(max(a))); % preallocate memory for a logical zeros matrix b
b(sub2ind(size(b),floor(a(:,1)),floor(a(:,2)),floor(a(:,3)))) = 1;
or use round function:
b=false(round(max(a))); % preallocate memory for a logical zeros matrix b
b(sub2ind(size(b),round(a(:,1)),round(a(:,2)),round(a(:,3)))) = 1;

Related

Store 3x3 matrix in a variable in a for loop

I have a 9x3 matrix that I subdivided into three (3) 3x3 matrix. Now I want to make a for loop function that will store each 3x3 matrix into a variable.
X=reshape(1:27,3,9)'; % sample 9x3 matrix
xx = mat2cell(X,[3,3,3],3); % subdivide X matrix into 3x3 cell matrix
for i:1:3
x(i) = xx{i,1}; %store the three cells into x1 x2 and x3 matrix
end
I know that this does not how it works in matlab but just to show the function I would like to attain.
You can use eval function.
X=reshape(1:27,3,9)'; % sample 9x3 matrix
xx = mat2cell(X,[3,3,3],3); % subdivide X matrix into 3x3 cell matrix
for i=1:3
eval(['x' num2str(i) ' = xx{' num2str(i) ',1};']);
end
But What you are asking for is not recommended at all. In fact i always avoid using eval because the code doesn't get checked by MATLAB editor.
It is also not a good idea to have multiple variables, instead use cells, structures, and so on for a better usage in the rest of your code.
Is this what you're looking for?
X=reshape(1:27,3,9)';
for i=1:3
block = X(3*i-2:3*i,:);
disp(block);
end
The preferred way to do this is to actually just store it in a 3D array and you can access each element along the third dimension. The reason for that is that MATLAB is optimized for computing using matrices, so if you keep all of your data in a matrix, operations can be performed in a vectorized fashion on all components.
Better yet you can remove the for loop needed to create it by using reshape and permute.
X = permute(reshape(X', [3 3 3]), [2 1 3]);
% And access each element
X(:,:,1)
X(:,:,2)
X(:,:,3)
This is going to be more performance than using cell arrays or eval.

Multiplying a 3D Matrix with a 1D

I attempted to use the solution from this post: Multiply a 3D matrix with a 2D matrix, to vectorize the multiplication of a one dimensional with a three dimensional, but to no avail. Any help would be greatly appreciated!
for s = 1: s_length
for a = 1: a_length
for g = g_length
two_dim(s,a) = two_dim(s,a) + one_dim(g) * three_dim(s,a,g);
end
end
end
I think this does what you want.
two_dim = reshape(three_dim, [], size(three_dim,3))*one_dim(:);
two_dim = reshape(two_dim, size(three_dim,1), size(three_dim,2));
This works as follows:
First line reshapes your 3D array into a matrix, collapsing the first two dimensions into one. That way the operation you want is standard multiplication of the resulting matrix times a column vector.
Second line reshapes the result into matrix shape.
mtimes does not work with inputs with dimension larger than 2, so you have to find a way to do the multiplication by yourself. The solution of Luis Mendo is a nice solution; here is another one using bsxfun:
two_dim = two_dim + squeeze(sum(bsxfun(#times, three_dim, reshape(one_dim,[1 1 g_length])),3));
Here is how it works:
reshape makes the vector one_dim looking like a 3D array. This must be done because the multiplication between the vector and the 3D array is performed along the 3rd dimension, so Matlab need a hint on sizes.
bsxfun perfoms the element-wise multiplcation, so the result must be sumed up along the 3rd dimension (and squeezed to be compliant with a 2D matrix format)

Matlab - Create N sparse matrices and sum them

I have N kx1 sparse vectors and I need to multiply each of them by their transpose, creating N square matrices, which I then have to sum over. The desired output is a k by k matrix. I have tried doing this in a loop and using arrayfun, but both solutions are too slow. Perhaps one of you can come up with something faster. Below are specific details about the best solution I've come up with.
mdev_big is k by N sparse matrix, containing each of the N vectors.
fun_sigma_i = #(i) mdev_big(:,i)*mdev_big(:,i)';
sigma_i = arrayfun(fun_sigma_i,1:N,'UniformOutput',false);
sigma = sum(reshape(full([sigma_i{:}]),k,k,N),3);
The slow part of this process is making sigma_i full, but I cannot reshape it into a 3d array otherwise. I've also tried cat instead of reshape (slower), ndSparse instead of full (way slower), and making fun_sigma_i return a full matrix rather than a sparse one (slower).
Thanks for the help! ,

Cropping matrix

for examples, I have a 6x6 matrix, then I want to take out the small matrix which is located in the center of that matrix, say 2x2. Is there any smart way to do it ? Or I have to loop through the old matrix and then copying values to new one?
Thank you very much.
Of course you can. try for instance
A = rand(6,6); % // big matrix, an example
B = A(3:4,3:4); % // central sub matrix obtained using indices
which (in this case) is also equivalent to
B = A([3 4],[3 4]);
In general you can extract subvectors from a vector selecting the indices you are interested to.

Matlab 3d-matrix

I have to create a very big 3D matrix (such as: 500000x60x60). Is there any way to do this in matlab?
When I try
omega = zeros(500000,60,60,'single');
I get an out-of-memory error.
The sparse function is no option since it is only meant for 2D matrices. So is there any alternative to that for higher dimensional matrices?
Matlab only has support for sparse matrices (2D). For 3D tensors/arrays, you'll have to use a workaround. I can think of two:
linear indexing
cell arrays
Linear indexing
You can create a sparse vector like so:
A = spalloc(500000*60*60, 1, 100);
where the last entry (100) refers to the amount of non-zeros eventually to be assigned to A. If you know this amount beforehand it makes memory usage for A more efficient. If you don't know it beforehand just use some number close to it, it'll still work, but A can consume more memory in the end than it strictly needs to.
Then you can refer to elements as if it is a 3D array like so:
A(sub2ind(size(A), i,j,k))
where i, j and k are the indices to the 1st, 2nd and 3rd dimension, respectively.
Cell arrays
Create each 2D page in the 3D tensor/array as a cell array:
a = cellfun(#(x) spalloc(500000, 60, 100), cell(60,1), 'UniformOutput', false);
The same story goes for this last entry into spalloc. Then concatenate in 3D like so:
A = cat(3, a{:});
then you can refer to individual elements like so:
A{i,j,k}
where i, j and k are the indices to the 1st, 2nd and 3rd dimension, respectively.
Since your matrix is sparse, try to use ndsparse (N-dimensional sparse arrays FEX)