Find 10 most repeated elements in a vector in MATLAB - arrays

I'm suppose to find 10 most repeated elements in a vector with n elements,
(the elements are from 1-100)
does anyone know how to do that?
I know how to find the one that is most repeated element in a vector but I don't know how to find 10 most repeated elements with n being unknown.

a = randi(10,1,100);
y = hist(a,1:max(a));
[~,ind] = sort(y,'descend');
out = ind(1:10);
for number of occurrences use y(ind(1:10)).
I had some doubts so I tested it many times, it seems to work.

You can use unique for that case. In my example, I have 4 numbers and I want to grep the 2 with the most occurances.
A = [1 1 3 3 1 1 2 2 1 1 1 2 3 3 3 4 4 4 4];
B = sort(A); % Required for the usage of unique below
[~,i1] = unique(B,'first');
[val,i2] = unique(B,'last');
[~,pos] = sort(i2-i1,'descend');
val(pos(1:2))
1 3
Replace val(pos(1:2)) by val(pos(1:10)) in your case to get the 10 most values. The get the number of elements you can use i1 and i2.
num = i2-i1+1;
num(1:2)
ans =
7 3

Since you already know how to find the most repeated element, you could use the following algorithm:
Find the most repeated element of the vector
Remove the most repeated element from the vector
Repeat the process on the new vector to find the 2nd most repeated element
Continue until you have the 10 most repeated elements
The code would look something like:
count = 0;
values = [];
while count < 10
r = Mode(Vector);
values = [values r]; % store most repeated values
Vector = Vector(find(Vector~=r));
count = count + 1;
end
Not efficient, but it'll get the job done

Related

How to iterate through a circular array multiple times in python?

I want to circle through the array multiple times. When I reach the last index, the next index should be the first one.
For example, I have an array of 6 elements
array1 = [1,2,3,4,5,6]
and I have K = 4. K will be the number of elements that I will skip.
In the above example, I will start from array1[0] and skip K elements including the array1[0] element.
So if I skip 4 elements, I will reach array1[4]. If I skip K elements once more, I should skip array1[4], array1[5], array1[0] and array1[1] and reach array1[2]. This process will repeat itself N times.
I tried searching for the solution online because I cannot think of a way to move through the array in circle. I found one solution that says to use modulo operator like this
print a[3 % len(a)]
but I cannot understand this since I am just starting out with python.
Understanding what modulo is will be helpful https://en.wikipedia.org/wiki/Modulo
To sum up, in this exercise you don't care how many times you went through the array. You only care about "at which position of the current iteration you are" lets say. Therefore, a modulo operation using the length of the array as modulo will give you the remainder of such division, which is exactly what you are looking for.
Example:
arr = [1,2,3,4,5]
k = 27
arrlength = len(arr) # 5
reminder = k % arrlength # 27 % 5 = 2
arr[reminder] # 3
So, the modulo operator returns the remainder from the division between two numbers.
Example:
6 % 2 = 0 # because 6/2 = 3 with no remainder
6 % 5 = 1 # because 6/5 = 1 (integer part) plus remainder 1
6 % 7 = 6 # because 7 doesn't fit in 6, so all the dividend goes into the remainder
So your problem can be solved by something like this:
arr = [1,2,3,4,5,6]
N = 5
step = 4
for i in range(5):
print(arr[(i+1)*step%len(arr)])
where N is the number of elements you want to print
This is the same as creating an extended list such as:
b = arr * 1000
and print each element in range(step,(N+1)*step,step).
Of course this method is not optimal since you don't now how many arrays arr you have to concatenate in order not to go out of bounds.
Hope it helped

How to find a sum 3 elements in array?

