I want to select 2 minimum elements from every column of matrix. How to can display number of row?
input:
a1 a2 a3
--------
b1 2 4 8
b2 8 5 3
b3 1 5 9
output:
a1 a2 a3 a1 a2 a3
-------- ----------
1 4 3 => b3 b1 b2
2 5 8 b1 b2 b1
my code:
for i = 1:3
MINN(:,i)=getNElements(distance(i,:), 1);
end
function [smallestNElements smallestNIdx] = getNElements(A, n)
[ASorted AIdx] = sort(A);
smallestNElements = ASorted(1:n);
smallestNIdx = AIdx(1:n);
end
Let me guess, is this what you want to do?
x = [2 4 8; 8 5 3; 1 5 9]; % data
n = 2; % desired number of smallest values per column
[y, ind] = sort(x,1); % sort each column and get indices of that sorting
y = y(1:n,:); % keep n smallest
ind = ind(1:n,:); % keep their indices
Results:
y =
1 4 3
2 5 8
ind =
3 1 2
1 2 1
Related
consider a matrix:
a = [1 2
1 3
2 3
4 5
6 1]
I want to find duplicates for every unique element of a and take the rows of them to different matrices. For example here lets say that the answer for number 1 is:
a1 = [1 2
1 3
6 1]
The answer for number 2 is:
a2 = [1 2
2 3]
The answer for number 3 is:
a3 = [1 3
2 3]
and so on for every unique elements of matrix a. Any suggestions?
This will do it:
temp=unique(a);
for k=1:numel(temp)
[r,~]=find(a==temp(k));
assignin('base', ['a' num2str(k)], a(sort(r),:))
end
Results:-
>> a1
a1 =
1 2
1 3
6 1
>> a2
a2 =
1 2
2 3
>> a3
a3 =
1 3
2 3
>> a4
a4 =
4 5
>> a5
a5 =
4 5
>> a6
a6 =
6 1
You can use any to check if any element of a row contains the value you want. This will return a logical array that is true where the row contained the value. You can then use this to grab the relevant rows of a.
result = a(any(a == value, 2), :);
We could create an anonymous function that does this for you.
rows_that_contain_value = #(A, value)A(any(A == value, 2), :);
Then we can use this like this
a = [1 2
1 3
2 3
4 5
6 1]
a1 = rows_that_contain_value(a, 1);
a2 = rows_that_contain_value(a, 2);
a3 = rows_that_contain_value(a, 3);
If we want to do this for all unique values in a, we can do something like the following.
groups = arrayfun(#(x)rows_that_contain_value(a, x), unique(a), 'uniformoutput', 0);
I would like to sort the first N elements of a vector that has more elements.
For example:
A = [3 2 5 1 8 9 2 1 9];
If N = 5, the output should be:
B = [1 2 3 5 8 9 2 1 9];
I would also like to have a vector of indices v, so that B = A(v).
How can I do this?
[B, v] = sort(A(1:N));
B = [B, A(N+1:end)]; % sorted vector
v = [v, N+1:numel(A)]; % index vector
This problem is a succession of my previous problem:
1) Extract submatrices, 2) vectorize and then 3) put back
Now, I have two patients, named Ann and Ben.
Indeed the matrices A and B are data for Ann and the matrix C is data for Ben:
Now, I need to design a matrix M such that y = M*x where
y = [a11, a21, a12, a22, b11, b21, b12, b22]' which is a vector, resulting from concatenation of the top-left sub-matrices, Ann and Ben;
x = [2, 5, 4, 6, 7, 9, 6, 2, 9, 3, 4, 2]' which is a vector, resulting from concatenation of sub-matrices A, B and C.
Here, the M is a 8 by 12 matrix that
a11 = 2 + 7, a21 = 5 + 9, .., a22 = 6 + 2 and b11 = 9, ..b22 = 2.
I design the M manually by:
M=zeros(8,12)
M(1,1)=1; M(1,5)=1; % compute a11
M(2,2)=1; M(2,6)=1; % compute a21
M(3,3)=1; M(3,7)=1; % compute a12
M(4,4)=1; M(4,8)=1; % compute a22
M(5,9)=1; % for setting b11 = 9, C(1,1)
M(6,10)=1; % for setting b21 = 3, C(2,1)
M(7,11)=1; % for setting b12 = 4, C(1,2)
M(8,12)=1 % for setting b22 = 2, C(2,2)
Obviously, in general for M(i,j), i means the 8 linear-index position of vector y and j means linear-index position of vector x.
However, I largely simplified my original problem that I want to construct this M automatically.
Thanks in advance for giving me a hand.
Here you have my solution. I have essentially build the matrix M automatically (from the proper indexes) as you suggested.
A = [2 4 8;
5 6 3;
10 3 6];
B = [7 6 3;
9 2 9;
10 2 3];
C = [9 4 7;
3 2 5;
10 3 4];
% All matrices in the same array
concat = cat(3, A, B, C);
concat_sub = concat(1:2,1:2,:);
x = concat_sub(:);
n = numel(x)/3; %Number of elements in each subset
M2 = zeros(12,8); %Transpose of the M matrix (it could be implemented directly over M but that was my first approach)
% The indexes you need
idx1 = 1:13:12*n; % Indeces for A
idx2 = 5:13:12*2*n; % Indices for B and C
M2([idx1 idx2]) = 1;
M = M2';
y = M*x
I have taken advantage of the shape that the matrix M shold take:
You can index into things and extract what you want without multiplication. For your example:
A = [2 4 8; 5 6 3; 10 3 6];
B = [7 6 3; 9 2 9; 10 2 3];
C = [9 4 7;3 2 5; 10 3 4];
idx = logical([1 1 0;1 1 0; 0 0 0]);
Ai = A(idx);
Bi = B(idx);
Ci = C(idx);
output = [Ai; Bi; Ci];
y = [Ai + Bi; Ci]; % desired y vector
This shows each step individually but they can be done in 2 lines. Define the index and then apply it.
idx = logical([1 1 0;1 1 0;0 0 0]);
output = [A(idx); B(idx); C(idx)];
y = [Ai + Bi; Ci]; % desired y vector
Also you can use linear indexing with idx = [1 2 4 5]' This will produce the same subvector for each of A B C. Either way works.
idx = [1 2 4 5]';
or alternatively
idx = [1;2;4;5];
output = [A(idx); B(idx); C(idx)];
y = [Ai + Bi; Ci]; % desired y vector
Either way works. Check out doc sub2ind for some examples of indexing from MathWorks.
A1 and A2 are two arrays of integers with the same dimensions 6000x2000.
I want to find a third matrix B by following these steps:
for i=1:1:6000
for j=1:2000
a1 = fliplr(dec2binvec(A1(i,j),14)); % Convert A1(i,j) to a binary vector
a2 = fliplr(dec2binvec(A2(i,j),32)); % Convert A2(i,j) to a binary vector
b = [a1 a2];
B(i,j) = sum(b.*2.^(numel(b)-1:-1:0)); % Convert b to decimal
end
end
my problem is the computation time to find B.
Is there a way to avoid loops in order to reduce the computation time ?
Example:
A1 = [2 3 A2 = [7 6
4 5] 2 9]
A1(1,1) = 2 and A2(1,1) = 7
a1 = [0 0 0 1 0] (eg 5 bits) a2 = [0 0 0 1 1 1] (eg 6 bits)
b = [a1 a2] = [0 0 0 1 0 0 0 0 1 1 1]
B1(1,1) = sum(b.*2.^(numel(b)-1:-1:0)) = 135
Using your example:
A1 = [2 3;
4 5];
A2 = [7 6;
2 9];
B=bitshift(A1,6)+A2
Output:
B =
135 198
258 329
I assume the example contains what you want. Simply use math ;)
A1 = [2 3;4,5]
A2=[7 6;2 9]
A1.*2^6+A2
Please be aware that doubles can hold up to 53 bits without precision loss. Recent versions of matlab support uint64. For even longer numbers check vpa, but vpa will result in slow code.
If I understand your example correctly, you only need to bit-shift A1 (i.e. multiply by a power of 2):
M = 5; %// not used actually
N = 6;
B = A1 * 2^N + A2;
In your example, this gives
B =
135 198
258 329
I am trying to match 1st column of A with 1st to 3rd columns of B, and append corresponding 4th column of B to A.
For example,
A=
1 2
3 4
B=
1 2 4 5 4
1 2 3 5 3
1 1 1 1 2
3 4 5 6 5
I compare A(:,1) and B(:, 1:3)
1 and 3 are in A(:,1)
1 is in the 1st, 2nd, 3rd rows of B(:, 1:3), so append B([1 2 3], 4:end)' to A's 1st row.
3 is in the 2nd and 4th rows of B(:,1:3), so append B([2 4], 4:end)' to A's 2nd row.
So that it becomes:
1 2 5 4 5 3 1 2
3 4 5 3 6 5 0 0
I could code this using only for and if.
clearvars AA A B mem mem2 mem3
A = [1 2 ; 3 4]
B = [1 2 4 5 4; 1 2 3 5 3; 1 1 1 1 2; 3 4 5 6 5]
for n=1:1:size(A,1)
mem = ismember(B(:,[1:3]), A(n,1));
mem2 = mem(:,1) + mem(:,2) + mem(:,3);
mem3 = find(mem2>0);
AA{n,:} = horzcat( A(n,:), reshape(B(mem3,[4,5])',1,[]) ); %'
end
maxLength = max(cellfun(#(x)numel(x),AA));
out = cell2mat(cellfun(#(x)cat(2,x,zeros(1,maxLength-length(x))),AA,'UniformOutput',false))
I am trying to make this code efficient, by not using for and if, but couldn't find an answer.
Try this
a = A(:,1);
b = B(:,1:3);
z = size(b);
b = repmat(b,[1,1,numel(a)]);
ab = repmat(permute(a,[2,3,1]),z);
row2 = mat2cell(permute(sum(ab==b,2),[3,1,2]),ones(1,numel(a)));
AA = cellfun(#(x)(reshape(B(x>0,4:end)',1,numel(B(x>0,4:end)))),row2,'UniformOutput',0);
maxLength = max(cellfun(#(x)numel(x),AA));
out = cat(2,A,cell2mat(cellfun(#(x)cat(2,x,zeros(1,maxLength-length(x))),AA,'UniformOutput',false)))
UPDATE Below code runs in almost same time as the iterative code
a = A(:,1);
b = B(:,1:3);
z = size(b);
b = repmat(b,[1,1,numel(a)]);
ab = repmat(permute(a,[2,3,1]),z);
df = permute(sum(ab==b,2),[3,1,2])';
AA = arrayfun(#(x)(B(df(:,x)>0,4:end)),1:size(df,2),'UniformOutput',0);
AA = arrayfun(#(x)(reshape(AA{1,x}',1,numel(AA{1,x}))),1:size(AA,2),'UniformOutput',0);
maxLength = max(arrayfun(#(x)(numel(AA{1,x})),1:size(AA,2)));
out2 = cell2mat(arrayfun(#(x,i)((cat(2,A(i,:),AA{1,x},zeros(1,maxLength-length(AA{1,x}))))),1:numel(AA),1:size(A,1),'UniformOutput',0));
How about this:
%# example data
A = [1 2
3 4];
B = [1 2 4 5 4
1 2 3 5 3
1 1 1 1 2
3 4 5 6 5];
%# rename for clarity & reshape for algorithm's convenience
needle = permute(A(:,1), [2 3 1]);
haystack = B(:,1:3);
data = B(:,4:end).';
%# Get the relevant rows of 'haystack' for each entry in 'needle'
inds = any(bsxfun(#eq, haystack, needle), 2);
%# Create data that should be appended to A
%# All data and functionality in this loop is local and static, so speed
%# should be optimal.
append = zeros( size(A,1), numel(data) );
for ii = 1:size(inds,3)
newrow = data(:,inds(:,:,ii));
append(ii,1:numel(newrow)) = newrow(:);
end
%# Now append to A, stripping unneeded zeros
A = [A append(:, ~all(append==0,1))]