How to generate continuous numbers with repetitive increment in matlab - matlab

I would like to generate a continuous number with repetitive increment, for example,from 1 to 3. with a repetitive increment of 1 (x 5). so the output will be.
output =
[1
1
1
1
2
2
2
2
2
3
3
3
3
3]
five repetition of 1, then five repetition of 2 and so on.
I tried this code:
a = [1:1:3]
for i = a(:,1:end)
disp(i+zeros(5,1))
end
I got the same result, however, I can't put the output in one column. Thanks for the help.

Let
n = 3; % number of distinct numbers
s = 2; % starting number
m = 5; % number of repetitions of each number
A couple of options are
output = repelem(s:s+n-1,m);
or
output = ceil(s-1+1/m:1/m:s+n-1);

Related

Can I get 2 set of random number array in matlab?

idx=randperm(5)
idx=[1,3,4,2,5]
I know this works like that but I'm curious about is there anyway to get something like this.
idx=[1,3,4,2,5,5,3,2,4,1]
adding one set of array after one array
Is there any way to make that?
One vectorized way would be to create a random array of size (m,n), sort it along each row and get the argsort indices. Each row of those indices would represent a group of randperm values. Here, m would be the number of groups needed and n being the number of elements in each group.
Thus, the implementation would look something like this -
[~,idx] = sort(rand(2,5),2);
out = reshape(idx.',1,[])
Sample run -
>> [~,idx] = sort(rand(2,5),2);
>> idx
idx =
5 1 3 2 4
4 3 2 5 1
>> out = reshape(idx.',1,[])
out =
5 1 3 2 4 4 3 2 5 1
You can use the modulo operation:
n = 5 %maximum value
r = 2 %each element are repeated r times.
res = mod(randperm(r*n),n)+1

MATLAB: Creating a matrix with all possible group combinations

I'm running an experiment with lots of conditions, and particular numbers of groups in each condition.
A. 3 groups
B. 3 groups
C. 2 groups
D. 3 groups
E. 3 groups
I've worked out that there are 3×3×2×3×3 = 162 possible combinations of groups.
I want to create a MATLAB matrix with 162 rows and 5 columns. That is, one row for each combination and one column to indicate the value for each group.
So, for instance, the first row would be [1 1 1 1 1], indicating that this combination is group 1 for all conditions. The second row would be [1 1 1 1 2], indicating that it's group 1 for all conditions except for the last which is group 2. The 162nd and final row would be [3 3 2 3 3].
M = 1 1 1 1 1
1 1 1 1 2
.........
3 3 2 3 3
What's the most efficient way to achieve this? I realise I could use a loop, but feel sure there's a better way. I thought maybe the perms function would work but I can't see how.
You can use combvec (see last line, the rest is only generating test data):
% A. 3 groups
% B. 3 groups
% C. 2 groups
% D. 3 groups
% E. 3 groups
ngroups = zeros(5, 1);
ngroups(1) = 3;
ngroups(2) = 3;
ngroups(3) = 2;
ngroups(4) = 3;
ngroups(5) = 3;
v = {};
for i = 1:length(ngroups)
v{i} = 1:ngroups(i) % generate a vector of valid group indices
end
% get all possible combinations
x = combvec( v{:} )
As this will return a 5 x 162 double you need to transpose the resulting matrix x:
x.'

Unmatched arrays extending in Matlab

I wrote a code but when i am trying to change the variable schedule(2,:) it gives error. Here's the code:
clc;clear;
a = [1 2 3 4];
N = 3;
c=[1:12];
schedule(1,:) = kron(a,ones(1,N));% repeat 4 days
schedule(2,:) = repmat([1 2 3],1,((numel(c)/length(a)))+1); % repeat time slots in each day %nums col rep
schedule(3,:) = randperm(c(1,end)); % randomize 12 courses
schedule
I need a way of matching lengths of schedule(2,:) with other rows. When length of other rows is 20, schedule(2,:) does not build more than 20.
clc;clear;
day = [1 2 3 4];
n=length(day);
time=[1 2 3];
a=length(time);
schedule(1,:) = kron(day(1):n,ones(1,a));
schedule(2,:) = repmat(time,1,n);
schedule(3,:) = randperm(120,length(schedule(2,:)));
schedule
i have completed my code myself haha :) it is aflexible matrix and can accept any changes awithout errors

Count number of bouts separated by zeros

I have a vector like this:
A = [1 2 1 1 1 4 5 0 0 1 2 0 2 3 2 2 2 0 0 0 0 33]
I would like to count how many GROUPS of non zero elements it contains and save them.
so I want to isolate:
[1 2 1 1 1 4 5]
[1 2]
[2 3 2 2 2]
[33]
and then count the groups (they should be 4) :)
Can you help me please?
Thanks
To count your groups, a fast vectorized method using logical indexing is:
count = sum(diff([A 0]==0)==1)
This assumes that A is a row vector as in your example. This works with no zeros, all zeros, the empty vector, and several other test cases I tried.
To obtain your groups of values themselves, you can use a variation to my answer to a similar question:
a0 = (A~=0);
d = diff(a0);
start = find([a0(1) d]==1) % Start index of each group
len = find([d -a0(end)]==-1)-start+1 % Length, number of indexes in each group
In your case it might make sense to replace len with
finish = find([d -a0(end)]==-1) % Last index of each group
The length of start, len, and finish should be the same as the value of count so you could just use this if you need to do the breaking up. You can then use start and len (or finish) to store your groups in a cell array or struct or some other ragged array. For example:
count = length(start);
B = cell(count,1);
for i = 1:count
B{i} = A(start(i):finish(i));
end

