matrix to cell matrix of indices - matlab

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.

Related

Searching a matrix by row and column

Lets say I have the matrix
dataSet = [400,300,200,100,200,300,400;
1, 2, 3, 4, 5, 6, 7]
This will give me a 2x7 array with the larger numbers on row 1 and the smaller on row 2.
Lets say I am given the number 200 and asked to find what all the numbers below 200 are. The answer is 3 and 5, because they both correspond to 200, but how can I code this into my script?
>> dataSet(2,dataSet(1,:) == 200)
ans =
3 5
Is this what you want?
[t, ~, u] = unique(dataSet(1,:));
result = accumarray(u, dataSet(2,:).', [], #(x) {x.'});
result = [num2cell(t).' result];
In your example, this gives:
>> result
result =
[100] [ 4]
[200] [1x2 double]
[300] [1x2 double]
[400] [1x2 double]
with
result{2,2} =
3 5
result{3,2} =
2 6
etc

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

comparing rows of a logical matrix in matlab?

I have sentences cross words [4 cross 5] matrix as follows:
out=
0 1 1 0 1
1 1 1 0 0
0 0 1 1 0
1 1 0 1 1
I want to create a 1D cell array based upon above matrix which should tell in which two sentences same words appear with value = 1 i.e. let's take line 1 and line 2 in which at 2 points column 2 and column 3 the logical matrix has both 1's in row 1 and row 2 this information should be stored in 1D cell array.
suppose above example it's output would be as:
output{1,1} = []
output{1,2} = [2 3]
output{1,3} = [3]
.....
output{n,n} = [....]
where {1,1} tells sentence 1 relation with sentence 1 on the basis of value=1 of words, {1,2} tells sentence 1 relation with sentence 2 on the basis of value=1 of words and so on...
Try this:
x = [ 0 1 1 0 1
1 1 1 0 0
0 0 1 1 0
1 1 0 1 1];
[ii, jj] = ndgrid(1:size(x,1));
y = arrayfun(#(m,n) find(x(m,:) & x(n,:)), ii, jj, 'uniformoutput', 0);
Result:
y{1,1} =
2 3 5
y{2,1} =
2 3
y{3,1} =
3
y{4,1} =
2 5
[...]
If you want the diagonal elements to be empty:
y = arrayfun(#(m,n) find(x(m,:) & x(n,:) & m~=n), ii, jj, 'uniformoutput', 0)
Result:
y{1,1} =
[]
y{2,1} =
2 3
y{3,1} =
3
y{4,1} =
2 5
[...]
If you want something written quick... and since we are dealing with cell arrays, the easiest thing would be to have a pair of for loops. Assuming that you have your matrix defined in out:
out_cell = cell(size(out,1),size(out,1));
for idx = 1 : size(out,1)
for idx2 = 1 : idx
vals = find(out(idx,:) & out(idx2,:));
out_cell{idx,idx2} = vals;
out_cell{idx2,idx} = vals;
end
end
For each pair of rows, idx and idx2, we look to see if any columns match in terms of having a 1, then place the indices into its respective cell location in the 2D cell array. Note that because will encounter pairs of rows that are duplicates (i.e. checking row 3 and row 5, compared to row 5 and row 3), there is no need for the second for loop to iterate all over the other rows. We only need to check up to the current row that is described by the outer loop and we simply write the same values with the row indices swapped... so this is a "symmetric" matrix.
If you would like the diagonal elements to be empty, simply change the inner for loop so that it goes for idx2 = 1 : idx-1, instead of for idx2 = 1 : idx.
With your example, we get:
>> out_cell
out_cell =
[1x3 double] [1x2 double] [ 3] [1x2 double]
[1x2 double] [1x3 double] [ 3] [1x2 double]
[ 3] [ 3] [1x2 double] [ 4]
[1x2 double] [1x2 double] [ 4] [1x4 double]
>> celldisp(out_cell)
out_cell{1,1} =
2 3 5
out_cell{2,1} =
2 3
out_cell{3,1} =
3
out_cell{4,1} =
2 5
out_cell{1,2} =
2 3
out_cell{2,2} =
1 2 3
out_cell{3,2} =
3
out_cell{4,2} =
1 2
out_cell{1,3} =
3
out_cell{2,3} =
3
out_cell{3,3} =
3 4
out_cell{4,3} =
4
out_cell{1,4} =
2 5
out_cell{2,4} =
1 2
out_cell{3,4} =
4
out_cell{4,4} =
1 2 4 5

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.

Simple indexing in a cell array

I've constructed a simple Matlab cell array:
d1 =
1
2
3
4
5
d2 =
2
3
4
5
6
d3 =
3
4
5
6
7
d =
[5x1 double]
[5x1 double]
[5x1 double]
clear d1 d2 d3;
How do I access the original array d1 data inside cell array d, after d1 is cleared? If I do:
>> d(1,:)
ans =
[5x1 double]
but what I want to do is issue this command:
d(what indexing goes here?)
and have it return:
1 2 3 4 5
Nevermind, I figured it out:
d{1,1,:}
returns back the original d1 information.