Count the number of membership changes across multiple vectors - matlab

I have 2 vectors in which elements of a similar value are considered to be of the same group, something like this:
V1 V2
1 7
1 8
1 8
1 8
1 9
2 10
3 11
3 11
3 11
3 12
4 12
4 12
In this example, V1 has 4 groups, group 1 has the first 5 elements , group 2 has the next 1 element, group 3 has the next 4 elements, and group 4 has the last 2 elements. V2 has 5 groups, group 1 has the first element, group 2 has the next 3 elements, etc.
Now, I would like to count the number of time an element switches groups, using V1 as the reference. Let's consider group 1 in V1. The first 5 elements are in this same group. In V2, that's no longer the case because V2(1,1) and V2(5,1) do not have the same value as the remaining elements and thus are considered to have switched/changed membership. Applied the same principle, there is no switch for group 2 (i.e.,V1(6,1) and V2(6,1)), one switch for group 3, and no switch for group 4. Total is 3 switches.
At first I thought this would be a simple calculation with no. of switches = numel(unique(V1)) - numel(unique(V2)). However, as you can see, this underestimates the number of switches. Does anyone have a solution to this?
I also welcome a solution to a simpler problem in which V1 contains only one group, like this:
V1 V2
2 7
2 8
2 8
2 8
2 8
2 8
2 8
2 9
2 8
2 10
2 10
2 8
In this second case, the count is 4 nodes that switch: V2(1,1), V2(8,1), V2(10,1), V2(11,1).
Side note: this is actually a network problem: V1 and V2 are partitions and I'm trying to count the number of time a node switches membership.

