Sort 2d matrix in Matlab - matlab

I have a 2d matrix, the first column is numeric, second is string and third is string, I want to sort by the first column. Here is my code used to create the loop.
Thanks
for i = 1:length(queries)
for j = 1:length(textures)
results{i * j, 1} = HI(queries{i, 2}, textures{j, 2});
results{i * j, 2} = textures{j, 3};
results{i * j, 3} = queries{i, 3};
end
results = sort(results, 1);
end

Use sortrows:
c = {0.608920898437500 'D1.gif' 'D106.gif'
0.803334960937500 'D1.gif' 'D109.gif'
0.831228027343750 'D1.gif' 'D26.gif'}; %// example data
cSorted = sortrows(c,1); %// sort rows according to first column
The result is
cSorted =
[0.6089] 'D1.gif' 'D106.gif'
[0.8033] 'D1.gif' 'D109.gif'
[0.8312] 'D1.gif' 'D26.gif'

Related

matlab/octave plot a mesh

t=0:0.01:2;
alpha=linspace(0, 1, 41);
r=linspace(0,1,41);
[aa,rr] = meshgrid(alpha,r);
At each point of (aa, rr), for each t there is a value t^aa+rr^2, then those values are summed up:
sum = (t1^aa+rr^2) + (t2^aa+rr^2) + ...
Thus for each point of (aa,rr), there is a number of sum. How do you plot that mesh?
You can reshape t into the third dimension to generate all triples of aa, rr and t via implicit expansion, and then sum over that dimension to get the desired result:
t3 = reshape(t, 1, 1, []);
s = sum(t3.^aa + rr.^2, 3);
mesh(aa, rr, s)
In your example, this produces

How to get elements after a sort on a dimensional matrix

