I have a sequence extracted from the measurement file and the sequence is shown below.
a=[2 1 3 2 1 0 1 2 3 4 5 4 3 2 3 4 5 4];
I want to find the starting indices of each decreasing sequence....
for eg: In the above sequence you can find the sequence starts decreasing at the following indices
1. [3 2 1] this sequence starts decreasing from the index 3,
2. [5 4 3 2] this sequence starts decreasing from the index 11,
3. [5 4] this sequence starts decreasing from the index 17.
Any idea regarding how to find this sequence starting point will be more useful... Thanks in advance
How about:
find(diff([0, diff(a) < 0]) == 1)
In other words find the index locations where the difference is negative (diff(a) < 0) and then choose only those that came after an increasing number.
Related
This question already has answers here:
How to obtain the mirror image of an array (MATLAB)?
(4 answers)
Closed 2 years ago.
During my course I came across that expression:
A(:,end:-1:1)
I have trouble to understand and read the morphemic structure of the 2nd Operand "end;-1;1"
Lets take the example:
A=[1 2 3; 4 5 6; 7 8 9]
I am aware of:
A(:).. Outputs [1 2 3; 4 5 6; 7 8 9] as rows. Operator is :.
A(1,:).. Outputs [1 2 3; 4 5 6; 7 8 9] as columns Operator is , then , .
A(:,1).. Outputs [1 2 3; 4 5 6; 7 8 9] as rows. Operator is , beforehand : .
A(:,end:-1:1)
Output in Matlab show me: 3x3 Matrix.
How am I supposed to read the structure?
Graphem: : ..show me the rows,
Graphem: end:-1 .. ??
Graphem: :1 ..
Somehow ":" was for me the operator for show all of the elements.
It makes sense to me that the "Operand1 , Operand2" shows me the 2 Dimensional Matrix.
First Idea:
The end:-1:1 expression seemed to me like a loop. So -1, 0, 1 => **3x Elements** ?
But when I type
A(1,end:3)
it only shows me the 3rd row.
Second Idea:
A(end:-1:1,1)
It shows me the inverted Matrix..
My background:
I am a undergraduate student from the field of language.
I build in my freetime the 8-Bit Sap1 according Ben Eater.
So I am familiar with program memory or instruction memory.
I understand only the result, but not how it is achieved by the MATLAB compiler.
Someone said to me that the "Matrixaddressing is somehow optimized".
Looking forward to a helpful answer in each step. :)
Thanks in advance!
The end keyword in matrix indexing indicates index of last element in the corresponding dimension. So, A(:,end:-1:1) simply means A(:, size(A, 2):-1:1), which in you example (A=[1 2 3; 4 5 6; 7 8 9]), is equivalent to A(:, 3:-1:1).
But to understand what it does, you need to know what 3:-1:1 does. It creates a subrange. You already know 1:3 creates [1, 2, 3]. 1:3 is simplified form of 1:1:3: rangeStrart:increment:rangeEnd. Now, 3:1 or 3:1:1 creates an empty vector, because rangeStart is greater than rangeEnd. To create [3, 2, 1] you need to use a negative step: 3:-1:1.
So, A(:,end:-1:1) means A(:, [3, 2, 1]), which inverts order of rows of A. Also, A(:,end:3) means A(:, 3:3) and eventually A(:, 3), which returns 3rd row of A.
Edit: about your misunderstandings, addressed by #CrisLuengo
I am aware of:
A(:).. Outputs [1 2 3; 4 5 6; 7 8 9] as rows. Operator is :.
A(1,:).. Outputs [1 2 3; 4 5 6; 7 8 9] as columns Operator is , then , .
A(:,1).. Outputs [1 2 3; 4 5 6; 7 8 9] as rows. Operator is ,beforehand : .
A(3, 2) is the element in the 3,2 position (third row, second column) of A
A(1, :) is equivalent to A(1, 1:size(A, 2)) and A(1, 1:end) and is the first row of A
A(:, 1) is equivalent to A(1:size(A, 1), 1) and A(1:end, 1) and is the first column of A
A(:) is equivalent to A(1:numel(A)) and is a single column containing all elements of A
In MATLAB, when accessing an array, it is accessed as A(row#,col#). row# and col# can either be integers or a vector of integers. If they are integers then one spot in the matrix is accessed. If they are vectors then MATLAB will loop through the vector and choose spots in A which correspond to the integers in the vector.
end:-1:1 creates a vector which contains the integers ranging from the number of columns (in this case because you put this vector in the col section: A(row#,col#)) to 1. Ex: 4x5 matrix, end:-1:1 would be [5 4 3 2 1].
When you put : in the row part of the matrix, that means you access all rows of the matrix.
Here's an example of A(:,end:-1:1)
The col# vector (:) is [1 2 3] and the row# vector (end:-1:1) is [3 2 1]
A = [1 2 3;
4 5 6;
7 8 9]
A(:,end:-1:1)
[3, 5, 7]
I think you're overthinking this slightly.
If we have a vector
A = [1 2 3]
and we call A(end:-1:1), then we get a vector [3 2 1]. The indexing has returned the same vector, with the values reversed. If we now have a matrix
A = [1 2 3; 4 5 6; 7 8 9]
and call A(:, end:-1:1), we get the matrix with the same values in each row, but now the columns have been reversed to give
A(:, end:-1:1) = [3 2 1; 6 5 4; 9 8 7].
Recall what the colon means in this context.
If we define a vector, v = (1:10), we get a vector with the first element being 1, the last element being 10 and each value in between being integers in steps of 1. If we instead define v = (1:2:10), we get the same, but the elements are separated by 2, not 1.
end:-1:1 is a vector made in just the same way. The first number is the final element in the row of A, and the final number is the first element in the row. Each number is separated by a value of -1. If we try
v = 10:-1:1
we get [10 9 8 7 6 5 4 3 2 1]. If we call v(2:4) we get the second, third and fourth elements of v. If we call v(1:end), we simply get v. If we call v(end:-1:1), we return v, with the elements in the reversed order.
Edit A typo.
Suppose to have an algorithm that find a partition of an array nodes=[1:10] based on some minimization problem. The output of the algorithm will be an array of indices indicating to which partition a certain nodes is assigned. For example: part=[1 1 1 1 3 3 2 2 2 2].
This algorithm has an issue though. It has a stochastic component and sometimes it can return the same partition but with a different numbering. For example part2=[2 2 2 2 3 3 1 1 1 1]. In this case part1 and part2 are de facto the same partition.
Let's say that I need to run the partitioning algorithm 5 times. The output will be a 5x10 matrix A. At the end I need to see how many different partitions the algorithm found. This implies that I need to know how many equivalent partitions are present in A.
I wrote an algorithm that does this but is really slow for large inputs.
Here an example of the input:
clusters=[ 1,1,2,2;
1,1,2,2;
2,2,1,1;
1,2,1,2;
2,1,2,1;
3,1,2,1;
2,1,2,1;
3,1,2,1;
1,2,1,2];
for which I obtain the different partitions, the most frequent partition and the number of times it occurs m:
true_clusters =
1 1 2 2
1 2 1 2
3 1 2 1
frequest =
1 2 1 2
m =
4
Does anyone know a fast way to solve the problem?
This is a vectorized version:
Consider rows [1 2 1 2] and [3 1 2 1] and [ 2 1 2 1] that have the same pattern because in all of them consecutive elements of each vector are different from each other so diff(clusters,1,2)~=0 for those rows generates the same pattern [1 1 1].
But that is not sufficient to get a correct answer for the algorithm.
Also for each row it is required to have unique elements that appear in it.
so in [1 1 2 2] the unique elements are [1 2] and for [3 1 2 1] unique elements are [1 2 3]
equally a logical vector can be created that represents if each of [1 2 3] are member of a row so for [1 1 2 2] logical vector is [1 1 0] and for [3 1 2 1] is [1 1 1] that accumarray do the mentioned task.
Concatenating two patterns as [diff(clusters,1,2)~=0 , ac] create an array that it's rows represent different partitions. then unique function can be applied to extract unique partitions
ac=accumarray([ repmat((1:size(clusters,1)).',size(clusters,2),1) clusters(:)],1,[],#any);
[~, v, I]=unique([diff(clusters,1,2)~=0 , ac],'rows');
many= hist(I,I(v));
true_clusters = clusters(v,:);
[m,im] = max(many);
frequest = true_clusters(im,:);
Result:
many = 3 4 2
true_clusters =
2 2 1 1
1 2 1 2
3 1 2 1
m = 4
frequest = 1 2 1 2
I don't know if it's fast enough for you:
[~,~,c] = unique(clusters','rows','stable');
c_unique = unique(c,'rows')
I've got a vector A = [6 5 7 7 4] and want to obtain the ranks as either [3 2 4 5 1] or [3 2 5 4 1] - I don't mind which. The answer is a vector in which each element is replaced by the rank it holds. This indicates to me that the fifth element is the smallest, then the second element is the second smallest, and so on.
I thought of doing [~,~,rnk] = unique(A), however that doesn't work, and produces instead [3 2 4 4 1].
How can I obtain the solution with no tied ranks?
It's almost a duplicate of this question.
We use sort twice, first sorting the array to get the index and then sort the index.
A = [6 5 7 7 4];
[~, rnk] = sort(A);
[~, rnk] = sort(rnk);
rnk =
3 2 4 5 1
How do I change the list of value to all 1? I need the top right to bottom left also end up with 1.
rc = input('Please enter a value for rc: ');
mat = ones(rc,rc);
for i = 1:rc
for j = 1:rc
mat(i,j) = (i-1)+(j-1);
end
end
final = mat
final(diag(final)) = 1 % this won't work?
Code for the original problem -
final(1:size(final,1)+1:end)=1
Explanation: As an example consider a 5x5 final matrix, the diagonal elements would have indices as (1,1), (2,2) .. (5,5). Convert these to linear indices - 1, 7 and so on till the very last element, which is exactly what 1:size(final,1)+1:end gets us.
Edit : If you would like to set the diagonal(from top right to bottom left elements) as 1, one approach would be -
final(fliplr(eye(size(final)))==1)=1
Explanation: In this case as well we can use linear indexing, but just for more readability and maybe a little fun, we can use logical indexing with a proper mask, which is being created with fliplr(eye(size(final)))==1.
But, if you care about performance, you can use linear indexing here as well, like this -
final(sub2ind(size(final),1:size(final,1),size(final,2):-1:1))=1
Explanation: Here we are creating the linear indices with the rows and columns indices of the elements to be set. The rows here would be - 1:size(final,1) and columns are size(final,2):-1:1. We feed these two to sub2ind to get us the linear indices that we can use to index into final and set them to 1.
If you would to squeeze out the max performance here, go with this raw version of sub2ind -
final([size(final,2)-1:-1:0]*size(final,1) + [1:size(final,1)])=1
All of the approaches specified so far are great methods for doing what you're asking.
However, I'd like to provide another viewpoint and something that I've noticed in your code, as well as an interesting property of this matrix that may or may not have been noticed. All of the anti-diagonal values in your matrix have values equal to rc - 1.
As such, if you want to set all of the anti-diagonal values to 1, you can cheat and simply find those values equal to rc-1 and set these to 1. In other words:
final(final == rc-1) = 1;
Minor note on efficiency
As a means of efficiency, you can do the same thing your two for loops are doing when constructing mat by using the hankel command:
mat = hankel(0:rc-1,rc-1:2*(rc-1))
How hankel works in this case is that the first row of the matrix is specified by the vector of 0:rc-1. After, each row that follows incrementally shifts values to the left and adds an increasing value of 1 to the right. This keeps going until you encounter the vector seen in the second argument, and at this point we stop. In other words, if we did:
mat = hankel(0:3,3:6)
This is what we get:
mat =
0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6
Therefore, by specifying rc = 5, this is the matrix I get with hankel, which is identical to what your code produces (before setting the anti-diagonal to 1):
mat =
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
Tying it all together
With hankel and the cheat that I mentioned, we can compute what you are asking in three lines of code - with the first line of code asking for the dimensions of the matrix:
rc = input('Please enter a value for rc: ');
mat = hankel(0:rc-1, rc-1:2*(rc-1));
mat(mat == rc-1) = 1;
mat contains your final matrix. Therefore, with rc = 5, this is the matrix I get:
mat =
0 1 2 3 1
1 2 3 1 5
2 3 1 5 6
3 1 5 6 7
1 5 6 7 8
Here's a simple method where I just add/subtract the appropriate matrices to end up with the right thing:
final=mat-diag(diag(mat-1))+fliplr(diag([2-rc zeros(1,rc-2) 2-rc]))
Here is one way to do it:
Say we have a the square matrix:
a = ones(5, 5)*5
a =
5 5 5 5 5
5 5 5 5 5
5 5 5 5 5
5 5 5 5 5
5 5 5 5 5
You can remove the diagonal, then create a diagonal list of ones to replace it:
a = a - fliplr(diag(diag(fliplr(a)))) + fliplr(diag(ones(length(a), 1)))
a =
5 5 5 5 1
5 5 5 1 5
5 5 1 5 5
5 1 5 5 5
1 5 5 5 5
The diag(ones(length(a), 1)) can be any vector, ie. 1->5:
a = a - fliplr(diag(diag(fliplr(a)))) + fliplr(diag(1:length(a)))
a =
5 5 5 5 1
5 5 5 2 5
5 5 3 5 5
5 4 5 5 5
5 5 5 5 5
I'm looking for an efficient MATLAB function which is able to transform a vector to a cell with group of unique numbers
e.g
from
a=[1 1 5 5 5 2 1 1 1 2 2 6 6 6 8 8 8 8]
to
a={[1 1] [5 5 5] [2] [1 1 1] [2 2] [6 6 6] [8 8 8 8]}
My previous approach was to locate the changing points before running within a loop:
e.g.
change_pts = a-[0,a(1:length(a)-1)];
for i=find(ans~=0)
% codes here
end
But it's obviously not an optimised solution.
Thank you
You can create a vectorized solution using the functions diff and mat2cell like so:
a = mat2cell(a, 1, diff([0 find([(diff(a) ~= 0) 1])]));
This works by first locating where the values change and marking the ends of sequences of equal numbers with a 1. It then finds the indices of all the ones and computes the spans between these indices (i.e. the counts for each sequence of equal numbers). These counts are then used by mat2cell to break the vector up into a cell array.