How to perform operations on cell arrays?

I have this section of code
V = cell(1,12);
for k = 1:12
V{k} = cumtrapz(A{k});
end
I now need to convert from a cummulative V to discrete instances of V. It should be noted that columns 1-3, 4-6, 7-9, and 10-12 are of the same size (1=2=3 /= 4, but 4=5=6 etc.). If, for example, A{1,0} = 0, A{1,1} = 1, and A{1,2} = 4, then V{1,1} = 1, and V{1,2} = 3. This operation needs to be performed throughout each cell in order to get velocities at a point instead of a running total.

3 Comments

It is not clear to me what your terminology means. Could you provide more details about what you want as output? It sounds like you want something like cellfun, but I'm not sure what steps to suggest.
"How to perform operations on cell arrays?"
cellfun()
I need to have the output of my operation to be cells that are a single column vector whose values are derived from the previous corresponding cell. Like that of above. For example
cumtrapz returns:
X{1}
1
3
5
10
12
16
I need to do an operation that looks like this:
Y{1}
1-0 = 1
3-1 = 2
5-3 = 2
10-5 = 5
12-10 = 2
16-12 = 4
And this is done for X{1} through X{12} and output into Y{1} through Y{12}.

Sign in to comment.

 Accepted Answer

Adam Danz
Adam Danz on 9 Oct 2019
Edited: Adam Danz on 9 Oct 2019
My understanding of the problem is that you have a cell array of column vectors and you'd like to differentiate them. I've created demo data similar to the data I think you're working with. Please let us know if this doesn't hit the target.
% Create demo data similar to OP's example
X = arrayfun(@(n){unique(randi(30,n,1))},10:15);
% differentiate with leading 0
Y = cellfun(@(x){x - [0; x(1:end-1)]}, X)
% See results of a single element
table(X{1}, Y{1}, 'VariableNames', {'X','Y'})

13 Comments

