convert For syntax to a faster way in Matlab - matlab

I have below code and I want to convert it to a faster way but I don't how I can convert For syntax to a faster way in Matlab.
If user count is 5 and item count is 2 and time count is 4, I want to create this matrix:
1 1 1
1 1 2
1 1 3
1 1 4
1 2 1
1 2 2
1 2 3
1 2 4
2 1 1
2 1 2
2 1 3
2 1 4
...
result=zeros(userCount*itemCount*timeCount,4);
j=0;
for i=1:userCount
result(j*itemCount*timeCount+1:j*itemCount*timeCount+itemCount*timeCount,1)=ones(itemCount*timeCount,1)*i;
j=j+1;
end
j=0;
h=1;
for i=1:userCount*itemCount
result(j*timeCount+1:j*timeCount+timeCount,2)=ones(timeCount,1)*(h);
j=j+1;
h=h+1;
if h>itemCount
h=1;
end
end
j=0;
for i=1:userCount*itemCount
result(j*timeCount+1:j*timeCount+timeCount,3)=1:timeCount;
j=j+1;
end
for i=1:size(subs,1)
f=(result(:,1)==subs(i,1)& result(:,2)==subs(i,2));
result(f,:)=[];
end

What you are describing is to enumerate permutations for three independent linear sets. One way to achieve this would be to use ndgrid and unroll each output into a single vector:
userCount = 5; itemCount = 2; timeCount = 4;
[X,Y,Z] = ndgrid(1:timeCount,1:itemCount,1:userCount);
result = [Z(:) Y(:) X(:)];
We get:
result =
1 1 1
1 1 2
1 1 3
1 1 4
1 2 1
1 2 2
1 2 3
1 2 4
2 1 1
2 1 2
2 1 3
2 1 4
2 2 1
2 2 2
2 2 3
2 2 4
3 1 1
3 1 2
3 1 3
3 1 4
3 2 1
3 2 2
3 2 3
3 2 4
4 1 1
4 1 2
4 1 3
4 1 4
4 2 1
4 2 2
4 2 3
4 2 4
5 1 1
5 1 2
5 1 3
5 1 4
5 2 1
5 2 2
5 2 3
5 2 4

Related

Matlab decision tree

I am trying to make a decision tree but the outcome is strange and I can't figure out where is wrong. There are seven variables, each of which I use 1 or 2 to represent their meaning, for example, for variable 1 the number 1 is warm and 2 is cold, for variable 2 the number 1 is yes and 2 is no.
vars = {'TEMP' 'SKIN' 'BIRTH' 'AQUATIC' 'AERIAL' 'LEGS' 'HIBER'};
x = [1 1 1 2 2 1 2
2 2 2 2 2 2 1
2 2 2 1 2 2 2
1 1 1 1 2 2 2
2 1 2 1 2 1 1
2 2 2 2 2 1 2
1 1 1 2 1 1 1
1 1 2 2 1 1 2
1 1 1 2 2 1 2
2 2 1 1 2 2 2
2 2 2 1 2 1 2
1 1 2 1 2 1 2
1 1 1 2 2 1 1
2 2 2 1 2 2 2
2 1 2 1 2 1 1];
s = {'M';'R';'F';'M';'A';'R';'M';'B';'M';'F';'R';'B';'M';'F';'A'};
y = cellstr(s);
t = classregtree(x, y, 'method','classification', 'names',vars,...
'categorical',[1 7], 'prune','off');
view(t)
The outcome is only one step tree without other information. What is wrong with this?
I'm not an expert of decision trees, anyway, playing a little bit with the parameters of classregtree (minparent, to be exact):
vars = {'TEMP' 'SKIN' 'BIRTH' 'AQUATIC' 'AERIAL' 'LEGS' 'HIBER'};
x = [1 1 1 2 2 1 2
2 2 2 2 2 2 1
2 2 2 1 2 2 2
1 1 1 1 2 2 2
2 1 2 1 2 1 1
2 2 2 2 2 1 2
1 1 1 2 1 1 1
1 1 2 2 1 1 2
1 1 1 2 2 1 2
2 2 1 1 2 2 2
2 2 2 1 2 1 2
1 1 2 1 2 1 2
1 1 1 2 2 1 1
2 2 2 1 2 2 2
2 1 2 1 2 1 1];
y = {'M';'R';'F';'M';'A';'R';'M';'B';'M';'F';'R';'B';'M';'F';'A'};
t = classregtree(x,y,'method','classification','Names',vars, ...
'categorical',[1 7],'prune','off','minparent',1);
view(t);
I've been able to reproduce something that looks fine. Anyway, since Matlab release 2011A, classregtree has become obsolete and has been superseded by fitrtree (RegressionTree) and fitctree (ClassificationTree) functions (classregtree is being kept for retrocompatibility reasons only). I recommend you to update your code and use those functions instead:
t = fitctree(x,y,'PredictorNames',vars, ...
'CategoricalPredictors',{'TEMP' 'HIBER'},'Prune','off','MinParentSize',1);

