Matlab - Quickly subtract [1xN] array from [MxN] matrix elements [duplicate] - matlab

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
How to subtract a vector from each row of a matrix?
How can I divide each row of a matrix by a fixed row?
I have matrix (M1) of M rows and 4 columns. I have another array (M2) of 1 row and 4 columns. I'd like to subtract every element in M1 by its respective column element in M2. In other words, each column of M1 needs to be subtraced by the scalar in the same column position in M2. I could call repmat(M2,M,1), which would create a NEW matrix of size MxN, where each element in a column was the same, and then do a element by element subtraction:
M2new = repmat(M2,M,1)
final = M1 - M2new
, however, this is two lines of code and creates a new element in memory. What is the fastest and least memory intensive way of performing this operation?

Use bsxfun like in the following example.
x=magic(4);
y=x(1,:);
z=bsxfun(#minus,x,y)
z =
0 0 0 0
-11 9 7 -5
-7 5 3 -1
-12 12 12 -12
Here z is obtained by subtracting the first row from every row. Just replace x with your matrix and y with your row vector, and you'r all set.

bsxfun(.) can potentially be more efficient, but personally as an old timer, I'll would recommend not to totally ignore linear algebra based solutions, like:
> M1= magic(4)
M1 =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
> M2= M1(1, :)
M2 =
16 2 3 13
> M1- ones(4, 1)* M2
ans =
0 0 0 0
-11 9 7 -5
-7 5 3 -1
-12 12 12 -12
Let the actual use case and profiler to decide the functionality actually utilized.

Related

Matlab, Sum Function for a Matrix row

Basically the sum function calculate the sum of the columns, that is to say if we have a 4x4 matrix we would get a 1X4 vector
A = magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
sum(A)
ans =
34 34 34 34
But if I want to get the Summation of the rows then i have 2 methods, the first is to get the transpose of the matrix then get the summation of the transposed matrix,and finally get the transpose of the result...., The Second method is to use dimension argument for the Sum function "sum(A, 2)"
A = magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
sum(A,2)
ans =
34
34
34
34
The problem is here I cannot understand how this is done, If anyone could please tell me the idea/concept behind this method,
It's hard to tell exactly how sum internally works, but we can guess it does something similar to this.
Matlab stores matrices (or N-dimensional arrays) in memory using column-major order. This means the order for the elements in memory for a 3 x 4 matrix is
1 4 7 10
2 5 8 11
3 6 9 12
So it first stores element (1,1), then (1,2), then (13), then (2,1), ...
In fact, this is the order you use when you apply linear indexing (that is, index a matrix with a single number). For example, let
A = [7 8 6 2
9 0 3 5
6 3 2 1];
Then A(4) gives 8.
With this in mind, it's easy to guess that what sum(A,1) does is traverse elements consecutively: A(1)+A(2)+A(3) to obtain the sum of the first column, then A(4)+A(5)+A(6) to sum the second column, etc. In contrast, sum(A,2) proceeds in steps of size(A,1) (3 in this example): A(1)+A(4)+A(7)+A(10) to compute the sum of the first row, etc.
As a side note, this is probably related with the observed fact that sum(A,1) is faster than sum(A,2).
I'm really not sure what you are asking. sum takes two inputs, the first of which is a multidimensional array A, say.
Now let's take sA = size(A), and d between 1 and ndims(A).
To understand what B = sum(A,d) does, first we find out what the size of B is.
That's easy, sB = sA; sB(d) = 1;. So in a way, it will "reduce" the size of A along dimension d.
The rest is trivial: every element in B is the sum of elements in A along dimension d.
Basically, sum(A) = sum(A,1) which outputs the sum of the columns in the matrix. 1 indicates the columns. So, sum(A,2) outputs the sum of the rows in the matrix. 2 indicating the rows. More than that, the sum command will output the entire matrix because there is only 2 dimensions (rows and columns)

Filtering an adjacency matrix in matlab

I have got a nx3 adjacency matrix that contains nodes in the first two dimension and the correspondant weight in the third dimension. I want to filter the matrix for specific thresholds (for nodes indexing). For example, I want to keep the adjacency matrix for nodes smaller than 10.000, 20.000, etc. Which is the most efficient way to do so in matlab? I tried to do the following, find the index which correspond to nodes:
counter = 1;
for i=1: size(graph4, 1)
if (graph4(i,1) >30000) | (graph4(i,2) >30000)
bucket(counter) = i;
counter=counter+1;
end
end
Suppose the adjacency matrix is A as given below:
A =
8 1 6
3 5 7
4 9 2
11 4 9
6 8 10
7 12 5
17 10 15
12 14 16
13 18 11
If you want both column 1 and column 2 to be less than a value, you can do:
value = 10;
T = A(A(:,1) < value & A(:,2) < value, :)
T =
8 1 6
3 5 7
4 9 2
6 8 10
The following line seems to give the same results as your sample code (but it doesn't seem like it fits your description.
value = 10000;
bucket = find((A(:,1)>value) | A(:,2)>value)
I guess you made a mistake and want to increment the counter above the bucket-line and initialize it as counter = 0 before the loop? As it is now, it will be one more than the number of elements in the bucket-list.

Delete Specific Rows in Matlab

I have a fairly large 2x2 matrix containing date and temperatures. There is a cluster of NaNs and incorrect data. I used find to get the index that contains the incorrect data. These indexes are stored in another variable. How do i remove the rows (date and value) corresponding to the indices?
Thanks.
fairly large 2x2 matrix makes little or no sense.
This is part from MATLAB documentation
You can delete rows and columns from a matrix by assigning the empty array [] to those rows or columns. Start with
A = magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
Then, delete the second column of A using
A(:, 2) = []
This changes matrix A to
A =
16 3 13
5 10 8
9 6 12
4 15 1
Also you can delete multiple rows/columns at once:
A([1 3],:)=[]
A =
5 10 8
4 15 1

Creating new matrix from existing one

I have a matrix in Matlab, A =
1 2 3
4 5 6
7 8 9
10 11 12
Now I want to create a new matrix B derived from A. The new matrix should look like: B =
1 0
0 4
2 0
0 5
3 0
0 6
Is it possible to solve that without using FOR loop?
Easy with some indexing:
A=[1 2 3 ;
4 5 6 ;
7 8 9 ;
10 11 12 ];
B = zeros(2*size(A,2),2);
B(1:2:end,1)=A(1,:); % put first row values in first column of c
B(2:2:end,2)=A(2,:); % put énd row values in 2nd column of c
If you're only working with 4x4 matrices then yes it is.
You want to convert a 4x4 and using row x column convention you can access A's elements one at at time like so A[row][column]
Then you want a 6x2 matrix then you just call it with zeros B = zeros(6,2)
Then alternate down B[row][column] = A[row][column] and you should be able to build it out easily.

Find the increasing and decreasing trend in a curve MATLAB

a=[2 3 6 7 2 1 0.01 6 8 10 12 15 18 9 6 5 4 2].
Here is an array i need to extract the exact values where the increasing and decreasing trend starts.
the output for the array a will be [2(first element) 2 6 9]
a=[2 3 6 7 2 1 0.01 6 8 10 12 15 18 9 6 5 4 2].
^ ^ ^ ^
| | | |
Kindly help me to get the result in MATLAB for any similar type of array..
You just have to find where the sign of the difference between consecutive numbers changes.
With some common sense and the functions diff, sign and find, you get this solution:
a = [2 3 6 7 2 1 0.01 6 8 10 12 15 18 9 6 5 4 2];
sda = sign(diff(a));
idx = [1 find(sda(1:end-1)~=sda(2:end))+2 ];
result = a(idx);
EDIT:
The sign function messes things up when there are two consecutive numbers which are the same, because sign(0) = 0, which is falsely identified as a trend change. You'd have to filter these out. You can do this by first removing the consecutive duplicates from the original data. Since you only want the values where the trend change starts, and not the position where it actually starts, this is easiest:
a(diff(a)==0) = [];
This is a great place to use the diff function.
Your first step will be to do the following:
B = [0 diff(a)]
The reason we add the 0 there is to keep the matrix the same length because of the way the diff function works. It will start with the first element in the matrix and then report the difference between that and the next element. There's no leading element before the first one so is just truncates the matrix by one element. We add a zero because there is no change there as it's the starting element.
If you look at the results in B now it is quite obvious where the inflection points are (where you go from positive to negative numbers).
To pull this out programatically there are a number of things you can do. I tend to use a little multiplication and the find command.
Result = find(B(1:end-1).*B(2:end)<0)
This will return the index where you are on the cusp of the inflection. In this case it will be:
ans =
4 7 13