Extract values from vector and save in new vector - matlab

I have a vector Cycle() that can contain several elements with a variable size.
I want to extract from this vector all the values which are in the odd columns, i.e. Cycle(1), Cycle(3), Cycle(5) ... and save them into a new vector Rcycle.
That's my code:
Rcycle = zeros(1, length(cycle)/2);
Rcycle(1) = cycle(1);
for j=3:length(cycle);
for i=2:length(Rcycle);
Rcycle(i) = cycle(j);
j = j+2;
end
end
Also I want to extract from Cycle() the even columns and save them in a vector Lcycle. My code:
Lcycle = zeros(1, length(cycle)/2);
Lcycle(1) = cycle(2);
for k=4:length(cycle);
for i=2:length(cycle);
Lcycle(i) = cycle(k);
k = k+2;
end
end
By running this for a sample Cycle() with 12 elements I get the right results for Lcycle, but the wrong ones for Rcycle. Also I get the error that my matrix have exceeded its dimension.
Has anyone any idea how to solve this in a more smooth way?

Use vector indexing!
Rcyle=cycle(1:2:end); %// Take from cycle starting from 1, each 2, until the end
Lcycle=cycle(2:2:end);%// same, but start at 2.

Related

Exceeding matrix dimensions when averaging elements

I am trying to create a vector with the average of every 48 elements in eddyCO2.
Tweedle = eddyCO2(1:47:end);
Tweedle(1) = mean(eddyCO2(1):eddyCO2(48));
for i = 2:length(Tweedle)
Tweedle(i) = mean(eddyCO2((i-1)*48):eddyCO2(i*48)); (ERROR: Index exceeds matrix dimensions)
end
I've tried reshaping and the only thing that seems to work is entering values manually but the size is too large to work without a loop. Why is this error appearing?
Does the following modified version of your script do what you intend? Hope it helps.
Tweedle = eddyCO2(1:48:end);
sz = length(eddyCO2);
for i = 1:length(Tweedle)-1
Tweedle(i) = mean(eddyCO2((i-1)*48+1):eddyCO2(i*48)); % averages elements 1-48, 49-96, etc.
end
Tweedle(i+1) = mean(eddyCO2(i*48+1):sz); % averages remaining items at end of vector

insert value in a matrix in a for loop