Iterate one vector through another in Matlab Part 2

This is a similar request to my post at Iterate one vector through another in Matlab
I am using Luis' suggestion with the following code:
E=[1 2 3 4 5 6 7 8 9 10];
A = [1 2];
s = size(E,2);
t = numel(A);
C = cell(1,s);
[C{:}] = ndgrid(A);
C = cat(s+1, C{:});
C = fliplr(reshape(C, t^s, s));
This produces a good result for C as a 1024x10 matrix with all possible permutations of 1 and 2 to a length of 10 columns. What I want to do is remove any rows that are not in increasing order. For example now I get:
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 1
1 1 1 1 1 1 1 1 2 2
All are valid except for the third row since it goes from 2 to back to 1.
I have code to get the desired result, but it is very slow and inefficient.
E=[1 2 3 4 5 6 7 8 9 10];
A = [1 2];
s = size(E,2);
t = numel(A);
C = cell(1,s);
[C{:}] = ndgrid(A);
C = cat(s+1, C{:});
C = fliplr(reshape(C, t^s, s));
min=0;
for row=1:size(C,1)
for col=1:size(C,2)
if(C(row,col)>min)
min=C(row,col);
elseif(C(row,col)<min)
C(row,:)=0;
continue;
end
end
min=0;
end
C = C(any(C,2),:); %remove all zero rows
The desired output is now:
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 2
1 1 1 1 1 1 1 2 2 2
1 1 1 1 1 1 2 2 2 2
1 1 1 1 1 2 2 2 2 2
1 1 1 1 2 2 2 2 2 2
1 1 1 2 2 2 2 2 2 2
1 1 2 2 2 2 2 2 2 2
1 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
Any ideas on how to optimize my code so I do not need to use nested loops?
The super-simple but not-quite-so-obvious solution via a couple of row-wise operations:
d = diff(C, [], 2);
m = min(d, [], 2);
C = C(m>=0, :);
Of course, in this particular example it would be far easier to just generate the resulting matrix directly:
C = flipud(triu(ones(s+1,s).*(max(A)-min(A))) + min(A));
but I assume you're also interested in less trivial values of A ;)

MATLAB: How do you add all the first n rows of a matrix within the same column, and save the result to the last row?

It was hard to phrase the question, but here's an example of what I'm looking for:
1 2 3 4
2 1 1 1
2 2 3 1
0 0 0 0
and in column one, I add all the value of all of the first three rows and save it to the third and so on, so that it becomes:
1 2 3 4
2 1 1 1
2 2 3 1
5 5 7 6
I think you can use sum:
octave:23> m = [1 2 3 4; 2 1 1 1; 2 2 3 1; 0 0 0 0]
m =
1 2 3 4
2 1 1 1
2 2 3 1
0 0 0 0
octave:24> m(length(m), :) = sum(m)
m =
1 2 3 4
2 1 1 1
2 2 3 1
5 5 7 6