I have an array A=[a1,a2,a3, ..., aN] I would like to take a product of each 3 elements:
s1=a1+a2+a3
s2=a4+a5+a6
...
sM=a(N-2)+a(N-1)+aN
My solution:
k=size(A);
s=0;
for n=1:k
s(n)=s(n-2)+s(n-1)+s(n);
end
Error: Attempted to access s(2); index out of bounds because numel(s)=1.
Hoe to fix it?
If you want to sum in blocks, for the general case when the number of elements of A is not necessarily a multiple of the block size, you can use accumarray:
A = [3 8 5 8 2 3 4 7 9 6 4]; % 11 elements
s = 3; % block size
result = accumarray(ceil((1:numel(A))/s).', A(:));
If you want a sliding sum with a given block size, you can use conv:
A = [3 8 5 8 2 3 4 7 9 6 4]; % 11 elements
s = 3; % block size
result = conv(A(:).', ones(1,s), 'valid');
You try to calculate sby using values from s. Dont you mean s(n)=A(n-2)+A(n-1)+A(n);? Also size returns more than one dimension on its own.
That being said, getting the 2 privous values n-2 and n-1 doenst work for n=1;2 (because you must have positive indices). You have to explain how the first two values should be handeled. I assume either 0 for elements not yet exisiting
k=size(A,2); %only the second dimension when A 1xn, or length(A)
s=zeros(1,k); %get empty values instead of appending each value for better performance
s(1)=A(1);
s(2)=A(2)+A(1);
for n=3:k %start at 3
s(n)=A(n-2)+A(n-1)+A(n);
end
or sshoult be 2 values shorter than A.
k=size(A,2);
s=zeros(1,k-2);
for n=1:k-2
s(n)=A(n)+A(n+1)+A(n+2);
end
You initialise s as a scalar with s = 0. Then you try and index it like an array, but it only has a single element.
Your current logic (if fixed) will calculate this:
s(1) = a(1)+a(2)+a(3)
s(2) = a(2)+a(3)+a(4)
...
% 's' will be 2 elements shorter than 'a'
So we need to be a bit wiser with the indexing to get what you describe, which is
s(1) = a(1)+a(2)+a(3)
s(2) = a(4)+a(5)+a(6)
...
% 's' will be a third as big as 'a'
You should pre-allocate s to the right size, like so:
k = numel(A); % Number of elements in 'A'
s = zeros( 1, k/3 ); % Output array, assuming 'k' is divisible by 3
for n = 0:3:k-3
s(n/3+1) = a(n+1) + a(n+2) + a(n+3);
end
You could do this in one line by reshaping the array to have 3 rows, then summing down each column, this assumes that the number of elements in a is divisible by 3, and that a is a row vector...
s = sum( reshape( a, 3, [] ) );

How to check if all the entries in columns of a matrix are equal (in MATLAB)?

I have a matrix of growing length for example a 4-by-x matrix A where x is increasing in a loop. I want to find the smallest column c where all columns before that, each, carry one single number. The matrix A can look like:
A = [1 2 3 4;
1 2 3 5;
1 2 3 1;
1 2 3 0];
where c=3, and x=4.
At each iteration of the loop where A grows in length, the value of index c grows as well. Therefore, at each iteration, I want to update the value of c. How efficiently can I code this in Matlab?
Let's say you had the matrix A and you wanted to check a particular column iito see if all its elements are the same. The code would be:
all(A(:, ii)==A(1, ii)) % checks if all elements in column are same as first element
Also, keep in mind that once the condition is broken, x cannot be updated anymore. Therefore, your code should be:
x = 0;
while true
%% expand A by one column
if ~all(A(:, x)==A(1, x)) % true if all elements in column are not the same as first element
break;
end
x = x+1;
end
You could use this:
c = find(arrayfun(#(ind)all(A(1, ind)==A(:, ind)), 1:x), 1, 'first');
This finds the first column where not all values are the same. If you run this in a loop, you can detect when entries in a column start to differ:
for x = 1:maxX
% grow A
c = find(arrayfun(#(ind)~all(A(1, ind)==A(:, ind)), 1:x), 1, 'first');
% If c is empty, all columns have values equal to first row.
% Otherwise, we have to subtract 1 to get the number of columns with equal values
if isempty(c)
c = x;
else
c = c - 1;
end
end
Let me give a try as well:
% Find the columns which's elements are same and sum the logical array up
c = sum(A(1,:) == power(prod(A,1), 1/size(A,1)))
d=size(A,2)
To find the last column such that each column up to that one consists of equal values:
c = find(any(diff(A,1,1),1),1)-1;
or
c = find(any(bsxfun(#ne, A, A(1,:)),1),1)-1;
For example:
>> A = [1 2 3 4 5 6;
1 2 3 5 5 7;
1 2 3 1 5 0;
1 2 3 0 5 8];
>> c = find(any(diff(A,1,1),1),1)-1
c =
3
You can try this (easy and fast):
Equal_test = A(1,:)==A(2,:)& A(2,:)==A(3,:)&A(3,:)==A(4,:);
c=find(Equal_test==false,1,'first')-1;
You can also check the result of find if you want.

Matlab removing unwanted numbers from array

I have got a matlab script from net which generates even numbers from an inital value. this is the code.
n = [1 2 3 4 5 6];
iseven = [];
for i = 1: length(n);
if rem(n(i),2) == 0
iseven(i) = i;
else iseven(i) = 0;
end
end
iseven
and its results is this
iseven =
0 2 0 4 0 6
in the result i am getting both even numbers and zeros, is there any way i can remove the zeros and get a result like this
iseven =
2 4 6
To display only non-zero results, you can use nonzeros
iseven = [0 2 0 4 0 6]
nonzeros(iseven)
ans =
2 4 6
You can obtain such vector without the loop you have:
n(rem(n, 2)==0)
ans =
2 4 6
However, if you already have a vector with zeros and non-zeroz, uou can easily remove the zero entries using find:
iseven = iseven(find(iseven));
find is probably one of the most frequently used matlab functions. It returns the indices of non-zero entries in vectors and matrices:
% indices of non-zeros in the vector
idx = find(iseven);
You can use it for obtaining row/column indices for matrices if you use two output arguments:
% row/column indices of non-zero matrix entries
[i,j] = find(eye(10));
The code you downloaded seems to be a long-winded way of computing the range
2:2:length(n)
If you want to return only the even values in a vector called iseven try this expression:
iseven(rem(iseven,2)==0)
Finally, if you really want to remove 0s from an array, try this:
iseven = iseven(iseven~=0)
Add to the end of the vector whenever you find what you're looking for.
n = [1 2 3 4 5 6];
iseven = []; % has length 0
for i = 1: length(n);
if rem(n(i),2) == 0
iseven = [iseven i]; % append to the vector
end
end
iseven
To remove the all Zeros from the program we can use the following command,and the command is-
iseven(iseven==0)=[]

matlab: eliminate elements from array

I have quite big array. To make things simple lets simplify it to:
A = [1 1 1 1 2 2 3 3 3 3 4 4 5 5 5 5 5 5 5 5];
So, there is a group of 1's (4 elements), 2's (2 elements), 3's (4 elements), 4's (2 elements) and 5's (8 elements). Now, I want to keep only columns, which belong to group of 3 or more elements. So it will be like:
B = [1 1 1 1 3 3 3 3 5 5 5 5 5 5 5 5];
I was doing it using for loop, scanning separately 1's, 2's, 3's and so on, but its extremely slow with big arrays...
Thanks for any suggestions how to do it in more efficient way :)
Art.
A general approach
If your vector is not necessarily sorted, then you need to run to count the number of occurrences of each element in the vector. You have histc just for that:
elem = unique(A);
counts = histc(A, elem);
B = A;
B(ismember(A, elem(counts < 3))) = []
The last line picks the elements that have less than 3 occurrences and deletes them.
An approach for a grouped vector
If your vector is "semi-sorted", that is if similar elements in the vector are grouped together (as in your example), you can speed things up a little by doing the following:
start_idx = find(diff([0, A]))
counts = diff([start_idx, numel(A) + 1]);
B = A;
B(ismember(A, A(start_idx(counts < 3)))) = []
Again, note that the vector need not to be entirely sorted, just that similar elements are adjacent to each other.
Here is my two-liner
counts = accumarray(A', 1);
B = A(ismember(A, find(counts>=3)));
accumarray is used to count the individual members of A. find extracts the ones that meet your '3 or more elements' criterion. Finally, ismember tells you where they are in A. Note that A needs not be sorted. Of course, accumarray only works for integer values in A.
What you are describing is called run-length encoding.
There is software for this in Matlab on the FileExchange. Or you can do it directly as follows:
len = diff([ 0 find(A(1:end-1) ~= A(2:end)) length(A) ]);
val = A(logical([ A(1:end-1) ~= A(2:end) 1 ]));
Once you have your run-length encoding you can remove elements based on the length. i.e.
idx = (len>=3)
len = len(idx);
val = val(idx);
And then decode to get the array you want:
i = cumsum(len);
j = zeros(1, i(end));
j(i(1:end-1)+1) = 1;
j(1) = 1;
B = val(cumsum(j));
Here's another way to do it using matlab built-ins.
% Set up
A=[1 1 1 1 2 2 3 3 3 3 4 4 5 5 5 5 5];
threshold=2;
% Get the unique elements of the array
uniqueElements=unique(A);
% Count haw many times each unique element occurs
counts=histc(A,uniqueElements);
% Write which elements should be kept
toKeep=uniqueElements(counts>threshold);
% Make a logical index
indexer=false(size(A));
for i=1:length(toKeep)
% For every unique element we want to keep select the indices in A that
% are equal
indexer=indexer|(toKeep(i)==A);
end
% Apply index
B=A(indexer);

Resources