if-loop: Devide a table and save the parts in cell array
Show older comments
Dear Matlab-Community,
I am a total Matlab-newbie.
My problem is the following:
I have data as a two column table (A) with 142 rows. The values in the left column are loads and the values on the right are time values.
What I want to achieve with my skript is, to seperate the table after every t-th time unit. The resulting parts are supposed to be saved in the cells of a cell-array (B). So far, I could solve the problem by using an easy for loop.
But there is an extra condition: The table should only be separated when the last two values of the left column are identical. If that is not the case, the table should be separated one value after this.
My first approach is an if else loop:
Code:
%% create data
v=0.1+(50-0.1)*rand(142,1);
v=sort(v);
u=1+(100-1)*rand(71,1);
u=reshape(repmat(u(:)',2,[]),[],1);
A=[u,v];
numIters=13; %% number of seperations
t=A(end,2)/numIters; %% variable t results from the last time value and the number of seperations
k=1; %%
B = cell(numIters,1); %% B is defined
for i=1:length(A)
if (A(i,2) >= t*k && A(i,1) == A(i+1,1))
B {k,1} =A(1:i+1,:);
A=A(i+2:end,:);
k=k+1;
elseif (A(i,2) >= t*k)
B {k,1} =A(1:i+2,:);
A=A(i+3:end,:);
k=k+1;
else
continue
k=k+1;
end
This approach does not work, because A is getting smaller with every iteration, so that the i- assignment doesn't fit anymore.
Could anyone help me out with an other approach?
I hope, you understood the problem. Feel free to ask, if not.
I appreciate your help!
Thea
Answers (1)
Note that you are not using what matlab calls a table. You may actually be better off using tables or even better timetables.
Anyway, with regards to your question. As ever in matlab, it's easier to do it without a loop:
%using your A and t
destination = discretize(A(:, 2), 0:t:A(end, 2)); %find which cell each row is supposed to go in.
splitat = find(diff(destination)); %find at which row we're going to split the array.
notatboundary = A(splitat, 1) ~= A(splitat-1, 1); %which of these does not correspond to a duplicated row
splitat(notatboundary) = splitat(notatboundary) + 1; %increase by one for these
B = mat2cell(A, diff([0; splitat; size(A, 1)]), size(A, 2)); %split
I've not tried to understand your loop to see what you've done wrong.
However, I've just noticed this (which is not the cause for your code going wrong but is still a problem):
for i=1:length(A)
Never use length on a matrix. length is only the number of rows if the matrix has more rows than columns (and any other dimension). You meant size(A, 1) here. In fact, never use length. For vectors, use numel instead.
2 Comments
Thea
on 4 Apr 2019
Any idea how to solve that?
Depends on what you want to do. Your condition the rows should only be separated when the last two values of the left column are identical cannot apply since there aren't any last two values. So what should happen?
- Always separate at that row?
- Look at the next value, if identical increase by one?
- You are guaranteed that the first two values are identical, so always increase by one if split is found on 1st row.
The first one is easily achieved by replacing the offending line by:
notatboundary = A(splitat, 1) ~= A(max(splitat-1, 1), 1);
The last one, by replacing it with:
notatboundary = A(splitat, 1) ~= A(max(splitat-1, 1), 1) | splitat == 1;
The middle one is a bit more complicated. It probably can be done as a one liner, but for clarity I'd use an if:
notatboundary = A(splitat, 1) ~= A(max(splitat-1, 1), 1);
if splitat(1) == 1 && A(1, 1) == A(2, 1)
notaboundary(1) = true;
end
edit: the one liner version:
notatboundary = A(splitat, 1) ~= A(max(splitat-1, 1), 1) | (splitat == 1 & A(1, 1) == A(2, 1))
Categories
Find more on App Building in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!