Number of combinations in Matlab is missing - matlab

I am creating a list of combinations of 3 coefficients. The sum is 1 and the increment for each coefficient is 0.05:
s=0;
for x1 = 0 : 0.05 : 1
for x2 = 0 : 0.05 : (1-x1)
x3 = 1-x1-x2;
s=s+1;
fprintf('%0.2f %0.2f %0.2f \n',x1,x2,x3)
end
end
The number expected is 231 but I got 229.
Checking the result:
...
0.85 0.00 0.15
0.85 0.05 0.10
0.85 0.10 0.05
0.90 0.00 0.10
0.90 0.05 0.05
0.90 0.10 -0.00
0.95 0.00 0.05
1.00 0.00 0.00
I found '0.85 0.15 0.00' and '0.95 0.05 0.00' were missing but I can't explain why. Could anyone give me some hint about this. Much appreciate for your time.

You’re asking for hints, so I’ll give you some.
Read this Q&A: Why is 24.0000 not equal to 24.0000 in MATLAB?. Now think about what the upper limit for x2 (1-x1) exactly is and how you get there by incrementing 0 in steps of 0.05.

Related

vectorise foor loop with a variable that is incremented in each iteration

I am trying to optimise the running time of my code by getting rid of some for loops. However, I have a variable that is incremented in each iteration in which sometimes the index is repeated. I provide here a minimal example:
a = [1 4 2 2 1 3 4 2 3 1]
b = [0.5 0.2 0.3 0.4 0.1 0.05 0.7 0.3 0.55 0.8]
c = [3 5 7 9]
for i = 1:10
c(a(i)) = c(a(i)) + b(i)
end
Ideally, I would like to compute it by writting:
c(a) = c(a) + b
but obviously it would not give me the same results since I have to recalculate the value for the same index several times so this way to vectorise it would not work.
Also, I am working in Matlab or Octave in case that this is important.
Thank you very much for any help, I am not sure that it is possible to be vectorise.
Edit: thank you very much for your answers so far. I have discovered accumarray, which I did not know before and also understood why changing the for loop between Matlab and Octave was giving me such different times. I also understood my problem better. I gave a too simple example which I thought I could extend, however, what if b was a matrix?
(Let's forget about c at the moment):
a = [1 4 2 2 1 3 4 2 3 1]
b =[0.69 -0.41 -0.13 -0.13 -0.42 -0.14 -0.23 -0.17 0.22 -0.24;
0.34 -0.39 -0.36 0.68 -0.66 -0.19 -0.58 0.78 -0.23 0.25;
-0.68 -0.54 0.76 -0.58 0.24 -0.23 -0.44 0.09 0.69 -0.41;
0.11 -0.14 0.32 0.65 0.26 0.82 0.32 0.29 -0.21 -0.13;
-0.94 -0.15 -0.41 -0.56 0.15 0.09 0.38 0.58 0.72 0.45;
0.22 -0.59 -0.11 -0.17 0.52 0.13 -0.51 0.28 0.15 0.19;
0.18 -0.15 0.38 -0.29 -0.87 0.14 -0.13 0.23 -0.92 -0.21;
0.79 -0.35 0.45 -0.28 -0.13 0.95 -0.45 0.35 -0.25 -0.61;
-0.42 0.76 0.15 0.99 -0.84 -0.03 0.27 0.09 0.57 0.64;
0.59 0.82 -0.39 0.13 -0.15 -0.71 -0.84 -0.43 0.93 -0.74]
I understood now that what I would be doing is rowSum per group, and given that I am using Octave I cannot use "splitapply". I tried to generalise your answers, but accumarray would not work for matrices and also I could not generalise #rahnema1 solution. The desired output would be:
[0.34 0.26 -0.93 -0.56 -0.42 -0.76 -0.69 -0.02 1.87 -0.53;
0.22 -1.03 1.53 -0.21 0.37 1.54 -0.57 0.73 0.23 -1.15;
-0.20 0.17 0.04 0.82 -0.32 0.10 -0.24 0.37 0.72 0.83;
0.52 -0.54 0.02 0.39 -1.53 -0.05 -0.71 1.01 -1.15 0.04]
that is "equivalent" to
[sum(b([1 5 10],:))
sum(b([3 4 8],:))
sum(b([6 9],:))
sum(b([2 7],:))]
Thank you very much, If you think I should include this in another question instead of adding the edit I will do so.
Original question
It can be done with accumarray:
a = [1 4 2 2 1 3 4 2 3 1];
b = [0.5 0.2 0.3 0.4 0.1 0.05 0.7 0.3 0.55 0.8];
c = [3 5 7 9];
c(:) = c(:) + accumarray(a(:), b(:));
This sums the values from b in groups defined by a, and adds that to the original c.
Edited question
If b is a matrix, you can use
full(sparse(repmat(a, 1, size(b,1)), repelem(1:size(b,2), size(b,1)), b))
or
accumarray([repmat(a, 1, size(b,1)).' repelem(1:size(b,2), size(b,1)).'], b(:))
Matrix multiplication and implicit expansion and can be used (Octave):
nc = numel(c);
c += b * (1:nc == a.');
For input of large size it may be more memory efficient to use sparse matrix:
nc = numel(c);
nb = numel(b);
c += b * sparse(1:nb, a, 1, nb, nc);
Edit: When b is a matrix you can extend this solution as:
nc = numel(c);
na = numel(a);
out = sparse(a, 1:na, 1, nc, na) * b;

Matrix columns correlations, excluding self-correlation, Matlab

I have a couple of matrices (1800 x 27) that represent subjects and their recordings (3 minutes equivalent for each of 27 subjects). Each column represents a subject.
I need to do intercorrelation between subjects, let's say to correlate F to G, G to H, and H to F for all 27 subjects.
I use CORR command corr(B) where B is a matrix and it returns the next example:
1 0.07 -0.05 0.10 0.04 0.12
0.07 1 -0.02 -0.08 0.17 0.03
-0.05 -0.02 1 0.04 0.16 0.13
0.10 -0.08 0.04 1 -0.04 0.34
0.04 0.18 0.16 -0.04 1 0.13
How can I adjust the code to exclude self-correlation (eg F to F) so I won't get "1" numerals?
(it's present in each row/column)
I have to perform some transformations afterwards, like Fisher Z-Transformation, which returns inf for each "1", and as result, I can't use further calculations.

sum specific columns in matlab vectorized

I have a big matrix lets say 100000x13.
I need to sum specific columns of this matrix.
For example:
matrix = [0.70 0.30 0 0 0.15 0.21 0.58 0.06 0.00 1.00 0 0 1.00;
0.70 0.00 0 0 0.00 0.00 0.07 0.06 0.00 0.80 0 0 1.00;
0.70 0.00 0 0 0.00 0.00 0.58 0.06 0.00 1.00 0 0 0.94];
inputVect = [4 4 3 2];
idx2 = cumsum(inputVect);
idx1 = [1 idx2(1:end-1)+1];
result = (1-sum(matrix(:,idx1(1):idx2(1)),2)) + (1-sum(matrix(:,idx1(2):idx2(2)),2))+(1-sum(matrix(:,idx1(3):idx2(3)),2)) + (1-sum(matrix(:,idx1(4):idx2(4)),2));
The thing is inputVect needs to be a function argument that I don't allways know the size. And because of the size of the matrix I should also avoid for loops. Any help would be much appreciated.

Extracting lower Triangular matrix without considering diagonal element

I have a 5x5 matrix
A =
[0 0 0 0 1;
0.36 0 0 0 1;
0 0.25 0 0 1;
0.35 0 0 0 1;
0 0 0.28 0 1];
I want to extract lower triangular elements of the matrix without considering the diagonal elements. Therefore, resulting matrix should be
C = [0.36 0 0.35 0 0.25 0 0 0 0.28 0]
Let me know how I can get this.
You can use matlab tril, e.g.:
index = find(tril(ones(size(A)), -1));
C = A(index);
I'm assuming this is Matlab, based on the format of the matrices.
If you want the elements of the lower triangular portion in a row vector, you can do it with a loop (although I'm sure somebody will have a nifty vectorized approach):
C=[];
for n=1:size(A,1)
C=[C,A(n+1:end,n)'];
end
The output is:
C =
0.36 0.00 0.35 0.00 0.25 0.00 0.00 0.00 0.28 0.00
If instead you want the full 5x5 matrix, you would use the second argument of tril:
C = tril(A,-1);
The output is:
C =
0.00 0.00 0.00 0.00 0.00
0.36 0.00 0.00 0.00 0.00
0.00 0.25 0.00 0.00 0.00
0.35 0.00 0.00 0.00 0.00
0.00 0.00 0.28 0.00 0.00
bsxfun-based approach:
C = A( bsxfun(#gt, (1:size(A,1)).', 1:size(A,2)) ).';

Show only predefined value in axes MATLAB

I would like to only show these x-values on the x-axes
xx=[0.0005 0.005 0.05 0.1 0.25 0.5 0.75 1 1.25 1.5];
Is it possible?
You can modify axis labels using XtTickLabel property. For example:
set(gca,'XTickLabel',[0.0005 0.005 0.05 0.1 0.25 0.5 0.75 1 1.25 1.5])
This will change only labels, not actual values on the plot. To check values as well you can use:
set(gca,'XTick',[0.0005 0.005 0.05 0.1 0.25 0.5 0.75 1 1.25 1.5]);
set(gca,'XScale','log'); % Your xx values seem to be logarithmic, so this can help.