MATLAB search row index of matrix with values of another matrix - matlab

In MATLAB I have a very large matrix (matrix A). Now I would like to find the row-index of the row which contain certain values in the second column. These values - which I'm looking for in Matrix A - are stored in anonther Matrix (Matrix B) with consists out of a row (800 numbers).
Besides I would like to redo this calculation for the same matrix A, but for ten different matrices, with different sizes (which contain the values I'm looking for in different columns of matrix A).
Because of the sizes of the matrix I think i need a loop to extract the row in matrix A which contain te value of Matrix B. How can I do this?
regards,
V
Thanks for the quick response! Indeed the problem is maybe a bit complex to answer without an example, and indeed duplicate entries cause some problems. Therefore hereby an example
For example I have a -simplified- matrix A:
1 2 3 4
9 9 9 9
4 3 2 1
And a -simplified- matrix (row) B: [9 3]
And a -simplified- matrix (row) C: [9 2]
Then I would like to get matrix D and matrix E.These matrices should contain in the first column the numbers from the original matrix D(or E) and in the second column the corresponding row-location of this value in matrix A.
So, matrix D =
9 2
3 3
matrix E =
9 2
2 3
As represented in this example matrix B and matrix C can contain data which is present in several column of matrix A (like the nine). However, martix B should "search" in column 2 of matrix A. Likewise, should matrix C "search" in column 3 of Matrix A, resulting in matrix D and E as given in the example.

As mentionned by Shai in his comment, your question is quite vague and a lot of special case could arise (duplicate entries, relative size of A and B, etc.). But in all generality I tried a small piece of code that seems to do what you want. There are certainly quicker ways of doing it, and certainly more information on your problem could help optimize this.
colA=2;
% Example
nmax=10;
nA=5;
A=randi(nmax,[nA nA]);
nB=3;
B=randi(nmax,[1 nB]);
% Find rows
rows=cell(size(B));
for i=1:numel(B)
rows(i)={find(A(:,colA)==B(i))};
end
The input / output was:
A =
3 7 8 5 4
9 7 3 7 5
8 2 9 9 8
9 5 9 7 9
3 3 4 6 8
B =
1 7 5
rows =
[0x1 double] [1;2] [4]

Assuming you have two vectors, largeDataIndex (the second column of your matrix) and interestingIndex (your b) and you want the following:
For each value of interestingIndex , find the position in largeDataIndex
Then an easy method would be this:
result = zeros(size(interestingIndex))
for i = 1:length(result)
result(i) = find(interestingIndex(i) == largeDataIndex)
end
Note that this assumes there is always just one entry that matches, otherwise you should define result as a cell array rather than a vector.

Related

1) Extract submatrices, 2) vectorize and then 3) put back

I simplify my problem, let says I have three matrices.
I want to extract the red-boxed sub-matrices. I define
S = [1 4;
2 5]
that are the linear indices of the above matrices. So, A(S), B(S) and C(S) can extract the entries of the three matrices.
I pack them into vector by V = [ A(S)(:); B(S)(:); C(S)(:) ]. Let says after some manipulations, I obtain a new vector
V_new = [12 9 8 12 21 8 7 5 3 12 11 10]'
Here comes to my problem:
E.g for matrix A, I want to obtain
2->12, 5->9, 4->8 and 6->12
which are the first four entries of my V_new.
Since I have around 200 matrices, I have no idea to swap along the 200 matrices and the updated vector, V_new at the same time. Is writing a for-loop best way to do this purpose?
Thanks in advance.
Assuming that your A, B and C matrices have the same dimensions, rather work with a 3D matrix.
e.g. assuming your example matrices
M = cat(3,A,B,C)
No to extract those 4 upper left elements:
M_subset = M(1:2,1:2,:)
And then to reshape them into the vector you had:
V = M_subset(:)
then manipulate it to get V_new and finally put it back in the original:
M(1:2,1:2,:) = reshape(V_new,2,2,[])

How to move a number of columns in a matrix to the right most in matlab