Here is a solution using unique and accumarray
u = unique([V1 V2],'rows');
switches = accumarray(u(:,1) , 1, [],#numel)-1;
total_switches = sum(switches)
or you can use histcounts
u = unique([V1 V2],'rows');
switches = histcounts(u(:,1) , [unique(u(:,1)); u(end,1)])-1;
total_switches = sum(switches)

Related

How to add an iterative id column which goes up when a value in another column resets to 1 in Postgresql

I have a SQL table which has two columns called seq and sub_seq as seen below. I would like to add a third column called id, which goes up by 1 every time the sub_seq starts again at 1 as shown in the table below.
seq
sub_seq
id
1
1
1
2
2
1
3
3
1
4
4
1
5
5
1
6
1
2
7
2
2
8
3
2
9
1
3
10
2
3
11
3
3
12
4
3
13
5
3
14
6
3
15
7
3
I could write a solution using plpgsql, however I would like to know if there is a way of doing this in standard SQL. Any help would be greatly appreciated.
If sub_seq is always a running sequence then you can use the DENSE RANK function and order over the differences of two columns, assuming it will consistently uniform.
SELECT seq, sub_Seq, DENSE_RANK() OVER (ORDER BY seq-sub_Seq) AS id
FROM tableDemo
This solution is based on the sample data you have provided, I think more sample data would be helpful to check the whole scenario.

extract the unique blocks from matrix using Mean Square Error matlab

The Mean Square Error(MSE), is a method used to define the difference in between two blocks, and can be calculated as follow: a and b two blocks equal size
MSE = sqrt(sum(sum((a-b).^2)))/size(a or b)
If the MSE is less than a given threshold, than the two blocks are not different.
Given a matrix A, already reshaped to be contain blocks all in the same raw,
the purpose is to extract all blocks where the MSE is less than a given threshold (based on the first block), then return the mean of those blocks. again, extract the second group of blocks which the MSE is less than the given threshold where the blocks that already assigned to be a part of other group of blocks must not be extracted again. Better than that, it must be deleted to reduce the search time. and so on till all blocks of the matrix A are assigned to be part of a group. the blocks of the resulted matrix should be organized based on the number of block within the group, from the biggest number of blocks to the lowest. And here is an example :
Given matrix A where the size of A is 2 by 14:
A= [1 1 2 2 9 9 4 4 6 6 5 5 3 3
1 1 2 2 9 9 4 4 6 6 5 5 3 3];
PS: its not necessary the blocks contain the same numbers, it is just to make the example clear.
blocks size is : 2 by 2
the threshold is 2
now we extract all blocks where the MSE is less than the threshold starting from the first block in the matrix A. so the blocks are:
1 1 2 2 3 3
1 1 2 2 3 3
the mean of those blocks is
Result= [ 2 2
2 2];
again. we extract all blocks where the MSE is less than the threshold, but we need to avoid the blocks that already extracted, so the second group of blocks is :
9 9
9 9
the mean of this block is it self, so:
Result= [2 2 9 9
2 2 9 9];
again. we extract all blocks where the MSE is less than the threshold, but we need to avoid the blocks that already extracted, so the third group of blocks is :
4 4 6 6 5 5
4 4 6 6 5 5
the block
3 3
3 3
is not a part of this group even if the MSE is less then the threshold because is already extracted to be part of the first group.
the mean of those blocks is:
5 5
5 5
therefore the result should be:
Result= [2 2 5 5 9 9
2 2 5 5 9 9 ];
there are any fast way to apply that ?
PS: that Datasize is huge, therefore , there are a need for a fast way to do that.

How to find out if numbers are different in pascal?

i can't solve one pascal problem, first i have to enter N which is the number or mesurments, next i enter those mesurments (if N is 5 i enter 5 mesurments for exmaple 3 4 5 6 7). After that i enter Q which is the number of times i check the number of different numbers in a specific part of the row. For example you have input
5 (number of mesurments)
1 2 3 3 4 (mesurments)
3 (number of checkings)
1 3
3 4
1 5 (left number is the starting number from the row, if it's 1 you start from 1, if it's 4 you start from 3 because 3 is the fourth mesurment and the right number is the last number if it's 5 it would be 4 because 4 is the fifth in the row)
And for output you would get
3
1
4 (for the first checking you have number from 1 to 3 (1 2 3) and you have 3 different numbers, second mesurment from 3 to 4 (3 3) and it's 1 different number and last from 1 to 5 there are 4 different numbers)
Hope you understod me, and thanks if you can solve it, i am in highschool now and i am preparing my self for something more complicating :) thanks in advance
The inequality operator of Pascal is <>

MATLAB: Conditionally matrix elements into two separate cell arrays

A matrix has 2 rows and several columns, and the first contains alternating strings of 1's and 0's. I want to use this binary as a decision to copy the information below it into one of two cell arrays. I understand that this can be done through iteration with the use of the IF conditional, or with while loops, but I'm having trouble cleaning it up.
For example, for
mat = [ 1 1 1 0 0 1 1 0 0 0 0 1 1 1 ;...
1 2 3 4 5 6 7 1 2 3 4 5 6 7 ]
I would like to output two cell arrays, one for the '1s', and one for the '0s':
1 2 3
6 7
5 6 7
and:
4 5
1 2 3 4
There are a couple of ways of doing this, I am sure. One might be using a loop; however, you can also make good use with the built-in find function. Below is a sample solution based on your example.
For '1s',
Here, we would like to get the indices with '1' from the first row.
on_array= mat(2, find(mat(1,:)));
or as suggested by #H.Muster
on_array= mat(2, mat(1,:)==1);
For '0s',
Here, we would like to get the indices with '0' from the first row.
off_array = mat(2, find(mat(1,:)==0));
or as suggested by #H.Muster
off_array= mat(2, mat(1,:)==0);
For the output format(the one that you want), i am sure you know what to do. Good luck.

how do I put the results from an iteration into an array in matlab

a=[1 2 3 4
5 6 7 8
8 7 6 5
4 3 2 1]
for i=(1:4)
b=(a(i,:));
c=sort(b,2)
end
Please, How can I obtain the results from this iteration in a single array(4x4) instead of getting the results of c=sort(b,2) separately for each loop.
You don't have to use a loop at all! You're trying to sort the columns in each row. This can be achieved by supplying an optional argument to sort.
c=sort(a,2);
c=
1 2 3 4
5 6 7 8
5 6 7 8
1 2 3 4
should give you what you need. The argument 2 tells sort to sort a by columns. If you wanted to sort it by rows, you'd use c=sort(a,1)