Sort cell array base on the 2D value - arrays

I have a 3X3 cell array and each element store a (x,y) point.
The point are generate by random number from [0,1].
What I want to do is sort the cell array so that it looks like following
ex: 9 points
each circle is one 2D point
index:(1,1) in the left top corner and (3,3) to the right bottom corner as the usual array index
that is to ensure the topological order.
How do I do it?
Thank in advance.
for the example
pairs = [4 9 2 6 5 1 7 8 3; 9 6 2 1 3 8 7 4 5] (row 1 = x-values, row 2 = y-values))
what I want to do is put them in the cell array so that they can be connected by read lines like the image's topology.

The number of permutations is factorial(9), which is not terribly large. So a brute-froce approach is feasible: test all permutations for your desired conditions, and pick the first that is valid.
In the following I'm using a 2x3x3 array, instead of a 3x3 cell array containing length-2 vectors, because it's much easier that way.
N = 3;
data = rand(2,N,N);
permutations = perms(1:N^2); %// generate all permutations
for k = 1:numel(permutations)
dx = reshape(data(1,permutations(k,:)),N,N); %// permuted x data
dy = reshape(data(2,permutations(k,:)),N,N); %// permuted y data
if all(all(diff(dy,[],1)<0)) && all(all(diff(dx,[],2)>0)) %// solution found
disp(dx) %// display solution: x values
disp(dy) %// y values
break %// we only want one solution
end
end
Note that for some choices of data there may not be a solution.

Related

Getting corresponding coordinates of a vectorized matrix

I have a matrix X of size n x m. I resized X to a vector a of length n x m.
How can I know "automatically" that the ith element in vector a corresponds to what element position (coordinates) in X?
I have written the following MATLAB code but I do not know how to continue.
X = rand(10,10);
[n,m] = size(X);
a = reshape(X, [n*m, 1]);
t = zeros(length(a),1);
for i = 1 : length(a)
t(i) = % I want to perform here the sum over the x and y coordinate values of the element in X
% that corresponds to the ith element in vector a.
end
Any help will be very appreciated.
That's what ind2sub does:
[row, col] = ind2sub([m n], i);
However, you may prefer to do it manually:
row = mod(i-1,m)+1;
col = floor((i-1)/m)+1;
This works because Matlab used column-major order for storing array elements. For example, in a 3×4 matrix the order in which the elements are stored in memory is as follows:
1 4 7 10
2 5 8 11
3 6 9 12
So the entry in the 2nd row, 3rd column is the 8th element in (column-major) linear order. When this matrix is reshaped into a vector (or into any other shape) this linear order is preserved. Therefore you can retrieve the original coordinates by divisions and modulus operations. Note also that, since Matlab's indexing is 1-based (as opposed to 0-based), the modulus operations need to be shifted by 1.

Finding indexes of maximum values of an array

How do I find the index of the 2 maximum values of a 1D array in MATLAB? Mine is an array with a list of different scores, and I want to print the 2 highest scores.
You can use sort, as #LuisMendo suggested:
[B,I] = sort(array,'descend');
This gives you the sorted version of your array in the variable B and the indexes of the original position in I sorted from highest to lowest. Thus, B(1:2) gives you the highest two values and I(1:2) gives you their indices in your array.
I'll go for an O(k*n) solution, where k is the number of maximum values you're looking for, rather than O(n log n):
x = [3 2 5 4 7 3 2 6 4];
y = x; %// make a copy of x because we're going to modify it
[~, m(1)] = max(y);
y(m(1)) = -Inf;
[~, m(2)] = max(y);
m =
5 8
This is only practical if k is less than log n. In fact, if k>=3 I would put it in a loops, which may offend the sensibilities of some. ;)
To get the indices of the two largest elements: use the second output of sort to get the sorted indices, and then pick the last two:
x = [3 2 5 4 7 3 2 6 4];
[~, ind] = sort(x);
result = ind(end-1:end);
In this case,
result =
8 5

remove the rows in a matrix whose elements are the same in matlab

