concurrent for loop over 2 variables - matlab

Is it possible in Octave to made 2 loops in the same time like :
(for i=0:10 && j=10:20)
i;
j;
end

If the loops are of the same length, then yes. Not well known is that for non-vectors, a for loop, loops over columns. So just place your vectors in a matrix, one row per variable:
for r = [0:10; 10:20]
printf ("1st is %2i; 2nd is %2i\n", r(1), r(2));
endfor
which returns:
1st is 0; 2nd is 10
1st is 1; 2nd is 11
1st is 2; 2nd is 12
1st is 3; 2nd is 13
1st is 4; 2nd is 14
1st is 5; 2nd is 15
1st is 6; 2nd is 16
1st is 7; 2nd is 17
1st is 8; 2nd is 18
1st is 9; 2nd is 19
1st is 10; 2nd is 20

In Matlab you can use arrayfun with two input arrays of the same size:
>> arrayfun(#(x,y) x+y, 1:10, 10:10:100)
ans =
11 22 33 44 55 66 77 88 99 110

If you want them to move in step then use a counter variable to reference them as arrays:
j = 0:10;
i = 0:10;
for k = 1:11
i(k);
j(k);
end
But you most likely need to make nested for loops:
for i = 0:10
for j = 0:10
i;
j;
end
end

Related

How do I save the values from every iteration of a for-loop?

I have a for-loop, but every iteration overwrites the variable and I have only the final data left.
How can I save the other values from every iteration of the for-loop?
Here is the code I tried:
p = [1:1:20]';
for x = 0.1:0.1:1
q = x.*p
end
Here is the result I got:
q =
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
You can make q a two-dimensional matrix or a cell.
Two-dimensional matrix:
q=zeros(numel(p),10); %better to pre-allocate if you know the dimensions beforehand.
count=0;
for x=.1:.1:1
count=count+1;
q(:,count)=x.*p;
end
Cell:
q=cell(10); %better to pre-allocate if you know the dimensions beforehand.
count=0;
for x=.1:.1:1
count=count+1;
q{count}=x.*p;
end
Here is an alternative solution use bsxfun() It multiplies each x index with p' in just one line
p = [1:1:20]';
x = 0.1:0.1:1;
q = bsxfun(#times,x,p)

Tracking changes in a cell in Matlab

I have a cell with 3 different columns. The first is a simple ranking, the second is a code composed by X elements and the third is a code composed by Y elements that usually is the same for a certain combination of numbers in column two. So if in column two you have the number 345, it is likely that in column three you will always have 798. The thing is that sometimes it changes. So what I have, for instance, is:
1 453 4789
1 56 229
1 453 1246 %here the corresponding code has changed
2 43 31
2 453 1246 %here the code did not change
3 56 31 %here the corresponding code has changed (it was 229 previously)
What I want to have at the end is a new cell with three columns, only descriminating the cases in which a change in the code of the third column (correspondent to the code form the second column) was observed. For instance, in this simple example I would get:
1 453 1246
3 56 31
If you have your data in a matrix A you can use sorting:
[~, I] = sort(A(:,2));
B = A(I,:);
code_diff = logical(diff(B(:, 2)));
value_diff = logical(diff(B(:, 3)));
value_diff(code_diff) = false;
rows = sort(I([false; value_diff]));
ans = A(rows, :);
If the "codes" in the second column are all smallish integers, another possibility is to use a lookup table:
n = size(A, 1);
m = max(A(:, 2));
mask = false(n, 1);
lookup = inf(m, 1);
for i = 1:n
code = A(i,2);
if isinf(lookup(code))
lookup(code) = A(i,3);
elseif lookup(code) ~= A(i,3)
mask(i) = true;
lookup(code) = A(i,3);
end
end
ans = A(mask, :);
Assuming the values are in a matrix, this is a possible solution:
CJ2 = [1 453 4789
1 56 229
1 453 1246
2 43 31
2 453 1246
3 56 31];
changes = zeros(size(CJ2));
nChanges = 0;
for i = 2:size(CJ2,1)
pos = find(CJ2(1:i-1,2) == CJ2(i,2), 1, 'last');
if ~isempty(pos) && CJ2(pos,3) ~= CJ2(i,3)
nChanges = nChanges + 1;
changes(nChanges, :) = CJ2(i,:);
end
end
changes = changes(1:nChanges, :);
changes
Results:
>> changes
changes =
1 453 1246
3 56 31

overlapping feature values and efficient features calculation [duplicate]

If I have a matrix
F=[ 24 3 17 1;
28 31 19 1;
24 13 25 2;
47 43 39 1;
56 41 39 2];
in the first three columns I have feature values a forth column is for class labels. my problem is to get rid of same feature values when class label is different for that particular values.
like for F matrix I have to remove the rows 1,3,4 and 5 ,because for first column there are 2 different values in column four and same is for third column (39 and 39)as class label again got changed.
so output should look like
F=[28 31 19 1];
The straightforward approach would be iterating over the columns, counting the number of different classes for each value, and removing the rows for values associated to more than one class.
Example
F = [24 3 17 1; 28 31 19 1; 24 13 25 2; 47 43 39 1; 56 41 39 2];
%// Iterate over columns
for col = 1:size(F, 2) - 1
%// Count number of different classes for each value
[vals, k, idx] = unique(F(:, col));
count = arrayfun(#(x)length(unique(F(F(:, col) == x, end))), vals);
%// Remove values associated to more than one class
F(count(idx) > 1, :) = [];
end
This results in:
F =
28 31 19 1
Another take at the problem, without arrayfun (edited)
F = [24 3 17 1; 28 31 19 1; 24 13 25 2; 47 43 39 1; 56 41 39 2];
Separate both classes:
A1 = F(F(:,4)==1,1:3);
A2 = F(F(:,4)==2,1:3);
Replicate them to a 3D matrix to compare each line of class1 with each line of class2:
B2 = repmat(shiftdim(A2',-1),size(A1,1),1);
B1 = repmat(A1,[1,1,size(A2,1)]);
D4 = squeeze(sum(B1 == B2,2));
remove rows duplicated rows
A1(logical(sum(D4,2)),:) = [];
A2(logical(sum(D4,1)),:) = [];
reconstruct original matrix
R = [A1 ones(size(A1,1),1);A2 2*ones(size(A2,1),1)];

overlapping feature values values in matlab

If I have a matrix
F=[ 24 3 17 1;
28 31 19 1;
24 13 25 2;
47 43 39 1;
56 41 39 2];
in the first three columns I have feature values a forth column is for class labels. my problem is to get rid of same feature values when class label is different for that particular values.
like for F matrix I have to remove the rows 1,3,4 and 5 ,because for first column there are 2 different values in column four and same is for third column (39 and 39)as class label again got changed.
so output should look like
F=[28 31 19 1];
The straightforward approach would be iterating over the columns, counting the number of different classes for each value, and removing the rows for values associated to more than one class.
Example
F = [24 3 17 1; 28 31 19 1; 24 13 25 2; 47 43 39 1; 56 41 39 2];
%// Iterate over columns
for col = 1:size(F, 2) - 1
%// Count number of different classes for each value
[vals, k, idx] = unique(F(:, col));
count = arrayfun(#(x)length(unique(F(F(:, col) == x, end))), vals);
%// Remove values associated to more than one class
F(count(idx) > 1, :) = [];
end
This results in:
F =
28 31 19 1
Another take at the problem, without arrayfun (edited)
F = [24 3 17 1; 28 31 19 1; 24 13 25 2; 47 43 39 1; 56 41 39 2];
Separate both classes:
A1 = F(F(:,4)==1,1:3);
A2 = F(F(:,4)==2,1:3);
Replicate them to a 3D matrix to compare each line of class1 with each line of class2:
B2 = repmat(shiftdim(A2',-1),size(A1,1),1);
B1 = repmat(A1,[1,1,size(A2,1)]);
D4 = squeeze(sum(B1 == B2,2));
remove rows duplicated rows
A1(logical(sum(D4,2)),:) = [];
A2(logical(sum(D4,1)),:) = [];
reconstruct original matrix
R = [A1 ones(size(A1,1),1);A2 2*ones(size(A2,1),1)];

How to replace a block matrix with a new one?

I have an image size 128*128, I divided into 32*32 non-overlapping blocks, the problem is that I want to change the values of a specific or choosing block (the first or the 3rd.. for example) and getting a block with new values then replace it in my image. Do you have any idea how to get an image with ONE block modified ( NOT all of them)?
Thank you
This is an example with a small matrix
%*********************
A=magic(6) ; %%%%% matrix size 6*6
B=Block(A,2,2) ; % divide the matrix into 2*2 non-overlapping blocks
subblock=B{3} ; % Choose the 3rd block
new_block= 2*subblock; % change the block values by multipliying by 2
This is what I get
A = 35 1 6 26 19 24
3 32 7 21 23 25
31 9 2 22 27 20
8 28 33 17 10 15
30 5 34 12 14 16
4 36 29 13 18 11
I extract the 3rd block
sub_block=19 24
23 25
Now I multiplied by 2 :
new_block= 38 48
46 50
This is my Block function:
function A=Block(IM,p,q)
p=3;
q=3;
[m,n] = size(IM);
IJ = zeros(p,q);
z = 1;
for m1 = 1:m/p
for n1 = 1:n/q
if m1*p <= m;
if n1*q <= n;
for i = (m1-1)*p+1:m1*p
for j = (n1-1)*q+1:n1*q
IJ(i-(m1-1)*p,j-(n1-1)*q) = IM(i,j);
if (i-(m1-1)*p)==p&&(j-(n1-1)*q)==q;
OUT = IJ;
A{1,z} = OUT;
z = z+1;
end
end
end
end
end
end
end
I want to replace these values in matrix A , but depending on block number. How can I do it?
Just type in the rows and cols you want to access, for your example
A(1:2,5:6)=A(1:2,5:6)*2
more generic, where n is the nth column block and m is the mth row block and c is the block width and r is the block height (in your example, n = 3, m = 1, r=c=2)
A(((m-1)*r+1):(m*r), ((n-1)*c+1):(n*c)) = any block of size(r,c)
I don't know about your Block function, you don't actually need to convert to a cell matrix but if you do want to then I would do this:
A = magic(6);
[m,n] = size(A);
r=2; %// Desired number rows of blocks, m must be a multiple of r
c=2; %// Desired number cols of blocks, n must be a multiple of c
%// Create blocks (but as a 2D grid rather than a list)
B = mat2cell(A,r*ones(m/r,1), c*ones(n/c,1))
%// Manipulate a block
B(1,3) = {2*B{1,3}};
%// Convert back to a matrix
cell2mat(B)
I think that RobertStettler's answer is the better way to go though, if this is all you are trying to do