MATLAB bsxfun or vectorization - matlab

I have been working on vectorizing my code mostly using bsxfun, but I came across a scenario that I can't quite crack. Here is a small sample of problem. I would like to remove the for loops in this code, but I am having a hard time with the tempEA line.
Index = [2; 3; 4;];
dTime = [25; 26; 27; 28; 25; 26; 27; 28; 27; 28];
dIndex = [3; 3; 3; 2; 1; 3; 2; 4; 4; 2];
aTime = [30; 38; 34; 39; 30; 38; 34; 39; 34; 39];
aIndex = [4; 2; 5; 4; 5; 4; 4; 2; 2; 4];
EA = zeros(numel(Index));
for i = 1:numel(Index)
for j = 1:numel(Index)
tempEA = aTime(Index(i) == dIndex(:,1) & Index(j) == aIndex(:,1));
if i == j
elseif tempEA > 0
EA(i,j) = min(tempEA);
else
EA(i,j) = 50;
end
end
end
The answer should look like this:
EA =
0 50 34
38 0 30
34 50 0
Thanks for help in advance.

This uses bsxfun; no loops. It assumes you don't have NaN's among your aTimevalues.
N = numel(Index);
ii = bsxfun(#eq, dIndex.', Index); %'// selected values according to each i
jj = bsxfun(#eq, aIndex.', Index); %'// selected values according to each j
[ igrid jgrid ] = ndgrid(1:N); %// generate all combinations of i and j
match = double(ii(igrid(:),:) & jj(jgrid(:),:)); %// each row contains the matches for an (i,j) combination
match(~match) = NaN; %// these entries will not be considered when minimizing
result = min(bsxfun(#times, aTime, match.')); %'// minimize according to each row of "match"
result = reshape(result,[N N]);
result(isnan(result)) = 50; %// set NaN to 50
result(result<=0) = 50; %// set nonpositive values to 50
result(1:N+1:end) = 0; %// set diagonal to 0
The line result(result<=0) = 50; is only necessary if your aTime can contain nonpositive values. Can it? Or is your elseif tempEA > 0 just a way of checking that tempEA is not empty?

Related

Sum parts of a column separated by 0

Suppose that you have a matrix with:
0 0 0 .... 0
A 0 0 .... 0
B 0 0 .... 0
C 0 0 .... 0
0 0 0 .... 0
D 0 0 .... 0
E 0 0 .... 0
If I want to get a new array with the output:
[A+B+C D+E]
how would you do it? Of course I can always do loops and check for 0 but I'd like to know if there is any other alternative.
Use cumsum to generate a vector of grouping values, and then accumarray to do the sums:
x = [0; 1; 2; 4; 0; 7; 3];
result = accumarray(cumsum(x==0) + (x(1)~=0), x);
gives
result =
7
10
The + (x(1)~=0) part is necessary if x may not start with a zero. This part ensures that for
x = [1; 2; 4; 0; 7; 3];
the result is the desired
result =
7
10
With the above approach, each zero starts a new group. So, for
x = [0; 1; 2; 4; 0; 7; 3; 0; 0; 5; 0];
the result is
result =
7
10
0
5
0
If you want each run of one or more zeros to start a new group: first collapse consecutive zeros in x, then apply the above:
x = [0; 1; 2; 4; 0; 7; 3; 0; 0; 5; 0];
ind = [true; x(2:end)~=0 | x(1:end-1)~=0]; % index to remove a zero if preceded by zero
t = x(ind);
result = accumarray(cumsum(t==0) + (x(1)~=0), t);
gives
result =
7
10
5
0

Remove table rows based on condition in matlab

a=[1; 2 ; 3]; b=[ 4; 5; 6 ]; T=table(a,b).
I want to remove rows of table for which the value of b is less than or equal to 5 (b<=5).
You can use logical indexing:
a=[1; 2 ; 3];
b=[ 4; 5; 6 ];
T=table(a,b);
rowidx = (T.b <= 5);
T = T(~rowidx, :);
Which returns:
T =
1×2 table
a b
_ _
3 6
Fast, simple. elegant:
T(T.b <= 5,:) = [];
Another approach:
a = [1; 2; 3];
b = [4; 5; 6];
X = [a, b];
n = 1; m = 1;
while (n <= size(X, 1))
if(X(n, 2) > 5)
X_new(m, :) = X(n, :);
m = m + 1;
end
n = n + 1;
end
'X_new' will be the required matrix.

Moving rows from a matrix to a cell array using matlab: Trouble indexing cells

Using matlab, I am attempting to move rows from one matrix (RF) to a cell array using equivalent values in the matrix and the array. For each value i in the first column of matrix RF I would like to find which cell contains the same value. I would then like to move the row containing i (i,:) to the first row of zeros in that cell.
At the end I will delete all remaining rows of zeros in M.
I currently have the following code:
RF = [1 7; 4 8; 3 9; 7 10]
M = cell(3,1);
for k = 1:3
M{k} = zeros(10,2);
end
matsize2 = length((RF(:)));
halfmatsize2 = 0.5 * matsize2;
for i = 1:halfmatsize2 % Values in the first column of RF
J = RF(i);
JK = RF(i,:);
L = find(cell2mat(M)==J); % I wanted this line to give me the index of the cell containing J
H = find(M{L}==0, 1, 'first'); % This returns an error
M{L}(H,:)= JK; % Puts JK into the first row of zeros (my goal)
end
This outputs the error "index exceeds matrix dimensions" for the line H = find(M{L}==0, 1, 'first'); This is because while I wanted L to return the index of the cell containing J, it is giving me the location with all cells combined into one. What's the best way to find the cell containing J and then move JK to the first row of zeros in the aforementioned cell?
For example, I have the matrix RF = [1 7; 4 8; 3 9; 7 10] and the cell array M = cell(3,1), where M{1}=[1 4; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0], M{2} = [2 5; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0] and M{3} = [3 6; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0; 0 0].
I would like to end with M{1} = [1 4; 1 7; 4 8; 7 10], M{2} = [2 5] and M{3} = [3 6; 3 9].`
The overarching goal here is to automate the process for taking a matrix containing parent-offspring relationships for species and turn it into a phylogeny. The example provided is the simple one I've been using to test other aspects of the larger code.
Help would be much appreciated! After hours of Google searching and trial/error I remain stuck. I would also appreciate advice on how to streamline my rather clumsy code.
Thanks in advance!
Based on what I have understood, I think this would work for you and should be more efficient too -
%// Get matches between each element of col1 of RF against each in its col2
RF12 = bsxfun(#eq,RF(:,1),RF(:,2)'); %//'
%// Cut each cell of M into cells that have only non-zero rows
M_cut = arrayfun(#(n) M{n}(any(M{n},2),:),1:numel(M),'Uni',0)
M_out = cell(size(M)); %// storage for output
for n = 1:numel(M) %// we need to iterate through each cell
%// Matches for all elements in col1 of RF against all elements in M
M_RF1 = any(bsxfun(#eq,M{n}(:),RF(:,1)')); %//'
%// Matching row indices for all elements in col1 of RF against all
%// matches in its col2 and all elements in M
idx = any(bsxfun(#and,RF12,M_RF1),2) | M_RF1(:); %//'
%// Logically index into RF for the matches and vertically concatenate
%// with the M_cut cells to give us the desired output in each cell
M_out{n} = [M_cut{n} ; RF(idx,:)];
end
celldisp(M_out) %// display output
Output -
M_out{1} =
1 4
1 7
4 8
7 10
M_out{2} =
2 5
M_out{3} =
3 6
3 9

Matlab - array of matrices

I have two matrices A1 and A2, for example A1 = [1 0; 1 1]; and A2 = [0 1; 1 1];
Now I don't want to have them called A1 and A2 since I will have An matrices.
So I wanted something like
A(1) = [1 0; 1 1];
A(2) = [0 1; 1 1];
..
A(n) = [...];
But Matlab does not allow me to do this.
I know one can use A(:,:,1) = [ ... ] but this is ugly and makes me type :,:, all the time... so I want to know if there is a different solution.
I tried A.1 but structs field names need to be strings.
Use cell array's:
A = cell(N, 1);
A{1} = [ 1 0; 1 1 ];
A{2} = [ 0 1; 1 1 ];
You can use an array of structs.
A(1).mat = [1 0; 1 1];
A(2).mat = [0 0; 1 1];
...
A(n)...
or a cell array
A{1} = [1 0; 1 1];
A{2} = [0 1; 1 1];
...
A{n}...

MATLAB neural networks

I'm using a simple XOR input and output data set in order to train a neural network before attempting anything harder but for some reason it won't work.
may someone please explain what I am doing wrong please?
This is my code:
%user specified values
hidden_neurons = 3;
epochs = 10000;
t_input = [1 1; 1 0; 0 1; 0 0];
t_output = [1; 0; 0; 1];
te_input = [1 1; 1 0; 0 1; 0 0];
net = newff(t_input, t_output, 1);
net = init(net);
net = train(net, t_input, t_output);
net.trainParam.show = 50;
net.trainParam.lr = 0.25;
net.trainParam.epochs = epochs;
net.trainParam.goal = 1e-5;
net = train(net, t_input, t_output);
out = sim(net, te_input);
THis is my error message:
??? Error using ==> network.train at 145 Targets are incorrectly sized for
network. Matrix must have 2 columns.
Error in ==> smallNN at 11 net =
train(net, t_input, t_output);
You must have your samples on columns and not rows (like all the NN software in the world do), so change the data sets creation lines in:
t_input = [1 1; 1 0; 0 1; 0 0]';
t_output = [1; 0; 0; 1]';
te_input = [1 1; 1 0; 0 1; 0 0]';
Now it works.