How to obtain certain size for a matrix - matlab

I am running a calculation and I want to achieve the result as NOJ(7x65) matrix
NOJ = zeros(7,65);
for x = 2:2:14
NOJ(x,:) = (1- sqrt(1-inflow_CT))./(1+(2*kNOJfit*x/2)).^2;
end
this is my code it works fine but it gives me 14 points (NOJ 14x65). I only want 7 points for x=2,4,6,8,10,12,14.
Resulting matrix
Does anyone know what is the reason for that?

The reason for that is: matrix size is being increased in the for loop.
For example:
abc=zeros(1,1); size(abc)
ans =
1 1
abc(2,1)=4; size(abc)
ans =
2 1

Related

How to create an Octave function that evaluate the sum of pairs of numbers in the vector?

It's like a reverse version of Pascal's triangle.
I want to create a vector-input function named
y = lastnum(vect) on Octave, that evaluate the sum of each pair of numbers in any vectors to output the single number from the evaluation loops like this
0 1 2 3 4
1 3 5 7
4 8 12
12 20
32
And the input and output would be like this,
lastnum([0 1 2 3 4])
ans = 32
I mean... is there any progresses that I can do??? You may not understand but, the reverse triangle above can guide you about my question.
I also tagged MATLAB since it has similar language. MATLAB pros may help my problem.
Notice that the number of times each element gets added to produce the final result comes from Pascals triangle itself, so, e.g., for the vector [a b c d] the result will be a+3b+3c+d. So create a vector of entries in Pascals triangle and multiply and add with the original vector v.
I only have access to Matlab, Octave may not have all these functions.
This is a one-liner diag(fliplr(pascal(numel(v)))).'*v(:).
Or a looping version
s = 0;
for i = 0:numel(v)-1
s = s+nchoosek(numel(v)-1,i)*v(i+1);
end
s
Simplest thing I can think of is:
while length(x) > 0
disp(x)
x = x(1:end-1) + x(2:end);
end
or did I misunderstand the question?
Here is the version for both MATLAB and Octave:
function y = lastnum(v)
while 1
if length(v) == 2
y = sum(v)
break;
end
# disp(v); # if you want to print the progress
vt = [];
for k = 1:(length(v)-1)
vt(end+1) = sum(v(k:(k+1)));
end
v = vt;
end
end

Average matrices in a cell array within a structure Matlab

