Dividing selected elements of array on Matlab - matlab

I have the following array
a = [ 1 10 3 4 68 2 34 8 10 ]
And I need to divide each number (/2) if this number is higher than 9.
This means that 1 has not to be divided, and 10 has to be divided (/2)
The resulting array should be:
a = [ 1 5 3 4 34 2 17 8 5 ]
I have to do it without using a FOR function. So I tried with this:
a = a./2;
This divides every number of the array, and I as told you before, I want to divide only the ones higher than 9.
Can anyone tell me how can I do it? Add a 'if whatever>5' in that statement or something?
Thanks in advance

Use logical indexing for both dividing only the numbers that meets your criterion and for assigning the result to those specific indices.
a = [ 1 10 3 4 68 2 34 8 10 ];
a(a>9) = a(a>9) ./ 2

Related

How to create a matrix B from a matrix A using conditions in MATLAB

If I have this matrix:
A:
X Y Z
1 1 2
0 3 4
0 5 6
2 7 8
7 9 10
8 11 12
3 13 14
12 14 16
15 17 18
How could I create new matrix B, C, D and E which contains:
B:
0 3 4
0 5 6
C:
X Y Z
1 1 2
2 7 8
3 13 14
D:
7 9 10
8 11 12
E:
12 14 16
15 17 18
The idea is to construct a loop asking if 0<A<1 else 1<A<5 else 6<A<10 else 11<A<15. and create new matrix from that condition. Any idea about how to store the results of the loop?
I suggest you an approach that uses the discretize function in order to group the matrix rows into different categories based on their range. Here is the full implementation:
A = [
1 1 2;
0 3 4;
0 5 6;
2 7 8;
7 9 10;
8 11 12;
3 13 14;
12 14 16;
15 17 18
];
A_range = [0 1 5 10 15];
bin_idx = discretize(A(:,1),A_range);
A_split = arrayfun(#(bin) A(bin_idx == bin,:),1:(numel(A_range) - 1),'UniformOutput',false);
celldisp(A_split);
Since you want to consider 5 different ranges based on the first column values, the arguments passed to discretize must be the first matrix column and a vector containing the group limits (first number inclusive left, second number exclusive right, second number inclusive left, third number exclusive right, and so on...). Since your ranges are a little bit messed up, feel free to adjust them to respect the correct output. The latter is returned in the form of a cell array of double matrices in which every element contains the rows belonging to a distinct group:
A_split{1} =
0 3 4
0 5 6
A_split{2} =
1 1 2
2 7 8
3 13 14
A_split{3} =
7 9 10
8 11 12
A_split{4} =
12 14 16
15 17 18
Instead of using a loop, use logical indexing to achieve what you want. Use the first column of A and check for the ranges that you want to look for, then use this to subset into the final matrix A to get what you want.
For example, to create the matrix C, find all locations in the first column of A that are between 1 and 5, then subset the matrix along the rows using these locations:
m = A(:,1) >= 1 & A(:,1) <= 5;
C = A(m,:);
You can repeat this in a similar way for the rest of the matrices you want to create.

How to rename values in order in matlab?

Say I have this vector A:
A=[2
92
91
91
91
92
9
92
-1
91];
I want to write a code to rename the smallest entry as 1, the next smallest entry as 2, and so on. So, I want the output to be:
B=[2
5
4
4
4
5
3
5
1
4];
How do I do that with a short and efficient code? The code I have been able to write is a "check one by one and rename" kind of code, which is highly inefficient.
U=unique(A);
for a=1:size(U,1)
for b=1:size(A,1)
if A(b,1)==U(a,1)
B(b,1)=a;
end
end
end
Is it possible to write one without using for loops, or one that is otherwise efficient?
As a consequence of unique sorting the output, your desired array is automatically built by the function and is accessible via the third output:
>> A=[2;92;91;91;91;92;9;92;-1;91];
>> [~,~,B] = unique(A)
B =
2
5
4
4
4
5
3
5
1
4

explanation of matlab data types

I'm having trouble understanding the datatypes in matlab. Why does this produce two different datatypes?
data = [25 8 15 5 6 10 10 3 1 20 7]
v = [1:8]
The first one produces a 1x11 double somehow and the second one I believe produces a vector right? How is the first one able to work with findpeaks when the documentation says it wants a vector?
I was trying to do this.
http://www.cyclismo.org/tutorial/matlab/vector.html
Typing
data = [25 8 15 5 6 10 10 3 1 20 7]
v = [1:8]
whos
returns
data =
25 8 15 5 6 10 10 3 1 20 7
v =
1 2 3 4 5 6 7 8
Name Size Bytes Class Attributes
data 1x11 88 double
v 1x8 64 double
so they are both the same, and I'd call them 1x11 vectors of doubles.

How to set an indexed value in a matrix based on another matrix's values

Say I have a matrix A
A =
0 1 2
2 1 1
3 1 2
and another matrix B
B =
0 42
1 24
2 32
3 12
I want to replace each value in A by the one associated to it in B.
I would obtain
A =
42 24 32
32 24 24
12 24 32
How can I do that without loops?
There are several ways to accomplish this, but here is an short one:
[~,ind]=ismember(A,B(:,1));
Anew = reshape(B(ind,2),size(A))
If you can assume that the first column of B is always 0:size(B,1)-1, then it is easier, becoming just reshape(B(A+1,2),size(A)).
arrayfun(#(x)(B(find((x)==B(:,1)),2)),A)

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