Given a 2-column matrix, for instance. The input is:
[ 1,2;
3,4;
5,5]
The expected output is:
[1,2;
3,4;]
Does anyone know how do accomplish this? Many thanks for your time and attention.
You could use logical indexing:
A = [1 2;3 4;5 5];
match = A(:,1) == A(:,2); // 1 where row has the same elements in both columns
A(match,:) = []; // make the match columns empty
You would need to make this more generic for another case, but for two columns and your example this will work.
Your question suggests your matrix may have an arbitrary number of columns. In that case you may want to delete a row if it has (a) any two elements equal, or (b) all elements equal.
One possible approach is:
Apply sort along each row;
Use diff to compute differences between consecutive elements;
Generate a logical index with all to (a) keep rows for which all such differences are non-zero, or with any to (b) keep rows for which any such difference is non-zero:
So:
X = [1 2 3;
3 4 3;
5 5 5];
Y = X(all(diff(sort(X,2),[],2),2),:);
Z = X(any(diff(sort(X,2),[],2),2),:);
gives
Y =
1 2 3
Z =
1 2 3
3 4 3

How to find a row in matrix containing closest values to given vector in Matlab

I am writing a function to find a row in matrix which is closest to given vector and given vector can be variable in size. For example if matrix size is by 4 and vector size is 3 then function will check the first three values form each row of matrix.
For comparison, I am calculating the distance of each row in matrix from given vector and then selecting the row which has minimum distance but I think this is not perfect solution because two different row can have same minimum distance from given vector.
I would like to know that is there any built in function available in matlab. I have already tried method ismember.
You can compute distances with pdist2, obtain the minimum, and then find all rows that have minimum distance:
vector = [1 3 2];
matrix = [2 1 2 2
1 3 3 4
0 0 0 0
5 4 3 2]; %// example data
dist = pdist2(vector, matrix(:,1:numel(vector)), 'euclidean'); %// compute distances
mindist = min(dist); %// minimum distance
result = find(dist==mindist); %// minimizing rows
Change 'euclidean' in pdist2 to use other distance definitions.
Depending on your definition of distance you could use bsxfun instead of pdist2. For example, for (squared) Euclidean distance,
dist = sum(bsxfun(#minus, vector, matrix(:,1:numel(vector))).^2, 2); %// squared distance

Avoid loops in matlab

I am limited in the use of cycles in matlab and I have one task. I have the matrix 2xn with numbers and cell array 1xn. Each element in the first row point to a position of the array. I want to add every number from the second row of matrix to cell, which is pointed by corresponding number in the first row. In addition, I want the cells to be strings.
Let me clarify with example:
A = [[1 4 3 3 1 4 2], [7 4 3 5 6 5 4]]
I want to get array of cells: {'76', '4', '35', '45'}
How can I do this without using a for or while loop?
A = [1 4 3 3 1 4 2; 7 4 3 5 6 5 4]; %// data: 2 x n array
[~, ~, ii] = unique(A(1,:));
R = accumarray(ii(:),A(2,:),[],#(v) {fliplr(regexprep(num2str(v(:).'),'\s',''))}).';
The second line (unique) is used to remove possible gaps in first row. Otherwise those gaps would translate to the result of accumarray, which would then take up more memory uselessly.
The third line (accumarray) aggregates all values of second row of A that have the same value in the first row. The aggregation is done by the anonymous function, which converts numbers to string (num2str), removes spaces (regexprep), and changes orientation (fliplr and .') to match the desired output format.
EDIT:
Thanks to #chappjc's suggestion, the third line can be simplified to
R = accumarray(ii(:),A(2,:),[],#(v) {fliplr(num2str(v(:).','%d'))}).';
Alright, by just pointing at cellfun, arrayfun, cell2mat, cell indexing and array indexing I was arrogant. So, I try to make it up by actually using some of those in a more constructive solution:
%// Using array-indexing to find all matches with the current index in the first row,
%// then print their counterpart(s) into strings
fun = #(ii) sprintf('%d', A(2, A(1, :) == ii));
%// The following could also be 1:size(A, 2) or unique(A(1, :)) depending on the
%// general form of your problem.
range = min(A(1, :)) : max(A(1, :));
%// Using arrayfun to loop over all values in the first row
R = arrayfun(fun, range, 'UniformOutput', false)

Resources