I have two matrices A & B and want to sort data on both using the 3rd dimension of A. For that, I use sort to get both result and indexes.
What I don't know is how to use the indexes to get sorted data on matrix B.
A = rand(2,2,2)
B = rand(2,2,2)
[S I] = sort(A, 3);
S
B(I) % Here, don't sort B according to the same sort than A
Convert your third dimensional subscripts to linear indices with:
[r, c, ~] = size(A);
LinInd = (I-1)*r*c + reshape(1:r*c, r, c); %For >=R2016b
%LinInd = bsxfun(#plus, (I-1)*r*c, reshape(1:r*c, r, c)); %For <R2016b
Now use these linear indices to sort B i.e:
B(LinInd)
As pointed by Sardar Usama, the key is to transform the 3rd dimensional indexes into linear indexes. The correct function to do that in Matlab is sub2ind. It is not straightforward:
clc; clear all; close all;
n = 8;
A = rand(n, n, n);
[S, I] = sort(A, 3, 'descend');
sizeA = size(A);
sizeA1 = sizeA(1);
sizeA2 = sizeA(2);
sizeA3 = sizeA(3);
baseVecIndex1 = (1:sizeA1)';
bM1_2D = repmat(baseVecIndex1, 1, sizeA2);
bM1_3D = repmat(bM1_2D, 1, 1, sizeA3);
baseVecIndex2 = 1:sizeA2;
bM2_2D = repmat(baseVecIndex2, sizeA1, 1);
bM2_3D = repmat(bM2_2D, 1, 1, sizeA3);
linearIndexes = sub2ind(sizeA, bM1_3D, bM2_3D, I);
test = A(linearIndexes );
test(:, :, n)
S(:, :, n)

How to fill columns of a matrix with random numbers of specific range?

I've a matrix of order 100*10 . Now the objective is to fill each columns of the matrix with random integer within a specific range. Now the problem is for every column the range of the random number changes. For instance, for the first column, the range is [1,100] , for the second its -10 to 1 and so on till 10th column.
This is what I've tried:
b = [0,100;-10,1;0,1;-1,1;10,20]
a = []
for i=1 to 10
a[] = [(i:100)' randi(1,100)]
end
How do I generate a matrix of this form?
I don't have matlab installed right now, but i would do something like this.
m = 100;
n = size(b, 1);
range = b(:, 2) - b(:, 1);
offset = b(:, 1);
A = round(bsxfun(#minus, bsxfun(#times, rand(m, n), range), offset);
Without loop it would become:
M = 100;
N = size(b, 1);
A = zeros(m, n); % preallocate to avoid matrix expansion
for ii = 1:n
A(:, ii) = randi(b(ii,:), m, 1);
end

How to convert an array of doubles to a cell array of strings with the same length each?

I woould like to insert a space before each positive value in a matrix.
I start with:
A =
1.0000 -0.2176 0.3766
-0.2176 1.0000 0.3898
-0.3766 0.3898 1.0000
I apply a function to each value of A:
B = arrayfun(#(x) num2str(x,'% 5.2f'),A,'UniformOutput',0)
And the ouput is this:
B =
'1.00' '-0.22' '0.38'
'-0.22' '1.00' '0.39'
'-0.38' '0.39' '1.00'
However, I would like the output to be:
B =
' 1.00' '-0.22' ' 0.38'
'-0.22' ' 1.00' ' 0.39'
'-0.38' ' 0.39' ' 1.00'
Notice that each cell has the same width (5 characters), no matter if the numb is positive or negative.
Thank you!
Insert the plus for equal length, then replace it with a blank
B = arrayfun(#(x) strrep(num2str(x,'%+5.2f'),'+',' '),A,'Uni',false)
If your question is just about equal length, use:
B = arrayfun(#(x) num2str(x,'%+5.2f'),A,'Uni',false)
or
B = arrayfun(#(x) num2str(x,'%05.2f'),A,'Uni',false)
You could avoid arrayfun and vectorize the conversion by using the precision property of num2str to apply it to the whole matrix directly:
prec = 2
B = mat2cell(num2str(A,'%+5.2f'), ones(size(A,1),1), (prec+3).*ones(size(A,2),1))
B =
'+1.00' '-0.22' '+0.38'
'-0.22' '+1.00' '+0.39'
'-0.38' '+0.39' '+1.00'
Explanation:
%// apply num2str to whole matrix with precision property
charArray = num2str(A,'%+5.2f');
%// reshape resulting char array
B = mat2cell(charArray, [1 1 1], [3+2 3+2 3+2])
%// which is generically
B = mat2cell(charArray, ones(size(A,1),1), (prec+3).*ones(size(A,2),1))
Benchmark:
f1 = #() mat2cell(num2str(A,'%+5.2f'), ones(size(A,1),1), (prec+3).*ones(size(A,2),1));
f2 = #() arrayfun(#(x) num2str(x,'%+5.2f'),A,'Uni',false);
t1 = timeit(f1)
t2 = timeit(f2)
t1 = 0.25875 %// mat2cell
t2 = 4.2812 %// arrayfun
So for a 200x100 matrix, the mat2cell solution is almost 20 times faster than arrayfun.

Multiplying Cell with elements of a matrix Matlab

I have a 1xm cell array A{}, with each element of the array being NxN matrix and a matrix W(N1,m).
I need to calculate
Sum(j) = W(j,1)*A{1,1} + W(j,2)*A{1,2}
and I am doing the following:
for j=1:N1
sum=false(N);
for k=1:m
sum = sum + W(j,k)*A{1,k};
end
Sum(j)=sum
end
Or more visually :
Matrix W(let's say N1=2)
|W11 W12||A{1,1}| = |W11*A{1,1} + W12*A{1,2}|
|W21 W22||A{1,2}| = |W21*A{1,1} + W22*A{1,2}|
Is there a way of doing it without using the loops?
To do that without for-loops, you can rape (pardon the expression) the arrayfun command:
w_func = #(j)arrayfun(#(k)(W(j, k) * A{k}), 1:m, 'Un', 0)
sum_func = #(x)sum(cat(3, x{:}), 3)
S = arrayfun(#(j)sum_func(w_func(j)), 1:N1, 'Un', 0);
This produces a cell array S that contains all the sums, from S{1} to S{N1}.
I'm confused over what you are trying to do, but if I understand it correctly, this code should work:
temp = cell2mat(A);
a_sum = temp*repmat(eye(n),m,1); % this reduces A by performing sum like operation so [1 1 1 3;0 1 0 2]
% becomes [2 4; 0 3]
Sum = W * a_sum
I am also not sure I understood the question, but here is some code to consider:
%# create some data resembling what you described
N = 2;
m = 4;
N1 = 5;
W = rand(N1,m);
A = cell(1,m); for i=1:m, A{i} = rand(N); end
%# do the multiplications
s = cell(N1,1);
for j=1:N1
AA = cellfun(#times, A, num2cell(W(j,:)), 'UniformOutput',false);
s{j} = sum(cat(3,AA{:}), 3);
end
The cell array s now contains the result such that:
s{j} = W(j,1)*A{1} + W(j,2)*A{2} + ... + W(j,m)*A{m}
thus s is a cell array of size N1-by-1, where each cell contains an N-by-N matrix