Sorting and randomising a matrix according to a particular constraint

I have a 32 x 3 matrix as follows:
A =
[ 1 1 1;
1 1 2;
1 1 3;
1 1 4;
1 1 5;
1 1 6;
1 1 7;
1 1 8;
1 2 1;
1 2 2;
1 2 3;
1 2 4;
1 2 5;
1 2 6;
1 2 7;
1 2 8;
2 1 1;
2 1 2;
2 1 3;
2 1 4;
2 1 5;
2 1 6;
2 1 7;
2 1 8;
2 2 1;
2 2 2;
2 2 3;
2 2 4;
2 2 5;
2 2 6;
2 2 7;
2 2 8]
What I need to do is randomise the order of the rows, while keeping the row values together, however, this needs to be constrained such that for A(:, 4), every 8 rows contain only the numbers 1 - 8. So for example, you could have something like:
A(1:8, :) =
[ 1 2 4;
1 1 5;
2 1 6;
1 1 8;
2 2 1;
2 1 2;
2 1 7;
1 1 3]
The occurrence of 1 and 2 in the first two columns needs to be random, 1 - 8 needs to be randomised for every 8 values of the third column. Initially I tried to use the function randswap within a loop with an added constraint, but this has only led to an infinite loop. Also important that the rows stay together as the 1s and 2s in the first two columns need to appear alongside the last column an equal number of times. Someone suggested the following, but it doesn't quite work out..
m = size(A,1);
n = 1:8;
out = 1;
i2 = 1;
while ~all(ismember(1:8,out)) && i2 < 100
i1 = randperm(m);
out = A(i1(n),:);
i2 = i2 + 1;
end
If all you need is to get one set of 8 rows out of A, you can construct the result like this:
out = [randi([1,2],[8,2]),randperm(8)']
out =
2 1 5
2 1 2
2 1 1
1 2 7
2 2 6
1 1 8
2 2 3
1 1 4
If you need to randomize all of A, you can do the following:
%# calculate index for the 1's and 2's
r = rand(8,4);
[~,idx12] = sort(r,2);
%# calculate index for the 1's through 8's
[~,idx8] = sort(r,1);
%# use idx8 to shuffle idx12
idx8into12 = bsxfun(#plus,idx8,[0 8 16 24]);
%# now we can construct the output matrix
B = [1 1;1 2;2 1;2 2];
out = [B(idx12(idx8into12),:),idx8(:)];
out =
1 1 7
1 2 3
1 2 1
2 1 8
2 1 5
2 2 4
2 2 2
2 1 6
1 1 3
1 2 7
1 1 1
1 2 8
1 2 4
1 1 5
2 2 6
2 1 2
1 1 8
2 1 7
1 2 5
2 1 1
1 2 6
2 1 3
1 1 2
1 1 4
2 1 4
2 2 7
2 2 8
2 2 3
1 2 2
1 1 6
2 2 5
2 2 1
If you do unique(out,'rows'), you'll see that there are indeed 32 unique rows. Every 8 rows in out have the numbers 1 through 8 in the third column.

Is it possible to delete elements from matlab matrix?

I have a matlab matrix in the form
A = [1 2 3 4 5 6; 1 1 2 2 3 3; 1 2 3 3 2 1]
Is it possible to delete the 4th, 5th and 6th columns of the matrix A so that the result would be:
A = [1 2 3; 1 1 2; 1 2 3]
This would do it:
A(:,4:6)=[];
octave-3.4.0:1> A = [1 2 3 4 5 6; 1 1 2 2 3 3; 1 2 3 3 2 1]
A =
1 2 3 4 5 6
1 1 2 2 3 3
1 2 3 3 2 1
octave-3.4.0:2> A = A(:,1:3)
A =
1 2 3
1 1 2
1 2 3