In Matlab I have a structure AVG of size 1 x 6 which has one field averageNEST that is a cell array also of size 1 x 6.
Each averageNEST contains matrices of varying sizes (in one dimension), so for example
AVG(1).averageNEST{1,1} is of size 281 x 3 x 19 and
AVG(1).averageNEST{1,2} is of size 231 x 3 x 19
The 2nd and 3rd dimensions of the matrices are always 3 and 19, it is only the first dimension that can change.
I want to average over all the matrices contained within AVG(1).averageNEST and obtain one matrix of size X x 3 x 19 where X is the size of the smallest matrix in AVG(1).averageNEST.
Then I want to do this for all 6 averageNEST in AVG - so have a separate averaged matrix for AVG(1), AVG(2) ... AVG(6).
I have tried multiple things including trying to concatenate matrices using the following code:
for i=1:6
min_epoch = epoch + 1;
for ii=1:19
averageNEST(:,:,ii) = [AVG(i).averageNEST(1:min_epoch,:,ii)];
end
end
and then average this but it doesn't work and now I'm really confused about what I'm doing!
Can anyone help?
I am not sure if I understand what you want to do. If you want to keep only the elements up to the size of the the smallest matrix and then average those matrices you can do the following:
averageNEST = cell(size(AVG));
for iAVG = 1:numel(AVG)
nests = AVG(iAVG).averageNEST;
minsize = min(cellfun(#(x) size(x,1), nests));
reducednests = cellfun(#(y) y(1:minsize, :, :), nests, 'UniformOutput', false);
averageNEST{iAVG} = sum(cat(4, reducednests{:}), 4) / numel(nests);
end

How to multiply matrix having different size (without knowing exactly the size they will have)?

I have to multiply 2 matrices (scalar multiplication) that have different sizes. For instance, the 1st has size n-by-m and the 2nd n+1-by-m+1. The fact is that it is not always the case. I mean, sometimes the first has size n+1-by-m+1 and the 2nd n-by-m or n+2-by-m+2 etc...
Example:
a = [ 1 2 3;
4 5 6];
b = [ 1 2 3;
4 5 6;
7 8 9]
I would like Matlab to check the size of each matrix, then multiply them using the smallest size available between the 2 i.e. ignoring the last rows and columns of the bigger matrix (or similarly, adding rows and columns of 0 to the smaller matrix).
With the example inputs I would like to obtain:
c = [1 4 9;
16 25 36]
or
c = [1 4 9;
16 25 36;
0 0 0]
How can I write this?
Find the number of rows and columns of your final matrix:
n = min(size(a,1), size(b,1));
m = min(size(a,2), size(b,2));
Then extract only the relevant sections of a and b (using the : operator) for your multiplication:
c = a(1:n,1:m).*b(1:n,1:m)
If you only consider dot product, it means that size(a) must equal size(b), which allows to simply restrain the size of b, you can use a simple if statement if you like. For example:
if all(size(b) == size(a))
answer = a.*b
else
minsize(:,1) = min(size(a,1),size(b,1));
minsize(:,2) = min(size(a,2),size(b,2));
answer = a(1:minsize(:,1),1:minsize(:,2)).*a(1:minsize(:,1),1:minsize(:,2));
end
I don't think this is easiest way to do it, but it is simple to understand :)
I am not always sure which one of the matrix is bigger, then I thought to use:
if size (a) > size (b)
a = a(1:size(b,1),1:size(b,2));
elseif size (a) < size (b)
b = b (1: size (a,1),1:size(a,2));
end
It seems to work like this.

Why does a column vector return a row vector when used to index matrices?

Imagine the following matrix is defined in MATLAB:
>> matrix=10:18
matrix =
10 11 12 13 14 15 16 17 18
Now I want to use another matrix to index the first one
>> index=[1,2;3,4]
index =
1 2
3 4
>> matrix(index)
ans =
10 11
12 13
So far so good, the size of the answer matches that of the matrix 'index'. If I use a row vector as the indexing matrix, the output is a row vector too. But the problem appears when I use a column vector as the indexing matrix:
>> index=(1:3)'
index =
1
2
3
>> matrix(index)
ans =
10 11 12
As you can see, here the size of the answer does not agree with the size of the matrix 'index'. This inconsistency in the sizes of the indexing matrix and the ans matrix prevents me from writing a piece of code accepting an indexing matrix of an arbitrary size.
I wonder if someone else has come across this problem before and has found some sort of solution to it; in other words, how can I force MATLAB to give me an ans matrix of the same size as the arbitrarily sized indexing matrix?
Cheers
Solution
#Dev-iL has nicely explained here why this is the way Matlab behaves, and #Dan has presented a general solution here. However, there was a simpler ad-hoc workaround for my code which I've explained here.
The reason comes from the function subsref.m, which is called when using parentheses:
%SUBSREF Subscripted reference.
% A(I) is an array formed from the elements of A specified by the
% subscript vector I. The resulting array is the same size as I except
% for the special case where A and I are both vectors. In this case,
% A(I) has the same number of elements as I but has the orientation of A.
As you can see, in the special case of vectors, the shape of the result will be the same as that of matrix in your example.
As for a workaround, IMHO Dan has the cleanest solution.
Preallocate the output matrix with the size of index matrix.
Then assign corresponding indices the corresponding values
out = zeros(size(index));
out(index) = matrix(index);
Example
index = (1:3)'
index =
1
2
3
>> out = zeros(size(index))
out =
0
0
0
>> in = magic(3)
in =
8 1 6
3 5 7
4 9 2
>> out(index) = in(index)
out =
8
3
4
>>
Dev-iL has explained why it is like that. Here is a potential workaround:
reshape(matrix(index),size(index))

vectorized array creation from a list of start/end indices

I have a two-column matrix M that contains the start/end indices of a bunch of intervals:
startInd EndInd
1 3
6 10
12 12
15 16
How can I generate a vector of all the interval indices:
v = [1 2 3 6 7 8 9 10 12 15 16];
I'm doing the above using loops, but I'm wondering if there's a more elegant vectorized solution?
v = [];
for i=1:size(M,1)
v = [v M(i,1):M(i,2)];
end
Here's a vectorized solution I like to use for this particular problem, using the function cumsum:
v = zeros(1, max(endInd)+1); % An array of zeroes
v(startInd) = 1; % Place 1 at the starts of the intervals
v(endInd+1) = v(endInd+1)-1; % Add -1 one index after the ends of the intervals
v = find(cumsum(v)); % Perform a cumulative sum and find the nonzero entries
cell2mat(arrayfun(#colon,M(:,1)',M(:,2)','UniformOutput',false))
I don't have IMFILL, but on my machine this method is faster than the other suggestions and I think would beat the IMFILL method due to the use of find.
It can be made even faster if M is set up transposed (and we adjust the third and fourth arguments of arrayfun).
There's probably an even better solution I'm somehow not seeing, but here's a version using IMFILL
startInd = [1,6,12,15];
endInd = [3,10,12,16];
%# create a logical vector with starts and ends set to true to prepare for imfill
tf = false(endInd(end),1);
tf([startInd,endInd]) = true;
%# fill at startInd+1 wherever startInd is not equal endInd
tf = imfill(tf,startInd(startInd~=endInd)'+1); %' SO formatting
%# use find to get the indices
v = find(tf)' %' SO formatting
v =
1 2 3 6 7 8 9 10 12 15 16
Very weird solution IMHO creating temporary strings and using EVAL. Can be also one-liner.
tmp = cellstr(strcat(num2str(M(:,1)),{':'},num2str(M(:,2)),{' '}));
v = eval(['[' cell2mat(tmp') ']']);
I know it will probably not work on large matrix. Just for fun.