All possible Intersections of cells in cell array : MATLAB. - 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.

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]

matrix to cell matrix of indices

Given a matrix of n dimensions, how can I convert it to a matrix of indices as seen below:
As mentioned by MATLAB documents, you can use ind2sub function:
IND = [3 4 5 6]
s = [3,3];
[I,J] = ind2sub(s,IND)
I =
3 1 2 3
J =
1 2 2 2
The function ind2sub should work. Another option is to calculate it by hand. This is easy. Note the stucture of the matrix. It is denoted by linear indexing distributed columnwise. This mean that the indices can be calculated as:
idxRow = mod(idx-1,nRows)+1;
idxCol = ceil(idx./nColumns);
This is more or less what is done in ind2sub except that function cleverly solves the problem for an N-dimensional matrix. And also have some error handling.
n = 3;
[X,Y] = meshgrid(1:n);
C = cell(n,n);
for ii = 1:n
for jj = 1:n
C{ii,jj} = [X(ii,jj) Y(ii,jj)];
end
end
Note that the X and Y matrices are probably what you are looking for, since they are matrices. To also include the cell of indices I had to use a nested loop, but there's probably a vectorised way to do that as well.
X =
1 2 3
1 2 3
1 2 3
Y =
1 1 1
2 2 2
3 3 3
C =
[1x2 double] [1x2 double] [1x2 double]
[1x2 double] [1x2 double] [1x2 double]
[1x2 double] [1x2 double] [1x2 double]
where each [1x2 double] is the requested combination of indices.

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.