Iterating over a cell array: do for loops work?

132 ビュー (過去 30 日間)
Ken
Ken 2024 年 3 月 28 日
コメント済み: Voss 2024 年 4 月 4 日
In the process of analyzing experimental data, I produce a series of arrays of object that are not all the same length. I thought it would be a reasonable strategy to make them each a member of a cell array. Then, thinking as I would think in Python, I can process them by iterating through the cell array, and sub-iterating through each of those arrays to process each object in turn. It isn't working. Here's what I have:
classdef Peak
properties
Amplitude
Time
ActualAmplitude
ActualTime
EventInterval
HWInterval
Start
End
HWStart
HWEnd
Pairing
TOF
StartIndex
NSamples
Partner % index of the second peak in a pair
Exclude % user chooses to exclude this peak from processing
end
Here's what the top level array looks like:
And here's my code for iterating, to produce input for the hist3 graphing operator.
function b3d(sequence, allPeaks)
stage = 1;
j = 1;
x(100000) = 0;
y(100000) = 0;
for group = allPeaks
for pcell = group
x(j) = sequence(stage);
p = pcell{1}
y(j)= p(1).ActualAmplitude;
end
end
graphable = [x', y'];
save("gr.mat", "graphable");
end
But it only iterates once! Producing this output. What to do differently?
  1 件のコメント
Stephen23
Stephen23 2024 年 3 月 29 日
編集済み: Stephen23 2024 年 3 月 29 日
"Iterating over a cell array: do for loops work?"
Of course they do. It would be odd if they did not. Here are some ways to index into a cell array:
Note that MATLAB is not Python. Rather than splitting the data up into lots of separate (nested) arrays, in MATLAB it is usually better to keep data together as much as possible: one table with some meta-data in a few columns is generally better than lots of separate (nested) arrays. Then you can leverage the efficient inbuilt approaches to data processing:
Having lots of vectors TIME, AMPLITUDE, etc hints that you should be using matrices and arrays more.
MATLAB is based around contiguous arrays of numeric data. Python is not (unless you use some third-party module, e.g. numpy). This fundamentally changes how data should be designed to process it efficiently:

サインインしてコメントする。

回答 (1 件)

Voss
Voss 2024 年 3 月 28 日
編集済み: Voss 2024 年 3 月 28 日
A few things:
  1. A for loop iterates over the columns of what you give it, so if you give it a column vector (cell array or otherwise) like allPeaks, it iterates once, because the thing has one column. To iterate over each element of a column vector, you can make it a row vector in the for loop statement by transposing it or reshaping it.
  2. Once that is changed, group will be a scalar cell array, so for pcell = group just makes pcell the same as group (and makes that for loop unnecessary). To iterate over the contents of the scalar cell array group, use for pcell = group{1}, in which case pcell takes as values each element of the Peak array group{1}. Then use pcell inside the loop instead of pcell{1}. See below.
  3. In your code, j never changes. I don't know if this is just example code, but as it is only the first row of graphable will ever be non-zero because j never increases beyond 1.
Here's a running example, using struct arrays instead of Peak arrays:
% construct a cell array of struct arrays with an ActualAmplitude field:
siz = [2,9,21,33,47,66];
N = numel(siz);
allPeaks = cell(N,1);
for ii = 1:N
allPeaks{ii} = struct('ActualAmplitude',num2cell(rand(1,siz(ii))));
end
allPeaks
allPeaks = 6x1 cell array
{1x2 struct} {1x9 struct} {1x21 struct} {1x33 struct} {1x47 struct} {1x66 struct}
% check the ActualAmplitude values:
temp = [allPeaks{:}];
[temp.ActualAmplitude]
ans = 1x178
0.5917 0.5443 0.3727 0.4115 0.4991 0.2764 0.0753 0.2299 0.6473 0.0032 0.2679 0.0090 0.3725 0.0210 0.5198 0.4835 0.2812 0.0487 0.5884 0.3015 0.7774 0.1971 0.1024 0.2095 0.5331 0.6826 0.0091 0.2153 0.1524 0.0446
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
% modified looping code:
sequence = 1;
stage = 1;
j = 1;
x(100000) = 0;
y(100000) = 0;
for group = allPeaks(:).' % making row vector to iterate over
for pcell = group{1} % group is a scalar cell array, take group{1} to iterate over its contents
x(j) = sequence(stage);
y(j) = pcell.ActualAmplitude;
j = j+1; % increment j
end
end
graphable = [x', y']
graphable = 100000x2
1.0000 0.5917 1.0000 0.5443 1.0000 0.3727 1.0000 0.4115 1.0000 0.4991 1.0000 0.2764 1.0000 0.0753 1.0000 0.2299 1.0000 0.6473 1.0000 0.0032
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
You can maybe avoid at least one of your loops by using the same syntax I used to check the ActualAmplitude values
temp = [allPeaks{:}];
which concatentates the contents of each cell of allPeaks together into a single Peak array, then iterate over that if necessary.
  5 件のコメント
Voss
Voss 2024 年 3 月 29 日
Any other questions, let me know. Otherwise, please Accept this Answer. Thanks!
Voss
Voss 2024 年 4 月 4 日
Hey @Ken, did this answer answer your questions? If so, Accept it.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeData Type Conversion についてさらに検索

製品


リリース

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by