for loop logic in matlab / octave incrementing - matlab

I have two lines where ii should increment 1:12
1 2 3 4 5 6 7 8 9 10 11 12
for ii=1:6
ii %line1
ii+1 %line2
end
Instead I get ii
1 2 2 3 3 4 4 5 5 6 6 7
Ps: I need to use two lines in the for loop due to functions being called from these lines and filenames are created based on ii variable

If you really need two lines, try:
for ii=1:6
ii*2-1
ii*2
end

Related

Replace values from a certain row onwards column-wise

I have a 10x5 double matrix mat. I also have a 1x5 row vector start_rows. In mat I would like to replace all numbers from specific rows onwards using start_rows. I could use a loop and replace all the numbers column by column. However, I'm sure there is some vectorized solution.
mat = nan(10, 5);
start_rows = [3,5,1,7,2];
% How to avoid that loop
for idx = 1 : numel(start_rows)
mat(start_rows(idx):end, idx) = 1;
end
This can be solved comparing an array of the following form to your start_rows vector:
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
6 6 6 6 6
7 7 7 7 7
8 8 8 8 8
9 9 9 9 9
10 10 10 10 10
which will return a logical array for when the condition is met (this uses broadcasting AKA implicit expansion).
If mat always contains zeros, and you're replacing with ones:
(1:size(mat,1)).'+ mat >= start_rows;
If mat is nonzero:
(1:size(mat,1)).'+ 0*mat >= start_rows; % option 1
(1:size(mat,1)).'+ zeros(size(mat)) >= start_rows; % option 2
If replacing with values other than 1 (or true):
((1:size(mat,1)).'+ 0*mat >= start_rows) * newVal;

Is there any command to find mean of first 5 values then next 5 values for a total of 1000 values in a vector in MATLAB

Is there any command to find mean of first 5 values then next 5 values from a total of 25 values present in a vector in MATLAB. If the dataset is X.
If anyone can help me to provide a code where I can get mean at every 5th value.
X=[4 5 6 7 2 5 7 4 2 6 7 3 2 1 5 7 8 3 4 6 8 4 2 6 8];
You can for instance reshape the vector in an array with reshape and then apply the mean function:
M = mean(reshape(X, [5, numel(X)/5]),1);
or simply
M = mean(reshape(X, 5, []),1);
But there as stated in the comments there are many other ways.
Here is one simple way to do it. Rearrange the vector into a matrix loop over the columns and take the mean of all values in each column. Store the results in a new vector.
X=[4 5 6 7 2 5 7 4 2 6 7 3 2 1 5 7 8 3 4 6 8 4 2 6 8];
Xr = reshape(X,5,5)
cols = size(Xr)(2)
avgs=zeros(1,cols)
for i= 1:cols
avgs(i) = mean(Xr(:,i))
end

Alter number sort / number sequence

I have an array / number sequence a=[1,2,3,4,5] and I'm trying
to create an array / number sequence that looks like a_new below:
The columns represent the orders / index the numbers should go in.
a_new=...
[1,2,3,4,5;
2,1,2,3,4;
3,3,1,2,3;
4,4,4,1,2;
5,5,5,5,1]
My thoughts where to use circshift but quickly found out that would not work.
a=[1,2,3,4,5];
for n=1:5
a_wrong(:,n)=circshift(a(:)',[0 n])(:)
end
produces
a_wrong=[
5 4 3 2 1
1 5 4 3 2
2 1 5 4 3
3 2 1 5 4
4 3 2 1 5]
Any thoughts? It doesn't need to use circshift if that won't work.
PS: I'm using Octave 4.2 which is similar to Matlab
There are probably quite a few different ways to generate this matrix. Here's one using the functions repmat, toeplitz, tril, and triu:
>> a_new = tril(repmat(a.', 1, numel(a)), -1)+triu(toeplitz(a))
a_new =
1 2 3 4 5
2 1 2 3 4
3 3 1 2 3
4 4 4 1 2
5 5 5 5 1
I'm not sure about a built-in function, but this should work;
a=[1,2,3,4,5];
a_out = ones(length(a), length(a))
for n=1:5
a_out(n,:) = [n*ones(n-1),a(n:end)]
end
I do not have Octave or MATLAB installed on my computer, so I cannot test it. This may have a silly error, forgive me for that!
You can use spdiags to generate the matrix:
n = numel(a);
a_new = spdiags([repmat(flip(a).',1,n); repmat(a,n-1,1)],(1-n):0);

Running 3 for loops in parallel in Matlab

I have three mobile operators O1,O2, and O3, each of them has its own mobile ( N_M_O1,N_M_O2, and N_M_O3) they are sharing the base stations (B1 and B2) represented by (conter_B1,conter_B2) I need to associate every mobile that belongs to (operator (O1) or operator (O2) or operator (O3)) to the base stations (B1 and B2)independently,however each mobile should ask the base stations (B1,B2) first if the conter_B1 and conter_B2 more than 10 they reject to associate with the next mobile (which is number 11).
The problem is the implementation of multiple loops in Matlab will be sequencially means that Matlab will run loop1 then finish all iterations (for example if have 200 iterations) then start to run the second loop (loop2) and update the result after that start to run the third loop3
I need to run all the loops (loop1,loop2,loop3) at the same time and update the result at the same time keeping in mind the result will update the same conter for all (conter_B1 and conter_B2):
The code below follows the normal way of Matlab not parallel only for giving an example of multiple loops
N_M_O1=10;
N_M_O2=12;
N_M_O3=13;
conter_B1=0;
conter_B2=0;
x=[2 3 5 8 6 3 4 5 8 9];
y=[2 3 6 5 2 9 4 6 3 5];
x2=[2 8 5 8 6 3 6 5 6 9 10 12];
y2=[9 3 6 9 7 9 4 6 8 5 1 23];
x3=[2 3 1 8 6 3 55 5 6 9 2 3 5];
y3=[2 4 6 4 6 5 4 6 6 4 12 32 3];
for m=1:N_M_O1
z(m)=x(m)+y(m);
if z(m)>10
conter_B1=conter_B1+1;
else
conter_B2=conter_B2+1;
end
end
for m=1:N_M_O2
z2(m)=x2(m)+y2(m);
if z2(m)>10
conter_B1=conter_B1+1;
else
conter_B2=conter_B2+1;
end
end
for m=1:N_M_O3
z3(m)=x3(m)+y3(m);
if z3(m)>10
conter_B1=conter_B1+1;
else
conter_B2=conter_B2+1;
end
end
If I understand your question you only want:
zz = [x+y,x2+y2,x3+y3];
counter_B1 = sum(zz>10)
counter_B2 = sum(zz<=10)
Which will produce the same result as your 3 for loops.

matlab: dividing vector into overlapping chunks of fixed size

I've a vector that I would like to split into overlapping subvectors of size cs in shifts of sh. Imagine the input vector is:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
given a chunksize of 4 (cs=4) and shift of 2 (sh=2), the result should look like:
[1 2 3 4]
[3 4 5 6]
[5 6 7 8]
[7 8 9 10]
[9 10 11 12]
note that the input vector is not necessarily divisible by the chunksize and therefore some subvectors are discarded. Is there any fast way to compute that, without the need of using e.g. a for loop?
In a related post I found how to do that but when considering non-overlapping subvectors.
You can use the function bsxfun in the following manner:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
A = v(bsxfun(#plus,(1:cs),(0:sh:length(v)-cs)'));
Here is how it works. bsxfun applies some basic functions on 2 arrays and performs some repmat-like if the sizes of inputs do not fit. In this case, I generate the indexes of the first chunk, and add the offset of each chunck. As one input is a row-vector and the other is a column-vector, the result is a matrix. Finally, when indexing a vector with a matrix, the result is a matrix, that is precisely what you expect.
And it is a one-liner, (almost) always fun :).
Do you have the signal processing toolbox? Then the command is buffer. First look at the bare output:
buffer(v, 4, 2)
ans =
0 1 3 5 7 9 11
0 2 4 6 8 10 12
1 3 5 7 9 11 13
2 4 6 8 10 12 0
That's clearly the right idea, with only a little tuning necessary to give you exactly the output you want:
[y z] = buffer(v, 4, 2, 'nodelay');
y.'
ans =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
That said, consider leaving the vectors columnwise, as that better matches most use cases. For example, the mean of each window is just mean of the matrix, as columnwise is the default.
I suppose the simplest way is actually with a loop.
A vectorizes solution can be faster, but if the result is properly preallocated the loop should perform decently as well.
v = 1:13
cs = 4;
sh = 2;
myMat = NaN(floor((numel(v) - cs) / sh) + 1,cs);
count = 0;
for t = cs:sh:numel(v)
count = count+1;
myMat(count,:) = v(t-cs+1:t);
end
You can accomplish this with ndgrid:
>> v=1:13; cs=4; sh=2;
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1)
>> chunks = X+Y
chunks =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
The nice thing about the second syntax of the colon operator (j:i:k) is that you don't have to calculate k exactly (e.g. 1:2:6 gives [1 3 5]) if you plan to discard the extra entries, as in this problem. It automatically goes to j+m*i, where m = fix((k-j)/i);
Different test:
>> v=1:14; cs=5; sh=2; % or v=1:15 or v=1:16
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1); chunks = X+Y
chunks =
1 2 3 4 5
4 5 6 7 8
7 8 9 10 11
10 11 12 13 14
And a new row will form with v=1:17. Does this handle all cases as needed?
What about this? First I generate the starting-indices based on cs and sh for slicing the single vectors out of the full-length vector, then I delete all indices for which idx+cs would exceed the vector length and then I'm slicing out the single sub-vectors via arrayfun and afterwards converting them into a matrix:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
idx = 1:(cs-sh):length(v);
idx = idx(idx+cs-1 <= length(v))
A = arrayfun(#(i) v(i:(i+cs-1)), idx, 'UniformOutput', false);
cell2mat(A')
E.g. for cs=5; sh=3; this would give:
idx =
1 3 5 7
ans =
1 2 3 4 5
3 4 5 6 7
5 6 7 8 9
7 8 9 10 11
Depending on where the values cs; sh come from, you'd probably want to introduce a simple error-check so that cs > 0; as well as sh < cs. sh < 0 would be possible theoretically if you'd want to leave some values out in between.
EDIT: Fixed a very small bug, should be running for different combinations of sh and cs now.