I wrote this matlab code in order to concatenate the results of the integration of all the columns of a matrix extracted form a multi matrix array.
"datimf" is a matrix composed by 100 matrices, each of 224*640, vertically concatenated.
In the first loop i select every single matrix.
In the second loop i integrate every single column of the selected matrix
obtaining a row of 640 elements.
The third loop must concatenate vertically all the lines previously calculated.
Anyway i got always a problem with the third loop. Where is the error?
singleframe = zeros(224,640);
int_frame_all = zeros(1,640);
conc = zeros(100,640);
for i=0:224:(22400-224)
for j = 1:640
for k = 1:100
singleframe(:,:) = datimf([i+1:(i+223)+1],:);
int_frame_all(:,j) = trapz(singleframe(:,j));
conc(:,k) = vertcat(int_frame_all);
end
end
end
An alternate way to do this without using any explicit loops (edited in response to rayryeng's comment below. It's also worth noting that using cellfun may not be more efficient than explicitly looping.):
nmats = 100;
nrows = 224;
ncols = 640;
datimf = rand(nmats*nrows, ncols);
% convert to an nmats x 1 cell array containing each matrix
cellOfMats = mat2cell(datimf, ones(1, nmats)*nrows, ncols);
% Apply trapz to the contents of each cell
cellOfIntegrals = cellfun(#trapz, cellOfMats, 'UniformOutput', false);
% concatenate the results
conc = cat(1, cellOfIntegrals{:});
Taking inspiration from user2305193's answer, here's an even better "loop-free" solution, based on reshaping the matrix and applying trapz along the appropriate dimension:
datReshaped = reshape(datimf, nrows, nmats, ncols);
solution = squeeze(trapz(datReshaped, 1));
% verify solutions are equivalent:
all(solution(:) == conc(:)) % ans = true
I think I understand what you want. The third loop is unnecessary as both the inner and outer loops are 100 elements long. Also the way you have it you are assigning singleframe lots more times than necessary since it does not depend on the inner loops j or k. You were also trying to add int_frame_all to conc before int_frame_all was finished being populated.
On top of that the j loop isn't required either since trapz can operate on the entire matrix at once anyway.
I think this is closer to what you intended:
datimf = rand(224*100,640);
singleframe = zeros(224,640);
int_frame_all = zeros(1,640);
conc = zeros(100,640);
for i=1:100
idx = (i-1)*224+1;
singleframe(:,:) = datimf(idx:idx+223,:);
% for j = 1:640
% int_frame_all(:,j) = trapz(singleframe(:,j));
% end
% The loop is uncessary as trapz can operate on the entire matrix at once.
int_frame_all = trapz(singleframe,1);
%I think this is what you really want...
conc(i,:) = int_frame_all;
end
It looks like you're processing frames in a video.
The most efficent approach in my experience would be to reshape datimf to be 3-dimensional. This can easily be achieved with the reshape command.
something along the line of vid=reshape(datimf,224,640,[]); should get you far in this regard, where the 3rd dimension is time. vid(:,:,1) then would display the first frame of the video.

save vectors of different sizes in matrix

I would like to divide a vector in many vectors and put all of them in a matrix. I got this error "Subscripted assignment dimension mismatch."
STEP = zeros(50,1);
STEPS = zeros(50,length(locate));
for i = 1:(length(locate)-1)
STEP = filtered(locate(i):locate(i+1));
STEPS(:,i) = STEP;
end
I take the value of "filtered" from (1:50) at the first time for example and I would like to stock it in the first row of a matrix, then for iterations 2, I take value of "filtered from(50:70) for example and I stock it in row 2 in the matrix, and this until the end of the loop..
If someone has an idea, I don't get it! Thank you!
As mentioned in the comments, to make it work you can edit the loopy code at the end with -
STEPS(1:numel(STEP),i) = STEP;
Also, output array STEPS doesn't seem to use the last column. So, the initialization could use one less column, like so -
STEPS = zeros(50,length(locate)-1);
All is good with the loopy code, but in the long run with a high level language like MATLAB, you might want to look for faster codes and one way to achieve that would be vectorized codes. So, let me suggest a vectorized solution using bsxfun's masking capability to process such ragged-arrays. The implementation to cover generic elements in locate would look something like this -
% Get differentiation, which represent the interval lengths for each col
diffs = diff(locate)+1;
% Initialize output array
out = zeros(max(diffs),length(locate)-1);
% Get elements from filtered array for setting into o/p array
vals = filtered(sort([locate(1):locate(end) locate(2:end-1)]));
% Use bsxfun to create a mask that are to be set in o/p array and set thereafter
out(bsxfun(#ge,diffs,(1:max(diffs)).')) = vals;
Sample run for verification -
>> % Inputs
locate = [6,50,70,82];
filtered = randi(9,1,120);
% Get extent of output array for number of rows
N = max(diff(locate))+1;
>> % Original code with corrections
STEP = zeros(N,1);
STEPS = zeros(N,length(locate)-1);
for i = 1:(length(locate)-1)
STEP = filtered(locate(i):locate(i+1));
STEPS(1:numel(STEP),i) = STEP;
end
>> % Proposed code
diffs = diff(locate)+1;
out = zeros(max(diffs),length(locate)-1);
vals = filtered(sort([locate(1):locate(end) locate(2:end-1)]));
out(bsxfun(#ge,diffs,(1:max(diffs)).')) = vals;
>> max_error = max(abs(out(:)-STEPS(:)))
max_error =
0

find index of max from two dimensional time series data in MATLAB

I am trying to find the max value and its location. Following is the example of the programme,
fname = dir('*.mat');
nfiles = length(fname);
vals = cell(nfiles,1);
phen = cell(nfiles,1);
for i = 1:nfiles
vals{i} = load(fname(i).name);
phen{i} = (vals{i}.phen);
[M, position] = max(phen{i},[],3);
clear vals
end
After the program is executed, all the position is showing 1. There are total 15 files and M is taking the values of the last file.
How to overcome this prpoblem? Any help will be appreciated
I am not sure I understand your question.
However, at every iteration you are computing the max value and position and overwriting them in the next iteration (i.e. not storing them anywhere). So at the end of the loop M and position would correspond to the last entry phen{nfiles}.
Each time you run through your for loop, you are overwriting M with the max from the most recently loaded phen from the dimension of 3. Since your data is only two dimensional, you probably should be using a dimension of 1 or 2 instead of 3. Because you are using 3, max is returning 1 to position. Fix the dimension issue and position should then be the correct value.
What you could do is make M and position the size of nfiles. So instead of
[M, position] = max(phen{i},[],3);
do
%create M and positions arrays here
%ex. M(nfiles) = 0; or a smaller value if your values are negative
%do the same for positions
[M(i), positions(i)] = max(phen{i},[],1); %1 or 2 correction here here!
then after your for loop
...
end
[maxM, maxMposition] = max(M);
position = positions(maxMposition);

Matlab: how to implement a dynamic vector

I am refering to an example like this
I have a function to analize the elements of a vector, 'input'. If these elements have a special property I store their values in a vector, 'output'.
The problem is that at the begging I don´t know the number of elements it will need to store in 'output'so I don´t know its size.
I have a loop, inside I go around the vector, 'input' through an index. When I consider special some element of this vector capture the values of 'input' and It be stored in a vector 'ouput' through a sentence like this:
For i=1:N %Where N denotes the number of elements of 'input'
...
output(j) = input(i);
...
end
The problem is that I get an Error if I don´t previously "declare" 'output'. I don´t like to "declare" 'output' before reach the loop as output = input, because it store values from input in which I am not interested and I should think some way to remove all values I stored it that don´t are relevant to me.
Does anyone illuminate me about this issue?
Thank you.
How complicated is the logic in the for loop?
If it's simple, something like this would work:
output = input ( logic==true )
Alternatively, if the logic is complicated and you're dealing with big vectors, I would preallocate a vector that stores whether to save an element or not. Here is some example code:
N = length(input); %Where N denotes the number of elements of 'input'
saveInput = zeros(1,N); % create a vector of 0s
for i=1:N
...
if (input meets criteria)
saveInput(i) = 1;
end
end
output = input( saveInput==1 ); %only save elements worth saving
The trivial solution is:
% if input(i) meets your conditions
output = [output; input(i)]
Though I don't know if this has good performance or not
If N is not too big so that it would cause you memory problems, you can pre-assign output to a vector of the same size as input, and remove all useless elements at the end of the loop.
output = NaN(N,1);
for i=1:N
...
output(i) = input(i);
...
end
output(isnan(output)) = [];
There are two alternatives
If output would be too big if it was assigned the size of N, or if you didn't know the upper limit of the size of output, you can do the following
lengthOutput = 100;
output = NaN(lengthOutput,1);
counter = 1;
for i=1:N
...
output(counter) = input(i);
counter = counter + 1;
if counter > lengthOutput
%# append output if necessary by doubling its size
output = [output;NaN(lengthOutput,1)];
lengthOutput = length(output);
end
end
%# remove unused entries
output(counter:end) = [];
Finally, if N is small, it is perfectly fine to call
output = [];
for i=1:N
...
output = [output;input(i)];
...
end
Note that performance degrades dramatically if N becomes large (say >1000).