find the intersection of a cell array - matlab

I have a vector, let say as = [1 3 4] and I have 30 by 30 cell array. I want to check if the elements of vector as intersect with the elements of each cell or not? the cells may be 2D arrays of size n-by-2 (where n= 1 2 3 4,etc).
If the row in a cell has an intersection with that vector, it should return (1 or 0) & if the row has no intersection with that vector, it should return (0 or 1).
Example:
If on of the cell arrays contains [ 1 8 ;6 9] , so the output is [1; 0].

Assuming cellarr to be input cell array, see if this approach works for you -
out = cellfun(#(x) any(any(bsxfun(#eq,x,permute(as,[1 3 2])),2),3),cellarr,'un', 0)
This would give you a cell array of all those matches for each cell. You can see their values with a call to celldisp(out).
Sample run -
as =
1 3 4
-----------------------------------
cellarr{1,1} =
1 8
6 9
cellarr{2,1} =
7 4
2 3
cellarr{1,2} =
4 3
cellarr{2,2} =
7 8
2 3
7 8
-----------------------------------
out{1,1} =
1
0
out{2,1} =
1
1
out{1,2} =
1
out{2,2} =
0
1
0
Edit: If you would like to find indices that do not have any zeros corresponding to their cell values in out, that is we intend to find cells where all rows have at least one element from as, you can use this modified code, assuming ca to be the input cell array (name changed here to keep the code compact) -
mch = cellfun(#(x) all(any(any(bsxfun(#eq,x,permute(as,[1 3 2])),2),3)),ca,'un',0)
%// Find matches for all cells
mch(cellfun('isempty',ca))={false} %// take care of empty cell condition
[row_ind,col_ind] = find(cell2mat(mch)) %// row and column indices of good matches

What about this?
matrices - Calculate intersection of vector subspace by using gauss-algorithm - Mathematics Stack Exchange http://goo.gl/PXCPlH

Related

sorting an array and keep the index in MATLAB

I have an array called A, it has 2 Rows and 56 columns ( as shown in the attached image)
the first row represents the values while the second row represents the index for each value.
I want to sort the first row but keep the index for each value (I tried to use Sort function but it doesnt keep the index of each value in the second row).
for example, let's suppose I have this matrix
input
x=[9 2 4 3 ;3 1 8 2 ]
i want the output looks like this
y=[2 3 4 9; 1 2 8 3 ];
There are a couple of ways to achieve this:
[y1,I] = sort(x(1,:))
y2 = x(2,I)
y = [ y1 ; y2 ]
This basically sort the first row of your data, and save the sorting index in I, and then use those index to get the 'sorted' second row, and then just join them
or
y = sortrows(x')'
The ' operator transposes the matrix, which allows you to use sortrows and then use it again to reshape your output matrix.
You can use indices of sorted elements
[S,I]=sort(x(1,:));
result = [S;x(2,I)]
The first row is sorted and indices of the sorted elements is used to order the second row.
result
2 3 4 9
1 2 8 3
You can get the indices directly from sorting the first row. These can be used as an argument in x itself:
x=[9 2 4 3 ;3 1 8 2 ];
%get the indices of the first row:
[~,indices] = sort(x(1,:))
%return x in the order "indices" for each row:
y = [x(1,indices);x(2,indices)]

Can I get 2 set of random number array in matlab?

idx=randperm(5)
idx=[1,3,4,2,5]
I know this works like that but I'm curious about is there anyway to get something like this.
idx=[1,3,4,2,5,5,3,2,4,1]
adding one set of array after one array
Is there any way to make that?
One vectorized way would be to create a random array of size (m,n), sort it along each row and get the argsort indices. Each row of those indices would represent a group of randperm values. Here, m would be the number of groups needed and n being the number of elements in each group.
Thus, the implementation would look something like this -
[~,idx] = sort(rand(2,5),2);
out = reshape(idx.',1,[])
Sample run -
>> [~,idx] = sort(rand(2,5),2);
>> idx
idx =
5 1 3 2 4
4 3 2 5 1
>> out = reshape(idx.',1,[])
out =
5 1 3 2 4 4 3 2 5 1
You can use the modulo operation:
n = 5 %maximum value
r = 2 %each element are repeated r times.
res = mod(randperm(r*n),n)+1

access cell array by two vector not pairwise

If I have a Cell array 2*2 where A{i,j} is a matrix, and I have two vectors v=1:2,c=1:2.
I want A(v,c) to return only A{1,1} and A{2,2} but matlab returns every combination of the two(aka also returns A{1,2} and A{2,1}).
Is there a way without using loops or cellfun ?
What I suspect you are doing is something like this:
B = A(v, c);
When you specify vectors to index into A, it finds the intersection of coordinates and gives you those elements. As such, with your indexing you are basically returning all of the elements in A.
If you want just the top left and lower right elements, use sub2ind instead. You can grab the column-major indices of those locations in your cell array, then slice into your cell array with these indices:
ind = sub2ind(size(A), v, c);
B = A(ind);
Example
Let's create a sample 2 x 2 cell array:
A = cell(2,2);
A{1,1} = ones(2);
A{1,2} = 2*ones(2);
A{2,1} = 3*ones(2);
A{2,2} = 4*ones(2);
Row 1, column 1 is a 2 x 2 matrix of all 1s. Row 1, column 2 is a 2 x 2 matrix of 2s, row 2 column 1 is a 2 x 2 matrix of all 3s and the last entry is a 2 x 2 matrix of all 4s.
With v = 1:2; c=1:2;, running the above code gives us:
>> celldisp(B)
B{1} =
1 1
1 1
B{2} =
4 4
4 4
As you can see, we picked out the top left and bottom right entries exactly.
Minor Note
If it's seriously just a cell array of 2 x 2, and you only want to pick out the top left and lower right elements, you can just do:
B = A([1 4]);
sub2ind would equivalently return 1 and 4 as the column major indices for the top left and lower right elements. This avoids the sub2ind call and still achieves what you want.

combine two n dimensional cell arrays into a n by n dimensional one

I wonder how to do this in MATLAB.
I have a={1;2;3} and would like to create a cell array
{{1,1};{1,2};{1,3};{2,1};{2,2};{2,3};{3,1};{3,2};{3,3}}.
How can I do this without a for loop?
You can use allcomb from MATLAB File-exchange to help you with this -
mat2cell(allcomb(a,a),ones(1,numel(a)^2),2)
Just for fun, using kron and repmat:
a = {1;2;3}
b = mat2cell([kron(cell2mat(a),ones(numel(a),1)) repmat(cell2mat(a),numel(a),1)])
Here square brackets [] are used to perform a concatenation of both column vectors, where each is defined either by kron or repmat.
This can be easily generalized, but I doubt this is the most efficient/fast solution.
Using repmat and mat2cell
A = {1;2;3};
T1 = repmat(A',[length(A) 1]);
T2 = repmat(A,[1 length(A)]);
C = mat2cell(cell2mat([T1(:),T2(:)]),ones(length(T1(:)),1),2);
You can use meshgrid to help create unique permutations of pairs of values in a by unrolling both matrix outputs of meshgrid such that they fit into a N x 2 matrix. Once you do this, you can determine the final result using mat2cell to create your 2D cell array. In other words:
a = {1;2;3};
[x,y] = meshgrid([a{:}], [a{:}]);
b = mat2cell([x(:) y(:)], ones(numel(a)*numel(a),1), 2);
b will contain your 2D cell array. To see what's going on at each step, this is what the output of the second line looks like. x and y are actually 2D matrices, but I'm going to unroll them and display what they both are in a matrix where I've concatenated both together:
>> disp([x(:) y(:)])
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
Concatenating both vectors together into a 2D matrix is important for the next line of code. This is a vital step in order to achieve what you want. After the second line of code, the goal will be to make each element of this concatenated matrix into an individual cell in a cell array, which is what mat2cell is doing in the end. By running this last line of code, then displaying the contents of b, this is what we get:
>> format compact;
>> celldisp(b)
b{1} =
1 1
b{2} =
1 2
b{3} =
1 3
b{4} =
2 1
b{5} =
2 2
b{6} =
2 3
b{7} =
3 1
b{8} =
3 2
b{9} =
3 3
b will be a 9 element cell array and within each cell is another cell array that is 1 x 2 which stores one row of the concatenated matrix as individual cells.

Finding maxima in 2D matrix along certain dimension with indices

I have a <206x193> matrix A. It contains the values of a parameter at 206 different locations at 193 time steps. I am interested in the maximum value at each location over all times as well as the corresponding indices. I have another matrix B with the same dimensions of A and I'm interested in values for each location at the time that A's value at that location was maximal.
I've tried [max_val pos] = max(A,[],2), which gives the right maximum values, but A(pos) does not equal max_val.
How exactly does this function work?
I tried a smaller example as well. Still I don't understand the meaning of the indices....
>> H
H(:,:,1) =
1 2
3 4
H(:,:,2) =
5 6
7 8
>> [val pos] = max(H,[],2)
val(:,:,1) =
2
4
val(:,:,2) =
6
8
pos(:,:,1) =
2
2
pos(:,:,2) =
2
2
The indices in idx represent the index of the max value in the corresponding row. You can use sub2ind to create a linear index if you want to test if A(pos)=max_val
A=rand(206, 193);
[max_val, idx]=max(A, [], 2);
A_max=A(sub2ind(size(A), (1:size(A,1))', idx));
Similarly, you can access the values of B with:
B_Amax=B(sub2ind(size(A), (1:size(A,1))', idx));
From your example:
H(:,:,2) =
5 6
7 8
[val pos] = max(H,[],2)
val(:,:,2) =
6
8
pos(:,:,2) =
2
2
The reason why pos(:,:,2) is [2; 2] is because the maximum is at position 2 for both rows.
max is a primarily intended for use with vectors. In normal mode, even the multi-dimensional arrays are treated as a series of vectors along which the max function is applied.
So, to get the values in B at each location at the time where A is maximum, you should
// find the maximum values and positions in A
[c,i] = max(A, [], 2);
// iterate along the first dimension, to retrieve the corresponding values in B
C = [];
for k=1:size(A,1)
C(k) = B(k,i(k));
end
You can refer to #Jigg's answer for a more concise way of creating matrix C