find group of elements in matrix matlab - matlab

I have an array of elements E = [1 2 3 4 5 10] and matrix A of couples of elements
A=[ 1 2;
2 3;
3 1;
4 1;
4 3;
5 1]
You can read this matrix as
1 is similar (with a certain probability) to 2
2 is similar (with a certain probability) to 3
3 is similar (with a certain probability) to 1 etc...
I would like to know how many different groups of element are in the array E given the matrix A
In this case I have
1 group = 1 2 3
2 group = 1 3 4
3 group = 1 5
4 group = 10
so there are 4 different groups of elements in E
NOTE:
if 1 is similar to 2 (first row)
and if 5 is similar to 1 (sixth row)
5 is not similar to 2!!! (if it is not written anywhere)
so 1 2 5 don't belong to the same group
On the other hand
1 is similar to 2 (first row),
2 is similar to 3 (second row)
and 3 is similar to 1 (third row)
so 1 2 3 belong to the same group

Related

Sum of each two elements using vector functions

How to get sum of eath two elements with the vector functions? I want the same result as:
{x+y}':[1 2 3 2 1]
Why this approach gives something different than first one?
sum':[1 2 3 2 1]
sum is not the same as {x+y}.
sum has rank 1 meaning it takes one input and sums the elements of that input.
It can sum an atom:
q)sum 1
1
a uniform list
q)sum 1 2
3
or a list of lists
q)sum(1 2;3 4)
4 6
{x+y} is rank 2 meaning it requires two inputs.
q){x+y}[1;2]
3
q){x+y}[1 2;3 4]
4 6
Giving it an atom, a single list, or a list of lists leads to projections
q){x+y}1
{x+y}[1]
q){x+y}1 2
{x+y}[1 2]
q){x+y}(1 2;3 4)
{x+y}[(1 2;3 4)]
Since each-prior (':) creates binary pairs from the input and attempts to apply a rank 2 function, it works as intended on your rank 2 function {x+y}.
But since sum is not rank 2 the each-prior doesn't generate pairs in the same way, it's equivalent to doing
q){x}':[1 2 3 2 1]
1 2 3 2 1
q){sum x}':[1 2 3 2 1]
1 2 3 2 1
You could force it to be rank 2:
q){sum(x;y)}':[1 2 3 2 1]
1 3 5 5 3
but this gives a different result since sum ignores nulls while + doesn't.
q)sum(0N;1)
1
q)0N+1
0N
Finally, an alternative way to achieve this using sum (and without using each-prior) is to shift the vector using prev and then sum
q){sum(prev x;x)}[1 2 3 2 1]
0N 3 5 5 3

Nested loop and conditional statement (Matlab)

