Matlab: How to locate a data in Matrix B based on the info in Matrix A? [duplicate] - matlab

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Sort a matrix with another matrix
The Matrix A ('10 x 1000' all numbers) look like this:
score(1.1) score(1.2) score(1.3)....score(1.1000)
score(2.1) score(2.2) score(2.3)....score(1.1000)
...
The Matrix B ('1 x 1000' all numbers):
Return(1) Return(2) Return(3) .....Return(1.1000)
Every time I sort a row of Matrix A, I want to sort Matrix B based on the order of the sorted row in Matrix A. Because there are 10 rows in Matrix A, Matrix B will be sorted 10 times and generate a new Matrix C ('10 x 1000') like this: (I am looking for a script to generate this Matrix C)
Return(3) Return(25) Return(600) .......Return(1000)
Return(36)Return(123) Return(2)........Return(212)
....
....

This should do what you want:
A = randn(10,1000);
B = randn(1,1000);
C = zeros(size(A));
for i = 1:10
[a idx] = sort(A(1,:));
A(i,:) = a;
C(i,:) = B(idx);
end
Now the rows of A are sorted, and the rows of C contain the corresponding sorted B.

This solution is a bit more compact, and it's also good to get used to doing this kind of solution for efficiency when your matrices get big. You can solve your problem with two ideas:
In [a, ix] = sort(X), a is a column-sorted version of X, and ix stores which rows moved where in each column. Thus if we do [a, ix] = sort(X.').'; (where the dot-apostrophe is the transpose) we can sort the rows.
B(ix) where ix is a bunch of indeces will make a matrix the same size as ix with the i-jth element being B at ix(i,j)
Then you just need to reshape it. So you can do:
A = rand(4,8);
B = rand(1,8);
n = size(A,1);
m = size(A,2);
[~,ix] = sort(A.');
C = reshape(B(ix'),n,m);

If I understand your question correctly the following should work. Using some sample scores:
>> score = [1 4 7 9; 3 5 1 7; 9 3 1 6]
score =
1 4 7 9
3 5 1 7
9 3 1 6
and sample return vector:
>> r = [10 20 30 40]
r =
10 20 30 40
Transpose the scores and sort since the SORT command works on columns of a matrix. We're only interested in the indices of the sorted values:
>> [~, ix] = sort(score')
ix =
1 3 3
2 1 2
3 2 4
4 4 1
Now transpose these indices and use them to reference the return values:
>> answer = r(ix)'
answer =
10 20 30 40
30 10 20 40
30 20 40 10

Related

creating diagonal matrix with selected elements

I have a 4x5 matrix called A from which I want to select randomly 3 rows, then 4 random columns and then select those elements which coincide in those selected rows and columns so that I have 12 selected elements.Then I want to create a diagonal matrix called B which will have entries either 1 or 0 so that multiplication of that B matrix with reshaped A matrix (20x1) will give me those selected 12 elements of A.
How can I create that B matrix? Here is my code:
A=1:20;
A=reshape(A,4,5);
Mr=4;
Ma=3;
Na=4;
Nr=5;
M=Ma*Mr;
[S1,S2]=size(A);
N=S1*S2;
y2=zeros(size(A));
k1=randperm(S1);
k1=k1(1:Ma);
k2=randperm(S2);
k2=k2(1:Mr);
y2(k1,k2)=A(k1,k2);
It's a little hard to understand what you want and your code isn't much help but I think I've a solution for you.
I create a matrix (vector) of zeros of the same size as A and then use bsxfun to determine the indexes in this vector (which will be the diagonal of B) that should be 1.
>> A = reshape(1:20, 4, 5);
>> R = [1 2 3]; % Random rows
>> C = [2 3 4 5]; % Random columns
>> B = zeros(size(A));
>> B(bsxfun(#plus, C, size(A, 1)*(R-1).')) = 1;
>> B = diag(B(:));
>> V = B*A(:);
>> V = V(V ~= 0)
V =
2
3
4
5
6
7
8
9
10
11
12
13
Note: There is no need for B = diag(B(:)); we could have simply used element by element multiplication in Matlab.
>> V = B(:).*A(:);
>> V = V(V ~= 0)
Note: This may be overly complex or very poorly put together and there is probably a better way of doing it. It's my first real attempt at using bsxfun on my own.
Here is a hack but since you are creating y2 you might as well just use it instead of creating the useless B matrix. The bsxfun answer is much better.
A=1:20;
A=reshape(A,4,5);
Mr=4;
Ma=3;
Na=4;
Nr=5;
M=Ma*Mr;
[S1,S2]=size(A);
N=S1*S2;
y2=zeros(size(A));
k1=randperm(S1);
k1=k1(1:Ma);
k2=randperm(S2);
k2=k2(1:Mr);
y2(k1,k2)=A(k1,k2);
idx = reshape(y2 ~= 0, numel(y2), []);
B = diag(idx);
% "diagonal" matrix 12x20
B = B(all(B==0,2),:) = [];
output = B * A(:)
output =
1
3
4
9
11
12
13
15
16
17
19
20
y2 from example.
y2 =
1 0 9 13 17
0 0 0 0 0
3 0 11 15 19
4 0 12 16 20

How to distinguish the two picture matrices?

I have a picture matrix A, the size of which is 200*3000 double. And I have another picture matrix B, the size of which is 200*1000 double. The 1000 columns of matrix B exactly comes from the columns of matrix A. My question is:
How to get a matrix C with the same size of matrix A, but only keep the original values of columns in matrix B? I mean the size of matrix C is 200*3000 double, but only 1000 columns have the same values as matrix B. The other 2000 columns will be set to another value d, that is my second question, what is the value I should set for d, so that the picture matrix C can distinguish from picture matrix A?
Use ismember with the 'rows' option. Here's an example:
A = [1 2 3 4; 5 6 7 8]; %// example A
B = [3 10 1; 7 20 5]; %// example B
val = NaN; %// example value to indicate no match
C = A; %// initiallize
ind = ismember(A.',B.','rows'); %// matching columns
C(:,~ind) = val; %// set non-matching columns to val
Equivalently, you coud replace ismember by bsxfun, so that line becomes
ind = any(all(bsxfun(#eq, A, permute(B, [1 3 2])), 1), 3);
In this example,
A =
1 2 3 4
5 6 7 8
B =
3 10 1
7 20 5
C =
1 NaN 3 NaN
5 NaN 7 NaN

matlab: find the index of rows from the first matching column value

Let's say I have a matrix,
>> m = magic(3)
m =
8 1 6
3 5 7
4 9 2
and suppose I have a vector containing a subset of the first elements of the columns,
>> v = [3 4]
v =
3 4
is there any function that I can use to find the index of the row from the first element of the columns? what I mean --
>> rows = row_index_from_col(m, 1, v)
rows =
2 3
??
if not, what is the best way to do this?
Looks like I got it --
m = magic(3)
v = [3 4]
[~,c] = size(m)
i = 1:c
i(ismember(m(:,1),v))
there might be a better way, I am not sure.

average 3rd column when 1st and 2nd column have same numbers

just lets make it simple, assume that I have a 10x3 matrix in matlab. The numbers in the first two columns in each row represent the x and y (position) and the number in 3rd columns show the corresponding value. For instance, [1 4 12] shows that the value of function in x=1 and y=4 is equal to 12. I also have same x, and y in different rows, and I want to average the values with same x,y. and replace all of them with averaged one.
For example :
A = [1 4 12
1 4 14
1 4 10
1 5 5
1 5 7];
I want to have
B = [1 4 12
1 5 6]
I really appreciate your help
Thanks
Ali
Like this?
A = [1 4 12;1 4 14;1 4 10; 1 5 5;1 5 7];
[x,y] = consolidator(A(:,1:2),A(:,3),#mean);
B = [x,y]
B =
1 4 12
1 5 6
Consolidator is on the File Exchange.
Using built-in functions:
sparsemean = accumarray(A(:,1:2), A(:,3).', [], #mean, 0, true);
[i,j,v] = find(sparsemean);
B = [i.' j.' v.'];
A = [1 4 12;1 4 14;1 4 10; 1 5 5;1 5 7]; %your example data
B = unique(A(:, 1:2), 'rows'); %find the unique xy pairs
C = nan(length(B), 1);
% calculate means
for ii = 1:length(B)
C(ii) = mean(A(A(:, 1) == B(ii, 1) & A(:, 2) == B(ii, 2), 3));
end
C =
12
6
The step inside the for loop uses logical indexing to find the mean of rows that match the current xy pair in the loop.
Use unique to get the unique rows and use the returned indexing array to find the ones that should be averaged and ask accumarray to do the averaging part:
[C,~,J]=unique(A(:,1:2), 'rows');
B=[C, accumarray(J,A(:,3),[],#mean)];
For your example
>> [C,~,J]=unique(A(:,1:2), 'rows')
C =
1 4
1 5
J =
1
1
1
2
2
C contains the unique rows and J shows which rows in the original matrix correspond to the rows in C then
>> accumarray(J,A(:,3),[],#mean)
ans =
12
6
returns the desired averages and
>> B=[C, accumarray(J,A(:,3),[],#mean)]
B =
1 4 12
1 5 6
is the answer.

Randomly interchange columns of a matrix: Matlab

Suppose
A = [1 2 3 5 7 9
6 5 0 3 2 3]
I want to randomize the position of the matrix column position; to give B like so:
B = [3 9 1 7 2 5
0 3 6 2 5 3]
How can I do this Matlab?
Try
B = A(randperm(length(A)))
Consult the documentation for explanations.
Now that code is formatted properly, it's clear the OP wants column preservation, although randperm is still the easiest option as given by HPM's answer.
idx = randperm(size(A,2)); % Create list of integers 1:n, in random order,
% where n = num of columns
B = A(:, idx); % Shuffles columns about, on all rows, to indixes in idx
You'll want to use the randperm function to generate a random permutation of column indices (from 1 to the number of columns in A), which you can then index A with:
B = A(:, randperm(size(A, 2)));