Let's say I have a matrix A, whose first column are IDs, and a vector B, containing certain IDs in a random order (and some of them might be missing etc).
How do I select the rows of A with matching IDs in the order given by B?
Example:
Using the matrices
A = [2, 0.4, 0.3;
9, 0.2, 0.8;
3, 0.3, 0.4;
5, 0.1, 0.5];
B = [9; 2; 5];
I would like to get the matrix
C = [9, 0.2, 0.8;
2, 0.4, 0.3;
5, 0.1, 0.5];
As per the revised stated problem, the first column of A are the IDs and B also contains certain IDs and we need to match A's IDs with those of B's and select the matching rows from A. Based on such an assumption, you can few approaches here.
Approach #1 [ With ismember]
[~,idx] = ismember(B,A(:,1))
C = A(idx,:)
Approach #2 [ With bsxfun]
[idx,~] = find(bsxfun(#eq,A(:,1),B'))
C = A(idx,:)
Approach #3 [ With intersect]
[~,~,idx] = intersect(B,A(:,1),'stable')
C = A(idx,:)
If your IDs are unique, positive integers, you could do the following:
Approach #4 [ With sparse and indexing]
Construct a sparse vector that corresponds to the mapping: ID -> rowIndex and evaluate this vector:
indexOfID = sparse(A(:,1), 1, 1:size(A,1));
C = A(indexOfID(B),:);
This could be beneficial, when you want to query your IDs more than once, as you only have to build indexOfID once.
(Also I do like the syntax of the "function evaluation" indexOfID(B))
Related
I have three vectors in a function, each of size 2. I want to get the sum of the top 2 numbers at each index. What I mean is this:
A = [4,4];
B = [3,5];
C = [5,6];
Sum = [9,11];
I would like to skip if-else statements if possible.
A simple way is to
concatenate the row vectors into a matrix: [A; B; C]
apply maxk along the first dimension: maxk(..., 2, 1), where 2 is the desired number of elements
then apply sum along the first dimension: sum(..., 1.
Thus:
result = sum(maxk([A; B; C], 2, 1), 1);
First, you concatenate your three vectors through
vectors = [A; B; C];
Then, you sort it through
s = sort(vectors, 'descent');
Finally, you sum the two bigger element of each column through
SUM = s(1, :) + s(2, :)
I have a question that is related to this post: "Cloning" row or column vectors. I tried to work around the answers posted there, yet failed to apply them to my problem.
In my case, I'd like to "clone" each row row of a matrix by converting a matrix like
A = [1,2; 3, 4; 5, 6]
into the matrix
B = [1, 2
1, 2
3, 4
3, 4
5, 6
5, 6]
by repeating each row of A a number of times.
So far, I was able to work with repmat for a single row like
A = [1, 2];
B = repmat(A, 2, 1)
>> B = [1, 2
1, 2]
I was trying to build a loop using that formula, in order to obtain the matrix wanted. The loop looked like
T = 3; N = 2;
for t = 1:T
for I = 1:N
B = repmat(C, 21, 1)
end
end
Has anyone an idea how to correctly write the loop, or a better way to do this?
kron
There are a few ways you can do this. The shortest way would be to use the kron function as suggested by Adiel in the comments.
A = [1,2; 3, 4; 5, 6];
B = kron(A, [1;1]);
Note that the number of elements in the ones vector controls how many times each row is duplicated. For n times, use kron(A, ones(n,1)).
kron calculates the kronecker tensor product, which is not necessarily a fast process, nor is it intuitive to understand, but it does give the right result!
reshape and repmat
A more understandable process might involve a combination of reshape and repmat. The aim is to reshape the matrix into a row vector, repeat it the desired number of times, then reshape it again to regain the two-column matrix.
B = reshape(repmat(reshape(A, 1, []), 2, 1), [], 2);
Note that the 2 within the repmat function controls how many times each row is duplicated. For n times, use reshape(repmat(reshape(A, 1, []), n, 1), [], 2).
Speed
A quick benchmark can be written:
% Setup, using a large A
A = rand(1e5, 2);
f = #() kron(A, [1;1]);
g = #() reshape(repmat(reshape(A, 1, []), 2, 1), [], 2);
% timing
timeit(f);
timeit(g);
Output:
kron option: 0.0016622 secs
repmat/reshape option: 0.0012831 secs
Extended benchmark over different sizes:
Summary:
the reshape option is quicker (~25%) for just duplicating the rows once each, so you should go for this option if you want to end up with 2 of each row for a large matrix.
the reshape option appears to have complexity O(n) for the number of row repetitions. kron has some initial overhead, but is much quicker when you want many repetitions and hardly slows down because of them! Go for the kron method if you are doing more than a few repetitions.
lets say that we have the next series of arrays:
A = [1, 2, -2, -24];
B = [1, 4, -7, -2];
C = [3, 1, -7, -14];
D = [11, 4, -7, -1];
E = [1, 2, -3, -4];
F = [5, 14, -17, -12];
I would like to create two arrays,
the first will be the maximum of each column for all arrays,
i.e.
Maxi = [11,14,-2 -1];
the second will be the minimum of each column for all arrays
i.e.
Mini= [1,1,-17 -24];
I am trying all day, using loops, with max, and abs but I cant make it work
in my problem have a matrix (100,200), so with the above example i am trying to easily approach the problem. The ultimate goal is to get a kinda fitting of the 100 y_lines of 200 x_points. The idea is to calculate two lines (i.e. max,min), that will be the "visual" boarders of all lines (maximum and minimum values for each x). The next step will be to calculate an array of the average of these two arrays, so in the end will be a line between all lines.
any help is more than welcome!
How about this?
Suppose you stack all the row vectors , namely A,B...,F as
arr=[A;B;C;D;E;F];% stack the vectors
And then use the max(), min() and mean() functions provided by Matlab. That is,
Maxi = max(arr); % Maxi is a row vector carrying the max of each column of arr
Mini = min(arr);
Meani = mean(arr);
You just have to stack them as shown above. But if you have 100s of row vectors, use a loop to stack them into array arr as shown above.
I have matrix X and A where
X = [x1, y1, 1, 1; x2, y2, 1, 3; x3, y, 2, 4]
A = [1, 1, 0; 1, 3, 1; 1, 4, 2]
I want to:
1. scan the last two columns for every row in X (FYI, these two number combinations are unique)
2. find those values in the first two columns of A
3. get the value of the last column in that row of A.
For example, for the first row of X, I get 1 and 1, so I find 1 and 1 for the first two columns in A (which appears to be the first row), so the number I want to get is 0.
I think I can do it using a loop and a "find" function if it were just one number I'm working with, but I'm new to matlab and have trouble with a combination of two numbers. I would appreciate your help!
The ismember function may be what you're looking for, along with the () and : operators to extract columns from an array.
% Map rows in X to rows in A
[tf,loc] = ismember(X(:,[3 4]), A(:,[1 2]), 'rows');
% Grab the corresponding value from A
rslt = A(loc, 3);
Now you have a logical vector tf that indicates for each row in X whether it was found in A, and loc, which holds the corresponding indexes in to the rows of A for the ones that matched. Then you use those indexes to index in to A to pull out the "value" or dependent variable columns. These are vectorized operations, so it'll be faster than doing it with loops and find().
Read through the documentation for ismember, unique, paren, and the functions they reference to get more background on Matlab's functions for doing recordwise searching like this.
How can I create an index-matrix that specifies which elements of a matrix to address?
So for example I have a matrix A which is 80 by 50. I know that A(1:5,:) addresses only the first 5 elements, but what if I want to multiply A with another matrix which also changes the elements to be addressed? So I want to multiply B(1,:) with A(1:5,:), and B(2,:) with A(10:15,:) and so on. Is there a smart way to specify this index-matrix where the information (1:5; 10:15, etc.) is stored?
Yes you can certainly define indices into a matrix using another matrix. Here is a simple example using a cell array to store the index list:
X =[1,2,3,4,5,6]
Idx = { [1, 2, 3], [4, 5, 6] }
Y = X( Idx{1} ) .* X( {Idx{2} )
Y = [ 4, 10, 18]