Suppose I have an mxn matrix A. Suppose I have a list (or a vector) P of i elements where each element of P indicates the number of a column in A. I need to move all the columns indicated by P to the right most of A; for instance the the columns indicated in the first and the i'th elements in P will become the (n-i)'th and the n'th column of A respectively.
Hope my statement is clear, let me know if there is any ambiguity.
thanks.
To get the columns 3,5,7 to the right, first c is constructed which indicates the new order of columns. Then the columns are indexed using c which reorders them.
>> M=magic(10);
>> c=[3,5,7];
>> c=[setdiff(1:size(M,2),c),c]
c =
Columns 1 through 9
1 2 4 6 8 9 10 3 5
Column 10
7
>> M=M(:,c);

Matrix of Matrixes

Is there a simpler way to create a matrix of matrixes:
A first matrix (9 x 32) that contain value (through a loop) for each item. I'll have 8 item, so 8 matrix of (9 x 32). I'll have also 2 condition so 2 * 8 of matrix of (9 x 32).
What is the simplest way to create it?
According to Documentation you can use various techniques to create each matrix. If you have a specific matrix you need to copy you can use the repmat(M, v, h) function to repeatedly create it. Otherwise to create a multidimensional array you can do:
B = repmat(0, [r c 8 2])
That should give you the matrices you need as a 4 dimensional array, where r is the number of rows, c the columns, 8 the number of repetitions, and 2 conditions. Hopefully that helps you
Just do
A = zeros(m,n,8,2)
or
A(m,n,8,2) = 0;

Matlab matrices dimension

