How to add up numbers with same value in matlab - matlab

So if i have an number array:
a b
1 2.5
1 1.2
3 2.5
4 0.4
6 3
3 1.2
i want to sum up numbers in column a with same value of of b in column 2, like this:
a b
4 2.5
4 1.2
4 0.4
6 3
so as you can see 1 and 3 add up and became 4, because they have the same value of b which is 2 and also to the rest of the numbers, so how i will do that? thanks
(PS: my real data is combination of integers and decimal no. thanks)

Assuming A to be the input array, you have two approaches to play with here.
Approach #1
A combination of accumarray and unique -
[unqcol2,~,idx] = unique(A(:,2),'stable')
[accumarray(idx,A(:,1)) unqcol2]
Approach #2
With bsxfun -
[unqcol2,~,idx] = unique(A(:,2),'stable')
[sum(bsxfun(#times,bsxfun(#eq,idx,1:max(idx)),A(:,1)),1).' unqcol2 ]

Related

get ordered integer vector from another vector

I have a vector:
v1 = [13 13 13 13 5 5 5 2 2 5 5];
and would like to create another vector, v2, such that if an element in v1 is the same as the previous element, it gets the same ordered (sequential) integer, eg:
v2 = [1 1 1 1 2 2 2 3 3 4 4];
Formalising Luis comment as a (community wiki) answer, you could do
cumsum([1, diff(v1)~=0]);
Which uses cumsum to do the running sum of a true/false array identifying where one element is different to the previous one, i.e. 1 where the value changed, 0 otherwise.

Alter number sort / number sequence

I have an array / number sequence a=[1,2,3,4,5] and I'm trying
to create an array / number sequence that looks like a_new below:
The columns represent the orders / index the numbers should go in.
a_new=...
[1,2,3,4,5;
2,1,2,3,4;
3,3,1,2,3;
4,4,4,1,2;
5,5,5,5,1]
My thoughts where to use circshift but quickly found out that would not work.
a=[1,2,3,4,5];
for n=1:5
a_wrong(:,n)=circshift(a(:)',[0 n])(:)
end
produces
a_wrong=[
5 4 3 2 1
1 5 4 3 2
2 1 5 4 3
3 2 1 5 4
4 3 2 1 5]
Any thoughts? It doesn't need to use circshift if that won't work.
PS: I'm using Octave 4.2 which is similar to Matlab
There are probably quite a few different ways to generate this matrix. Here's one using the functions repmat, toeplitz, tril, and triu:
>> a_new = tril(repmat(a.', 1, numel(a)), -1)+triu(toeplitz(a))
a_new =
1 2 3 4 5
2 1 2 3 4
3 3 1 2 3
4 4 4 1 2
5 5 5 5 1
I'm not sure about a built-in function, but this should work;
a=[1,2,3,4,5];
a_out = ones(length(a), length(a))
for n=1:5
a_out(n,:) = [n*ones(n-1),a(n:end)]
end
I do not have Octave or MATLAB installed on my computer, so I cannot test it. This may have a silly error, forgive me for that!
You can use spdiags to generate the matrix:
n = numel(a);
a_new = spdiags([repmat(flip(a).',1,n); repmat(a,n-1,1)],(1-n):0);

Selecting elements in matrix using matlab

My problem is this: I've a matrix, as example
1 2 3
4 2 6
6 1 8
4 5 4
7 1 5
8 2 0
I wish to extract selected values from the matrix, as example, a vector like this
B = [3 6 0]
selecting third column values when the value in the second column is 2.
I tried in different ways, but no one of these works.
Use this -
B = A(A(:,2)==2,3)' %// Assuming A is your input matrix
If M is your Matrix, you can select the second column using
M(:,2)
Compare it to two to get the lines which contain a 2
M(:,2)==2
And use this logical vector to select your elements from the third column.
M(M(:,2)==2,3)
A little more generally: if you want to select based on a set of values, use ismember to generate the logical index:
>> A(ismember(A(:,2), [2 5]) , 3) %// [2 5]: values you want to find in 2nd col
ans =
3
4
6
0

Duplicate the first row and the first column of a matrix

I have a 3*3 matrix A
A = [1 2 3
4 5 6
7 8 9];
I want to duplicate only the first row and column of this matrix. It should look like
1 1 2 3
1 1 2 3
4 4 5 6
7 7 8 9
can someone tell how can i do this in matlab
I think this is a good way just using indexing
A([1, 1:end], [1, 1:end])
You can do that by concatenating different parts of the original matrix:
B=[A(1) A(1,:);A(:,1) A];
In this expression A(1) is the top left element of A, A(1,:) is the first row and A(:,1) is the first column.
See the documentation on the colon operator.
In the code below, A is your starting point and I believe E is what you want to achieve.
You can of course combine all the intermediate expressions to achieve the final result in one step.
A= [1 2 3; 4 5 6; 7 8 9]
B= A(1:3,1:1)
C= [B A]
D= C(1:1,1:4)
E= [D;C]
A bit late in the game, but worthwhile answering. You can use padarray for that :
B = padarray(A,[1 1],'replicate','pre')
It's a one liner and more generic if you want to add more than just a single first and column ...

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