I've used cumtrapz to integrate some data, and put that data in the V{} cell. Since cumtrapz is cummulative it doesn't represent the value at a particular instance. In order to find what happened at time instance "3" you would need to subtract the cummulative total of instance 3 from instance 4. Something like
Cummulative V{1}
1
5
7
8
10
These values are the running sum of the area under the A{1} curve. I need the area of each instance, or in other words what was the velocity at time 3, not what is the cummulated velocity total. I'm sorry if this request is more confusing than it needs to be.
I'm not following....
The code in my answer does exactly what you described in this comment. If that isn't your goal, perhaps you could try to explain again with some input/output examples.
Here is my code - For reference these are acceleration vectors in the x, y, and z directions
%% Acceleration Vectors
A = cell(1,12);
% 480 CFH
A{1} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','N8:N11968');
A{2} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','O8:O11968');
A{3} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','P8:P11968');
% 960 CFH
A{4} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','S8:S8488');
A{5} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','T8:T8488');
A{6} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','U8:U8488');
% 2560 CFH
A{7} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','X8:X7494');
A{8} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','Y8:Y7494');
A{9} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','Z8:Z7494');
% 3600 CFH
A{10} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','AC8:AC5749');
A{11} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','AD8:AD5749');
A{12} = readtable('MaxAir Plugged.xlsx','Sheet','Data','Range','AE8:AE5749');
%% Table to Array
for k = 1:12 % table2array
A{k} = table2array(A{k});
end
%% Time Vectors
t = cell(1,4);
for k=1:4
t{k} = (0:0.02:(length(A{k*2+(k-2)})-1)*0.02)';
end
%% Some plotting stuff
%% Integration to Velocity
V = cell(1,12);
for k = 1:12 % cumtrapz
V{k} = cumtrapz(A{k});
end
From this point I have been using writecell to an excel file and doing the operation there and then importing that data back to MATLAB. In excel I've been using this type of formula:
B2 = A2 - A1
This is then applied to all 5k-12k data points for all 12 columns. The goal is to find a way to do this in MATLAB so I don't have to deal with this slow multi-step process.
This answer is much nicer.
This is helpful. Here's what I understand - please correct me where I go wrong:
You have a bunch of column vectors. Judging from the excel row references, those column vectors appear to be the same length so perhaps you have a matrix, instead. Your goal is to differentiate each column by subtracting row n+1 from n. Is that correct?
That's what I understood from "B2 = A2 - A1".
Is that correct?
Hi Adam,
I've seen Jesse's earlier question so have a reasonable idea.
The column vectors are acceleration in x,y and z from an accelerometer. So Jesse wants to integrate to find the change in velocity. Using cumtrapz he has the cumulative change over the data at each interval.
He wants to find the velocity for each individual time period, just finding the integral over multiple periods in a row. EG the integral of acceleration from point 1,2, then 2,3 etc. So he knows the change in velocity for each one. The sum of these is = to the integral over whole time period.
Both our solutions work but yours would be:
% Create demo data similar to OP's example
X = arrayfun(@(n){unique(randi(30,n,1))},10:15);
a = cellfun(@(x) {cumtrapz(x)}, X)
% differentiate with leading 0
Y = cellfun(@(x){x - [0; x(1:end-1)]}, a)
% See results of a single element
table(X{1}, Y{1}, 'VariableNames', {'X','Y'})
Yes. The column vectors aren't all equal in size to each other. The four sets of x, y, and z are, but all 12 aren't. If it would help to make them seperate and uniform that wouldn't be a problem, I just made only "A" cell array for ease of the shown for loop. Thanks for your patience.
John Doe
John Doe on 10 Oct 2019
Edited: John Doe on 10 Oct 2019
Cam you share the data? That would be a lot easier
I'm not sure if this will contain the data imported from Excel or not. I've never used this feature before, but my .m file is attached
@John Doe, thanks for the background info!
@Jesse Finnell, the mfile shows us how you're reading in the data but we still don't have access to your variable values. If you're trying to eliminate the process of writing to excel and then reading it back in (which is a wise decision), we'd need the variable values prior to writing the data into excel.
You can execute your code up to that point, pause it, and save the values to a mat file. Then attach the mat file.
Thanks for the tip! Here is the A cell data along with the time vectors that fit each separate set. The V cell should be easy enough to get to with the code. At least prior to where the final result will be.
Adam Danz I think this line of code from your answer above will work
Vmod = cellfun(@(v){v-[0;v(1:end-1)]},V);
I modified it obviously, to fit my needs. With your % comment I thought differentiation was happening, but when comparing my slow manual process and this result from this I get the same results! I suppose more investigation of the code would have been a wise decision on my end, opposed to continuing to ask questions. Thanks John Doe as well.
Adam Danz
Adam Danz on 10 Oct 2019
Edited: Adam Danz on 10 Oct 2019
Glad to hear you gave it a try! I kept re-reading your description and trying to figure out how it is different from my proposal. I usually give the benefit of the doubt to the OP and assume I'm missing something.
The method I'm using is close to Matlab's diff() function which computes the approximate derivative. The only difference is the leading 0 which preserves the number of elements in the output.
Thanks to John Doe for helping out and following the discussion in close detail.

Sign in to comment.

More Answers (1)

John Doe
John Doe on 10 Oct 2019
Edited: John Doe on 10 Oct 2019
I found using trapz is a more intuative method. I used linear acceleration so it was easy to check. I think there is a more efficient way to do this, but I am not certain.
Here is the results.
a = [0:1:49]'; %a = acceleration
deltaV = zeros(1,numel(a))'; % memory pre-allocation
for k = 1:49
deltaV(1,k) = trapz(a(k:k+1,1)) % integral over 1 period
end
figure(1)
plot(a)
xlabel('time')
ylabel('acceleration')
figure(2)
plot(v)
xlabel('time')
ylabel('velocity')
figure(3)
plot(deltaV)
xlabel('time')
ylabel('Change in Velocity')

2 Comments

I get this error when I ran your code
Index in position 1 exceeds array bounds (must not exceed 50).
Error in test (line 4)
deltaV(1,k) = trapz(a(k:k+1,1)) % integral over 1 period
Typo on my part in line 3. I've updated.
k = 1:50
Should have been
k = 1:49

Sign in to comment.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products

Release

R2019a

Asked:

on 8 Oct 2019

Edited:

on 10 Oct 2019

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!