If you have a random matrix, for example a 5x5:
A(i,j) = (5 4 3 2 1
4 3 2 1 0
5 4 3 2 1
4 3 2 1 0
5 4 3 2 1)
And a second array:
B(1,j) = (4 5 6 7 8)
How can I then assign values of B to A if this only needs to be done when the value of B(1,j) is larger than any of the values from a certain colomn of A?
For example, B(1,1) = 4 and in the first colomn of A it is larger than A(1,1), A(3,1) and A(5,1), so these must be replaced by 4. In the second colomn, nothing needs to be replaced, etc.
Thanks already!
You can do this without any explicit looping using bsxfun:
A = [5 4 3 2 1
4 3 2 1 0
5 4 3 2 1
4 3 2 1 0
5 4 3 2 1];
B = [4 5 6 7 8];
A = bsxfun(#min,A,B);
Result:
A =
4 4 3 2 1
4 3 2 1 0
4 4 3 2 1
4 3 2 1 0
4 4 3 2 1
In later versions of MATLAB (2016b and later) you can even omit the bsxfun and get the same result.
A = min(A,B);
Matlab "find" may be of use to you.
https://www.mathworks.com/help/matlab/matlab_prog/find-array-elements-that-meet-a-condition.html
If you aren't concerned about speed or efficiency, you could also set up a two nested for loops with a condition (i.e. an if) statement comparing the values of A and B.
If you only interested in column wise comparison to B, you could use the increment of the outer loop in the inner loop.
for i,...
for j,...
if B(1,i) > A(j,i)
A(j,i)=B(i,j)

MATLAB - Frequency of an array element with a condition

I need some help please. I have an array, as shown below, 6 rows and 5 columns, none of the elements in any one row repeats. The elements are all single digit numbers.
I want to find out, per row, when a number, let's say 1 appears, I want to keep of how often the other numbers of the row appear. For example, 1 shows up 3 times in rows one, three and five. When 1 shows up, 2 shows up one time, 3 shows up two times, 4 shows up two times, 5 shows up one time, 6 shows up two times, 7 shows up one time, 8 shows up three times, and 9 shows up zero times. I want to keep a vector of this information that will look like, V = [3,1,2,2,1,2,1,3,0], by starting with a vector like N = [1,2,3,4,5,6,7,8,9]
ARRAY =
1 5 8 2 6
2 3 4 6 7
3 1 8 7 4
6 5 7 9 4
1 4 3 8 6
5 7 8 9 6
The code I have below does not give the feedback I am looking for, can someone help please? Thanks
for i=1:length(ARRAY)
for j=1:length(N)
ARRAY(i,:)==j
V(j) = sum(j)
end
end
Using indices that is in A creae a zero and one 6 * 9 matrix that [i,j] th element of it is 1 if i th row of A contains j.
Then multiply the zero and one matrix with its transpose to get desirable result:
A =[...
1 5 8 2 6
2 3 4 6 7
3 1 8 7 4
6 5 7 9 4
1 4 3 8 6
5 7 8 9 6]
% create a matrix with the size of A that each row contains the row number
rowidx = repmat((1 : size(A,1)).' , 1 , size(A , 2))
% z_o a zero and one 6 * 9 matrix that [i,j] th element of it is 1 if i th row of A contains j
z_o = full(sparse(rowidx , A, 1))
% matrix multiplication with its transpose to create desirable result. each column relates to number N
out = z_o.' * z_o
Result: each column relates to N
3 1 2 2 1 2 1 3 0
1 2 1 1 1 2 1 1 0
2 1 3 3 0 2 2 2 0
2 1 3 4 1 3 3 2 1
1 1 0 1 3 3 2 2 2
2 2 2 3 3 5 3 3 2
1 1 2 3 2 3 4 2 2
3 1 2 2 2 3 2 4 1
0 0 0 1 2 2 2 1 2
I don't understand how you are approaching the problem with your sample code but here is something that should work. This uses find, any and accumarray and in each iteration for the loop it will return a V corresponding to the ith element in N
for i=1:length(N)
rowIdx = find(any(A == N(i),2)); % Find all the rows contain N(j)
A_red = A(rowIdx,:); % Get only those rows
V = [accumarray(A_red(:),1)]'; % Count occurrences of the 9 numbers
V(end+1:9) = 0; % If some numbers don't exist place zeros on their counts
end

Possible combinations - order is important

I want to create a table which contains all possible combinations, order is important, of N numbers in sets of k using matlab.
I tried Combinations = combntns(set,subset) and Combinations = perms(v) and Combinations = combnk(v,k)but in those order is not important.
An example:
nchoosek(1:5,3)
ans =
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
While it should also include
1 3 2
1 4 2
1 5 2
1 3 5
1 5 3
...
The number of possible combinations is given by the following by the function:
N!/(N-k)!
source: Mathisfun.com
Is there a possible way to do it this using matlab functions?
Try this memory efficient solution:
n = 5; k = 3;
nk = nchoosek(1:n,k);
p=zeros(0,k);
for i=1:size(nk,1),
pi = perms(nk(i,:));
p = unique([p; pi],'rows');
end
p should contain what you are describing. At least size(p,1) == factorial(n)/factorial(n-k) or 60 for this example.

Unique rows which have the max element on the last column in matlab

I have a matrix with the same rows which are different only in two columns, like this:
A = [2 3 3 3 1 0.7;
2 3 3 3 2 0.4;
3 2 2 2 1 0.8;
3 2 2 2 3 0.3]
Now I need to select unique rows which have the same elements of column1,2,3,4 and have the maximum elements in column6, like:
Response: [2 3 3 3 1 0.7;
3 2 2 2 1 0.8]
Sort according the first 4 columns, and in descending order according to 6th. Then, pick first occurrence within groups decided by first 4 columns.
out = sortrows(A,[1:4,-6]);
[~,idx] = unique(out(:,1:4),'rows');
out(idx,1:5)