select entries and put in a matrix without loop - matlab

I have the following:
b = [1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double]
whose dimensions are variable.
b{1}
ans =
0 0 0 0
I want to put the first entry of each of the 10 vectors as the first column of matrix A
2nd column of matrix A will be as v the 1st entry of each of the 10 vectors of r:
r =
[1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double] [1x4 double]
r{1} --> ans = 10 10 10 10
This is what i need to get:
A =
v{1}(1) r{1}(1)
v{2}(1) r{2}(1)
v{3}(1) r{3}(1)
How to do that without a loop is there a way?

Some example data:
b = {[ 101:104 ], [ 201:204 ], [ 301:304 ], [ 401:404 ], [ 501:504 ], [ 601:604 ], [ 701:704 ], [ 801:804 ], [ 901:904 ], [ 1001:1004 ]};
r = {[ 2101:2104 ], [ 2201:2204 ], [ 2301:2304 ], [ 2401:2404 ], [ 2501:2504 ], [ 2601:2604 ], [ 2701:2704 ], [ 2801:2804 ], [ 2901:2904 ], [ 3001:3004 ]};
Edit: a lot faster solution without looping by using vertcat.
Edit: corrected a typo in code.
bMatrix = vertcat(b{:});
rMatrix = vertcat(r{:});
A = [ bMatrix(:,1), rMatrix(:,1) ];
A lot slower solution by using cellfun (cellfun does loop) :
A = [ cellfun(#(x) x(1), b)', cellfun(#(x) x(1), r)' ];
Or in parts:
ColumnOneOfMatrixA = cellfun(#(x) x(1), b)';
ColumnTwoOfMatrixA = cellfun(#(x) x(1), r)';
A = [ ColumnOneOfMatrixA, ColumnTwoOfMatrixA ];
Both ways give the same result.
A =
101 2101
201 2201
301 2301
401 2401
501 2501
601 2601
701 2701
801 2801
901 2901
1001 3001

As Dan notes, cellfun is the trick to avoiding this loop.
%Setup test data
for ix = 1:10
b{ix} = ones(1,4)*(ix-1);
r{ix} = ones(1,4)*(ix+9);
end
%Cellfun based definition of the "A" matrix
A = [...
cellfun( #(x)x(1), b(1:10) ); ...
cellfun( #(x)x(1), r(1:10) ); ...
]';
Here the cellfun calls have been set up to return a numeric array containikng the first element of each numeric array in the cell array. The anonymous function #(x)x(1) serves as the core, just returning the first element, and cellfun takes care of implementing the appropriate looping without bothering you with the details.
Note that cellfun is usually not any faster than the loop that it replaces. It simply requires less typing, and is arguably easier to read after you learn to work with it.

Related

Indexing Cell arrays for more efficient performance

I have the following code to display a 9-by-3 cell array:
data = cell (9,3);
col1 = [2, 3, 5, 7, 8, 11, 12, 15, 16];
col2 = {[1 1], [1 5], [3 9], [4 2], [4 6], [6 2], [7 6], [6 9], [9 9]};
col3 = {[2 3 4 5 8],[1 3 5 8],[1 2 5 7 8],[1 2 3 6 7],[3 4 7 8],[2 4 8 9],[2 4 5 9],[4 5 7 9],[2 6 7 8]};
k = length(data);
for i = 1:k
data{i,1} = col1(i);
data{i,2} = col2{i};
data{i,3} = col3{i};
end
data
Please, can this code be more efficiently written using a form of indexing? Thanks.
Your have written code to assign a 9 x 3 cell array, which can also be written as:
data2 = [num2cell(col1') col2' col3']
data2 =
[ 2] [1x2 double] [1x5 double]
[ 3] [1x2 double] [1x4 double]
[ 5] [1x2 double] [1x5 double]
[ 7] [1x2 double] [1x5 double]
[ 8] [1x2 double] [1x4 double]
[11] [1x2 double] [1x4 double]
[12] [1x2 double] [1x4 double]
[15] [1x2 double] [1x4 double]
[16] [1x2 double] [1x4 double]

Inserting elements of a cell array into another cell array

How to insert elements of a cell array into another cell array without a for loop?
The elements of the cell A are all integers.
Input:
A = [1x2 double] [1x2 double]
[1x2 double] [1x2 double]
[1x2 double] [1x2 double]
[1x2 double] [1x2 double]
[1x2 double] [1x2 double]
[1x2 double] [1x2 double]
A{1}=[2 5]
A{2}=[6 8]
B=[8] [7]
[7] [0]
[4] [3]
[7] [0]
[2] [1]
[1] [2]
C=cell(6,2);
Output:
C{1}=[A{1} B{1}];
C{2}=[A{2} B{2}];
Some classic use of cellfun maybe
C=cellfun(#horzcat, A, B, 'uni', 0)
Is that possible:
B = reshape(B, [], 1);
C = [A(:) B(1:length(A))];

Assigning a value from a cell array to a numerical arrray

How to assign a value from a cell array to a numerical array efficiently? A and B are always square matrices of any size. For simplicity I just allocated small matrices. If for example A{1}=[2 3 8]; then I want allocate value 8 in second row and third column of the B matrix.
E.g.,
Input
A=[1x3 double] [1x3 double] [1x3 double] [1x3 double]
[1x3 double] [1x3 double] [1x3 double] [1x3 double]
[1x3 double] [1x3 double] [1x3 double] [1x3 double]
[1x3 double] [1x3 double] [1x3 double] [1x3 double]
B=zeros(4,4);
A{1}=[2 3 8];
A{2}=[3 4 7];
and so on...
Output
B(2,3)=8;
B(3,4)=7;
and so on...
Use spconvert:
B = full(spconvert(cat(1, A{:})));
You can do this without loops:
B=zeros(4,4);
A{1}=[2 3 8];
A{2}=[3 4 7];
C = cell2mat(A);
C = reshape(C,3,size(C,2)/3)';
indices = sub2ind(size(B), C(:,1), C(:,2));
B(indices) = C(:,3);
For your example this results in:
B =
0 0 0 0
0 0 8 0
0 0 0 7
0 0 0 0
Using sub2ind and indexing
%// creating a sample cell array. Replace this with your actual cell array
A = {[1 2 8] [1 1 4]; [2 1 5] [2 2 1]};
%// Reshaping the cell array to kx3 matrix
Amat = cat(1,A{:}); %// from luis' answer
%// taking first column as row sub, 2nd col as col sub
%// The subs are converted into linear indices to the size of A or B
ind = sub2ind(size(A),Amat(:,1),Amat(:,2));
%// You have done this (helps in fixing the dimensions of B)
B = zeros(size(A));
%// Taking last col of 'Amat' as values and assigning to corresponding indices
B(ind) = Amat(:,3);
Results:
>> B
B =
4 8
5 1
I would suggest looping once over the A cells to find the maximum index values, let's say max_i,max_j.
Then initialize B like:
B=zeros(max_i,max_j)
And loop again over the A cells and assign th values to the corresponding B elements.
Edit: Added example code:
max_i=0
max_j=0
for k=1:size(A,1)
for l=1:size(A,2)
max_i=max([A{k,l}(1),max_i])
max_j=max([A{k,l}(2),max_j])
end
B=zeros(max_i,max_j)
for k=1:size(A,1)
for l=1:size(A,2)
B(A{k,l}(1),A{k,l}(2))=A{k,l}(3)
end

matrix operation where the values can be expressed as a set

Is it possible to obtain a matrix as follows??
The input vectors are X(column vector) and Y(row vector)
X=[2 Y=[5 3 1 2 4]-1*5 vector
4
5
3
1]-5*1 vector
both vectors have the index values as elements. Now I want to have a 5*5 matrix which is as follows:
Z= (2,5) (2,3) (2,1) (2,2) (2,4)
(4,5) (4,3) (4,1) (4,2) (4,4)
(5,5) (5,3) (5,1) (5,2) (5,4)
(3,5) (3,3) (3,1) (3,2) (3,4)
(1,5) (1,3) (1,1) (1,2) (1,4)
Z-5*5 matrix
is it possible to obtain a matrix like this using matlab...pls help....i have no idea how to do this....thanks in advance...
Here's an alternative solution using a cell array instead of a regular array:
XX=meshgrid(X);
YY=meshgrid(Y);
C=reshape(num2cell([XX(:) YY(:)],2),numel(X),[]);
The outcome will be a 5x5 cell array,
C =
[1x2 double] [1x2 double] [1x2 double] [1x2 double] [1x2 double]
[1x2 double] [1x2 double] [1x2 double] [1x2 double] [1x2 double]
[1x2 double] [1x2 double] [1x2 double] [1x2 double] [1x2 double]
[1x2 double] [1x2 double] [1x2 double] [1x2 double] [1x2 double]
[1x2 double] [1x2 double] [1x2 double] [1x2 double] [1x2 double]
each element will contain the 2 numbers. For example:
C{2,2}
ans =
4 3
Maybe this is what you want:
Z = cat(3, repmat(X, 1, size(Y,2)), repmat(Y, size(X,1), 1));
This builds a 3D-array Z such that Z(m,n,:) gives the m,n entry of your "matrix".
However, depending on what you want to achieve, there are probably better ways to do it.

All possible Intersections of cells in cell array : MATLAB.

Consider a cell array ,
H = [ {N1x1} {N2x1} {N3x1} ...{Nmx1} ]
How does get (efficiently) all pairwise intersections of these cells?
Not sure how efficient this will be.
N = numel(H);
[ii jj] = ndgrid(1:N);
result = arrayfun(#(n) intersect(H{ii(n)},H{jj(n)}), 1:N^2, 'uni', 0);
result = reshape(result,N,N);
Example:
H = {[1 2 3], [2 3], [4 5]};
gives
result =
[1x3 double] [1x2 double] [1x0 double]
[1x2 double] [1x2 double] [1x0 double]
[1x0 double] [1x0 double] [1x2 double]
>> result{1,1}
ans =
1 2 3
>> result{1,2}
ans =
2 3
>> result{1,3}
ans =
Empty matrix: 1-by-0
[..]
This also works if H is a multidimensional cell array.
You could also use two for loops. Then you could save half operations explotiing the symmetry of the result.