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]
Related
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))];
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
I've been trying to come up with a smart way of doing this for a while. Given a matrix (or cell) with the following structure:
A = [-1 1
-1 2
1 3
3 5
2 3
2 4
2 7
4 5
5 6
6 7
7 -2 ]
(Note that the above matrix/cell is unsorted in both columns and contains negative numbers).
How could one group it by the unique values of a particular column. E.g. the desired output for grouping by the second column would be something like:
B{1} = [-1]
B{2} = [-1]
B{3} = [1,2]
B{4} = [2]
B{5} = [3,4]
B{6} = [5]
B{7} = [2,6]
B{-2} = [7]
Thanks in advance!
You can use accumarray:
[~,~,subs] = unique(A(:,2));
values = accumarray(subs,A(:,1),[],#(x) {x});
ofGroup = accumarray(subs,A(:,2),[],#(x) {x(1)});
out = [ofGroup values]
out =
[-2] [ 7]
[ 1] [ -1]
[ 2] [ -1]
[ 3] [2x1 double]
[ 4] [ 2]
[ 5] [2x1 double]
[ 6] [ 5]
[ 7] [2x1 double]
If you REALLY insist on your order proposed, you could do the following, but I don't think that should be necessary.
% positives
pos = A( A(:,2) >= 0 , :);
[~,~,subs] = unique(pos(:,2));
posvalues = accumarray(subs,pos(:,1),[],#(x) {x});
posofGroup = accumarray(subs,pos(:,2),[],#(x) {x(1)});
% negatives
neg = A( A(:,2) < 0 , :);
[~,~,subs] = unique(neg(:,2));
negvalues = flipud( accumarray(subs,neg(:,1),[],#(x) {x}) );
negofGroup = flipud( accumarray(subs,neg(:,2),[],#(x) {x(1)}) );
out = [posofGroup posvalues; negofGroup negvalues ]
out =
[ 1] [ -1]
[ 2] [ -1]
[ 3] [2x1 double]
[ 4] [ 2]
[ 5] [2x1 double]
[ 6] [ 5]
[ 7] [2x1 double]
[-2] [ 7]
How about:
[group, ~, subs] = unique(A(:,2))
B = accumarray(subs, A(:,1), [], #(x){x'})
Results in
B=
[ 7]
[ -1]
[ -1]
[2,1]
[ 2]
[4,3]
[ 5]
[2,6]
and group matches the index of B to the number of the group it represents
Also if you are attached to your ordering then you can do this:
[group, ~, subs] = unique(A(end:-1:1,2), 'stable');
B = flipud(accumarray(subs, A(end:-1:1,1), [], #(x){x'}));
group = flipud(group);
B =
[ -1]
[ -1]
[1x2 double]
[ 2]
[1x2 double]
[ 5]
[1x2 double]
[ 7]
group =
1
2
3
4
5
6
7
-2
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.
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.