Transfering elements of 2D array into cell array - matlab

Is there a way to instantly transfer elements of an n x n numerical array into an n x n cell array and vice versa so that each cell in the cell array has element's row, column, and value? E.g.,
Input:
A=[8 7 8 4 5;
7 0 7 4 4;
4 3 3 8 6;
7 0 10 8 7;
2 1 0 2 8;];
B=cell(5,5);
Output:
B{1}=[1 1 8];
B{2}=[2 1 7];
B{3}=[3 1 4];
B{4}=[4 1 7];
B{5}=[5 1 2];
B{6}=[1 2 7];
and so on...

Here's one approach:
dim=length(A); %//square matrix
cols = repmat(1:dim,dim,1);
rows = cols';
B=reshape(num2cell([rows(:) cols(:) A(:)],2),dim,dim);
You could wrap this piece of code in a function if you are going to use it often, to "instantly" transfer the elements of the matrix to the cell array.

Maybe using arrayfun
[row, col] = ndgrid(1:size(A,1));
B=arrayfun(#(x,y,z) [x y z], row(:), col(:), A(:), 'uni', 0);
Interesting point is that if you use
B=arrayfun(#(x,y,z) [x y z], row, col, A, 'uni', 0);
you get cell array B with the same size as A where each element is in its corresponding element in A.

Related

Building matrices using column vector and matrix in matlab

I have a column vector A (6x1) with values [6 3 10 4 2 8]'; and a matrix B (6x5) with values
B = [1 2 3 0 4 ;
3 7 8 5 0 ;
0 9 1 0 1 ;
5 0 3 1 2 ;
4 6 7 6 4 ;
3 1 2 7 3]
I want to make five matrices with size 6x2 using Matlab.
The first column is vector A
The second column is columns from B, like [A, B(first col)], [A, B(second col)]
First matrix is [6 1; 3 3; 10 0; 4 5; 2 4; 8 3];
2nd matrix is [6 2; 3 7; 10 9; 4 0; 2 6; 8 1]
... and so on
Any help I really appreciate it
You could use a loop
C = NaN( size(B,1), 2, size(B,2) );
for ii = 1:size(B,2)
C(:,:,ii) = [A, B(:,ii)];
end
This gives you a 3D array, where each slice in the 3rd dimension is a 6x2 matrix (for this example) as desired. You would access the nth slice with C(:,:,n).
You can do this slightly more concisely with arrayfun, but it's basically a loop in disguise
C = arrayfun( #(ii) [A, B(:,ii)], 1:size(B,2), 'uni', 0 );
C = cat(3, C{:} );
You could omit the cat function if you're happy with results in a cell array, where you access the nth matrix with C{n}.
You could first make a copy of the columns of A, then concatenate A and B, and reshape:
At = repmat(A, 1, size(B,2));
C = reshape([At;B], 6, 2, []);
Or oneliner:
C = reshape([repmat(A, 1, size(B,2));B], 6, 2, []);
Then retrieve your matrices with C(:,:,k)
you can use this
first_matrix=[A,B(:,1)];
second_matrix=[A,B(:,2)];
third_matrix=[A,B(:,3)];
... and so on

how can one obtain all combinations of a vector?

I want to find all possible variations (combinations) of a vector, choosing various numbers of elements from that vector.
For example, suppose I have the vector:
x = [1 2 3 4 5];
I can determine the number of combinations for each number of chosen elements:
x = [1 2 3 4 5]';
n = numel(x);
for k = 1:n
combs(k) = nchoosek(n,k);
end
sum(combs)
This results in:
combs = 5 10 10 5 1
sum(combs) = 31
I want a way to store all 31 of these combinations in an array, for example a cell array, with n cells, within each is an array in which each row is a vector combination of the elements.
e.g. at k = 4:
combs{4} =
1 2 3 4
1 2 3 5
1 2 4 5
1 3 4 5
2 3 4 5
Is there an existing function that does this, or what would be the most simple approach to this?
Call nchoosek with a vector as first input, using arrayfun (or equivalently for) to loop over the number of picked elements:
n = 5;
combs = arrayfun(#(k) nchoosek(1:n,k), 1:n, 'UniformOutput', false);
Here is an approach using dec2bin , find and accumarray:
x = [1 2 3 4 5];
[a b] = find(dec2bin(1:2^numel(x)-1)=='1');
combs = accumarray(a,x(b),[],#(c){c});

Extract values from 2d array with indices from another array (without loops)

I have an array [2; 3] and a matrix [ 1 3 4 5; 2 4 9 2].
Now I would like to extract the second element from the first row and the third element from the second row and thus obtain [3 ; 9]. I managed it to do it with a loop, but since I'm working with much larger arrays, I would like to avoid these.
You can use sub2ind to convert each of the column subscripts (along with their row subscripts) into a linear index and then use that to index into your matrix.
A = [1 3 4 5; 2 4 9 2];
cols = [2; 3];
% Compute the linear index using sub2ind
inds = sub2ind(size(A), (1:numel(cols)).', cols);
B = A(inds)
% 3
% 9
Alternately, you could compute the linear indices yourself which is going to be more performant than sub2ind
B = A((cols - 1) * size(A, 1) + (1:numel(cols)).');
% 3
% 9
By exploiting the diag function, you can obtain an elegant one-line solution:
A = [1 3 4 5; 2 4 9 2];
cols = [2; 3];
B = diag(A(:,cols))
% 3
% 9
Here is what diag(A(:,cols)) does:
A(:,cols) selects the columns cols of A, with column k of A(:,cols) corresponding to the column cols(k) of A, giving [3 4; 4 9];
diag returns the diagonal entries of this matrix, thus returning at position k the k-th diagonal element of A(:,cols), which is A(k,cols(k)).

How do you pick out the ith matrix in a n-dimensional matrix?

For the sake of argument, let's say I have this 3 x 3 x 2 matrix:
A = [5 7 8; 0 1 9; 4 3 6];
A(:,:,2) = [1 0 4; 3 5 6; 9 8 7];
And I'd like to pick out the first matrix (dimension: 3 x 3 x 1), how do I do it?
Short answer, already in the comments, is:
A(:,:,1)
Longer answer:
You can pick out any (hyper)-rectangular subset of a matric by simply specifying the elements you want per dimension, weather there are 1, 2, 3, 4 or more dimensions in the array. In short:
Each dimension is specified, in order. Dimension 1 is specifies row, dimension 2 specifies column, dimensions 3 and up are not usually visualized, so just represnt 3 and up
For each dimension you can specify one of the following: a) A single index number, b) A vector of index numbers, or c) a logical vector the same length as the dimension you are selecting from d) :, which represents all elements in this dimension.
Per dimension specifiers are ANDed together, resulting in a (hyper)-rectangular array.
For example, using your A array:
A = [5 7 8; 0 1 9; 4 3 6];
A(:,:,2) = [1 0 4; 3 5 6; 9 8 7];
To subset the first matrix you need: all of dimension 1 ":", all of dimension 2 ":", and the first element of dimension 3 "1". Therefore:
A(:,:,1) %Returns 5 7 8
% 0 1 9
% 4 3 6
To get the first and third columns of the second page, use:
A(:, [1 3], 2) %Returns 1 4
% 3 6
% 9 7
To get all rows which end in 9 from the first matrax, you can use:
mask = A(:,3,1)==9; %Returns logical [0; 1; 0];
A(mask, :, 1); %Returns [0 1 9;

Matlab - find function between matrix and cell array

I’ve a matrix A = (4*4) and a cell array B {4,1}. I’d like to find all the values of B in A, searching row by row and after I’d like to delete the correspondent column associated to this particular value. I’ve a problem using bsxfun o cellfun and find function with a matrix and a cell array. I‘ve tried to convert the cell array into a matrix but I don’t have more the exact correspondence.
For example:
A =
1 5 10 23
2 4 2 18
3 3 5 14
1 9 10 4
B =
1
2 4
3 3 14
1
To obtain:
C =
10
2
5
10
Thanks in advance,
L.
Here's how:
C = cellfun(#(x, y){sparse(1,find(ismember(x,y),numel(y)),true,1,size(A,2))}, ...
mat2cell(A, ones(size(A, 1), 1), size(A, 2)), B(:));
C = A(:, all(~vertcat(C{:})));
The cellfun is fed with two cell arrays: the first one contains the rows of A and second one is B. The anonymous function is the tricky part; it operates on a pair of two corresponding rows as follows:
It employs ismember to check which columns in A contain any of the elements in B.
It uses find to pick only the first N ones, with respect to the number of elements in the B.
It uses sparse as a fancy way of zeroing out the rest of the elements.
For your example it would look like this:
A = [1 5 10 23; 2 4 2 18; 3 3 5 14; 1 9 10 4];
B = {1; [2 4]; [3 3 14]; 1};
C = cellfun(#(x, y){sparse(1,find(ismember(x,y),numel(y)),true,1,size(A,2))}, ...
mat2cell(A, ones(size(A, 1), 1), size(A, 2)), B(:));
which yields:
C =
{
[1 0 0 0]
[1 1 0 0]
[1 1 0 1]
[1 0 0 0]
}
After that, it's a simple matter of logical indexing to pick the resulting columns:
C = A(:, all(~vertcat(C{:})));
which in this case should be:
C =
10
2
5
10