I am new to matlab and just wondering if you guys can help me out with this problem.
For instance, I have two matrices:
A = [X1 X2 X3 X4]
B = [Y1; Y2; Y3]
now what I really want to achieve is to multiply these two matrices in this way:
[X1Y1 X2Y1 X3Y1 X4Y1;
X1Y2 X2Y2 X3Y2 X4Y2;
X1Y3 X2Y3 X3Y3 X4Y3;
.... and so on]
I tried using A(1,:).*B(:,1) but matlab is saying that matrix dimensions must agree.
I just don't know how to manipulate this on matlab but in excel is possible.
This is a simple outer product. kron is not needed (although it will work.) bsxfun is wild overkill, although will yield what you have asked for. repmat is inappropriate, because while it will help you do what you wish, it replicates the arrays in memory, using more resources than are needed. (Avoid using inefficient programming styles when there are good ones immediately at your disposal.)
All you need use is the simple * operator.
A is a row vector. B a column vector.
C = B*A
will yield the result C(i,j)=B(i)*A(j), which is exactly what you are looking for. Note that this works because B is 3x1 and A is 1x4, so the "inner" dimensions of B and A do conform.
In MATLAB, IF you are unsure if something works, TRY IT!
A = [1 2 3 4];
B = [1;2;3];
C = B*A
ans =
1 2 3 4
2 4 6 8
3 6 9 12
See that kron did indeed work, although I'd bet that use of kron here is probably less efficient than is the simple outer product multiply.
C = kron(B,A)
C =
1 2 3 4
2 4 6 8
3 6 9 12
As well, bsxfun will work here too, although since we are using a general tool to do something that a basic operator will do, I'd bet it is slightly less efficient.
C = bsxfun(#times,B,A)
C =
1 2 3 4
2 4 6 8
3 6 9 12
The WORST choice is repmat. Again, since it artificially replicates the vectors in memory FIRST, it must go out and grab big chunks of memory in the case of large vectors.
C = repmat(B,1,4).*repmat(A,3,1)
C =
1 2 3 4
2 4 6 8
3 6 9 12
I suppose for completeness, you could also have used meshgrid or ndgrid. See that it is doing exactly what repmat did, but here it explicitly creates new matrices. Again, this is a poor programming style when there are good tools to do exactly what you wish.
[BB,AA] = ndgrid(B,A)
BB =
1 1 1 1
2 2 2 2
3 3 3 3
AA =
1 2 3 4
1 2 3 4
1 2 3 4
C = BB.*AA
C =
1 2 3 4
2 4 6 8
3 6 9 12
What you need to understand is exactly why each of these tools COULD have been used for the job, and why they are different.
In Matlab there is * and .* and they are very different.
* is normal matrix multiplication which is what you want i.e. B*A, note the B must come first as the inner dimension must match. You can multiply a column by a row but not a row by a column (unless they have the same number of elements).
.* is element by element multiplication in which case the matrices must be exactly the same size and shape so for example [1 2 3].*[4 5 6] = [1*4 2*5 3*6] = [4 10 18]
Do not do a ".*". You should rather do a "*".
The ".*" is for index by index multiplication and should have given you [X1Y1 X2Y2 X3Y3] were they vectors have been equal in size.
If you do the regular multiplication "*", this is actually matrix multiplication.
I think you just need to transpose one of the vectors. You are multiplying a column vector (A(1,:)) with a row vector (B(:,1)). This should work:
C = A(1,:).*B(:,1)';

matrix get min values of a matrix before max values occurred

I was trying to get the min values of a matrix before the max values of the matrix occurred. I have two matrices: matrix data and matrix a. Matrix a is a subset of matrix data and is composed of the max values of matrix data. I have the following code but obviously doing something wrong.
edit:
Matrix a are the max values of matrix data. I derived it from:
for x=1:size(data,1)
a(x)=max(data(x,:));
end
a=a'
clear x
matrix b code:
for x=1:size(data,1)
b(x)=min(data(x,(x<data==a)));
end
b=b'
clear x
matrix data matrix a matrix b
1 2 3 4 4 1
6 5 4 7 7 4
9 6 12 5 12 6
I need all the min values that occurred before to matrix a occurred in matrix data
Short and simple:
[a,idxmax] = max(data,[],2);
b = arrayfun(#(ii) min(data(ii,1:idxmax(ii))), 1:size(data,1));
which is the same as
b=NaN(1,size(data,1)); % preallocation!
for ii=1:size(data,1)
b(ii) = min(data(ii,1:idxmax(ii)));
end
Ignore maximum itself
If you want minimum of everything really before (and not including the maximum), it's possible that the maximum is the first number, and you try taking minimum of an empty matrix. Solution then is to use cell output, which can be empty:
b = arrayfun(#(ii) min(data(ii,1:idxmax(ii)-1)), 1:size(data,1),'uni',false);
Replace empty cells with NaN
If you want to replace empty cells to Nan and then back to a matrix use this:
b(cellfun(#isempty,b))={NaN};
b=cell2mat(b);
or simply use the earlier version and replace b(ii) with NaN when it is equal to a(ii) same outcome:
b = arrayfun(#(ii) min(data(ii,1:idxmax(ii))), 1:size(data,1));
b(b'==a) = NaN
Example:
data=magic(4)
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
outputs:
a' = 16 11 12 15
b =
16 5 6 4
and
b =[1x0 double] [5] [6] [4]
for the 2nd solution using cell output and ignoring the maximum itself also.
And btw:
for x=1:size(data,1)
a(x)=max(data(x,:));
end
a=a'
clear x
can be replaced with
a=max(data,[],2);
It's not pretty but this is the only way I found so far of doing this kind of thing without a loop.
If loops are ok I would recommend Gunther Struyf answer as the most compact use of matlab's in-built array looping function, arrayfun.
Some of the transposition etc may be superfluous if you're wanting column mins instead of row...
[mx, imx] = max(data');
inds = repmat(1:size(data,2), [size(data,1),1]);
imx2 = repmat(imx', [1, size(data,2)]);
data2 = data;
data2(inds >= imx2) = inf;
min(data2');
NOTE: if data is not needed we can remove the additional data2 variable, and reduce the line count.
So to demonstrate what this does, (and see if I understood the question correctly):
for input
>> data = [1,3,-1; 5,2,1]
I get minima:
>> min(data2')
ans = [1, inf]
I.e. it only found the min values before the max values for each row, and anything else was set to inf.
In words:
For each row get index of maximum
Generate matrix of column indices
Use repmat to generate a matrix, same size as data where each row is index of maximum
Set data to infinity where column index > max_index matrix
find min as usual.