Filtering sequences in MATLAB

Is it possible to do something like regular expressions with MATLAB to filter things out? Basically I'm looking for something that will let me take a vector like:
[1 2 1 1 1 2 1 3 3 3 3 1 1 4 4 4 1 1]
and will return:
[3 3 3 3 4 4 4]
These are the uninterrupted sequences (where there's no interspersion).
Is this possible?
Using regular expressions
Use MATLAB's built-in regexp function for regular expression matching. However, you have to convert the input array to a string first, and only then feed it to regexp:
C = regexp(sprintf('%d ', x), '(.+ )(\1)+', 'match')
Note that I separated the values with spaces so that regexp can match multiple digit numbers as well. Then convert the result back to a numerical array:
res = str2num([C{:}])
The dot (.) in the pattern string represents any character. To find sequences of certain digits only, specify them in brackets ([]). For instance, the pattern to find only sequences of 3 and 4 would be:
([34]+ )(\1)+
A simpler approach
You can filter out successively repeating values by checking the similarity between adjacent elements using diff:
res = x((diff([NaN; x(:)])' == 0) | (diff([x(:); NaN])' == 0))
Optionally, you can keep only certain values from the result, for example:
res(res == 3 | res == 4)
You can do it like this:
v=[1 2 1 1 1 2 1 3 3 3 3 1 1 4 4 4 1 1];
vals=unique(v); % find all unique values in the vector
mask=[]; % mask of values to retain
for i=1:length(vals)
indices=find(v==vals(i)); % find indices of each unique value
% if the maximum difference between indices containing
% a given value is 1, it is contiguous
% --> add this value to the mask
if max(indices(2:end)-indices(1:end-1))==1
mask=[mask vals(i)];
end
end
% filter out what's necessary
vproc=v(ismember(v,mask))
Result:
vproc =
3 3 3 3 4 4 4
This can be another approach, although a little bit too elaborated.
If you see the plot of your array, you want to retain its level sets (i.e. a == const) which are topologically connected (i.e. made by one piece).
Coherently, such level sets are exactly the ones corresponding to a==3 and a==4.
Here is a possible implementation
a = [1 2 1 1 1 2 1 3 3 3 3 1 1 4 4 4 1 1]
r = []; % result
b = a; % b will contain the union of the level sets not parsed yet
while ~isempty(b)
m = a == b(1); % m is the current level set
connected = sum(diff([0 m 0]).^2) == 2; % a condition for being a connected set:
% the derivative must have 1 positive and 1
% negative jump
if connected == true % if the level set is connected we add it to the result
r = [r a(m)];
end
b = b(b~=b(1));
end
If you try something like
a = [1 2 1 1 1 2 1 3 3 3 3 1 1 4 4 4 1 1] %initial vector
b = a>=3 %apply filter condition
a = a(b) %keep values that satisfy filter
a will output
a = [3 3 3 3 4 4 4]