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

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.

Related

how can one obtain all combinations of a vector?

I want to find all possible variations (combinations) of a vector, choosing various numbers of elements from that vector.
For example, suppose I have the vector:
x = [1 2 3 4 5];
I can determine the number of combinations for each number of chosen elements:
x = [1 2 3 4 5]';
n = numel(x);
for k = 1:n
combs(k) = nchoosek(n,k);
end
sum(combs)
This results in:
combs = 5 10 10 5 1
sum(combs) = 31
I want a way to store all 31 of these combinations in an array, for example a cell array, with n cells, within each is an array in which each row is a vector combination of the elements.
e.g. at k = 4:
combs{4} =
1 2 3 4
1 2 3 5
1 2 4 5
1 3 4 5
2 3 4 5
Is there an existing function that does this, or what would be the most simple approach to this?
Call nchoosek with a vector as first input, using arrayfun (or equivalently for) to loop over the number of picked elements:
n = 5;
combs = arrayfun(#(k) nchoosek(1:n,k), 1:n, 'UniformOutput', false);
Here is an approach using dec2bin , find and accumarray:
x = [1 2 3 4 5];
[a b] = find(dec2bin(1:2^numel(x)-1)=='1');
combs = accumarray(a,x(b),[],#(c){c});

MATLAB multidimensional array

I have been trying to use the multidimensional array function to store NxN vectors of length n in each (i,j) entry of a 3d matrix of NxNxn dimensions.
My code looks like:
a=zeros(N,N,n);
a(i,j,:)=v_ij; %here v is a vector of length n, which differs for each i,j
However when I try to extract each vector by typing e.g. a(1,1,:) I don't get a nice vector. Rather I get something like:
ans(:,:,1) = ..
ans(:,:,2) = ..
...
I don't understand why it says ans(:,:)...
That's because each vector v_ij is stored along the 3rd dimension of your matrix, so when you access a(1,1,:), you are looking for a multidimensional array consisting of every value at the location (1,1) along the 3rd dimension of a.
Let's consider a simple example:
N = 2;
n = 3;
a = zeros(N,N,n);
for k = 1:N
for l = 1:N
v_kl = randi([0 10],1,n);
a(k,l,:) = v_kl;
end
end
The randomly-generated matrix a is a 2x2x3 matrix that looks like this:
a(:,:,1) =
4 1
4 10
a(:,:,2) =
0 2
0 5
a(:,:,3) =
2 2
9 5
Therefore, using a(1,1,:) is equivalent to getting the element located at (1,1) for all 3 dimensions, here it would be 4,0 and 2.
Indeed, calling a(1,1,:) yields:
ans(:,:,1) =
4
ans(:,:,2) =
0
ans(:,:,3) =
2
Benoit_11's answer plus squeeze should work, but I would like to propose a different solution.
Rather than creating a NxNxn array, why not make it nxNxN?
N = 2;
n = 3;
a = zeros(n,N,N);
for p = 1:N
for q = 1:N
v_pq = randi([0 10],1,n);
a(:,p,q) = v_pq;
if (p == 1) && (q == 1)
v_pq %// display vector at a(:,1,1)
end
end
end
a
v_pq =
3 4 8
a =
ans(:,:,1) =
3 3
4 9
8 7
ans(:,:,2) =
5 6
10 1
9 5
Now the vectors are stored along the first dimension, so [3 4 8] shows up as the first column of ans(:,:,1). To access it you would use a(:,p,q) rather than a(p,q,:):
a(:,1,1)
ans =
3
4
8

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)));

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

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