How do I use indexing (vectorization?) rather than for loops for dynamic field referencing into a cell array?
5 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
Daniel Bridges
il 10 Giu 2016
Commentato: Daniel Bridges
il 20 Nov 2017
I think there's a way to eliminate for loops by indexing, or perhaps it's called vectorizing. How do I do this?
For example, I'm trying to plot several vectors of different lengths in the same 3D scatter plot. This code stores 34 DICOM ROI items' double arrays in a 1x34 cell array:
info = dicominfo('filename.dcm');
numberofarrays = 34;
datacells = cell(1,numberofarrays);
names = fieldnames(info.ROIContourSequence.Item_9.ContourSequence);
for loop = 1:numberofarrays
datacells(loop) = {info.ROIContourSequence.Item_9.ContourSequence.(names{loop}).ContourData(:,1)};
end
but this code results in the following error:
datacellsfaster(1:34) = {info.ROIContourSequence.Item_9.ContourSequence.(names{1:34}).ContourData(:,1)};
Expected one output from a curly brace or dot indexing expression, but there were 34 results.
Why was it expecting only one output? How do I eliminate for loops through indexing?
0 Commenti
Risposta accettata
Guillaume
il 10 Giu 2016
I'm suprised you get Expected one output from a curly brace or dot indexing expression as an error and not Argument to dynamic structure reference must evaluate to a valid field name.
Unfortunately, you cannot pass a cell array as dynamic field names, The dynamic name must be a scalar string so,
.ContourSequence.(name{1:34})
is never going to work.
If all the ContourData have the same size you could eliminate the loop with struct2cell and by concatenating all the CountourData into one big matrix. There's no guarantee that it'd be faster, and it certainly would use up a lot more memory.
You're better off with the loop. In any case, with only 34 iterations that loop should execute very quickly.
4 Commenti
Guillaume
il 17 Giu 2016
ismember, as a built-in function, is going to be faster than a loop. The bottleneck is going to be the accumarray calls due to the use of a non-standard accumulation function (the @(x) {x} anonymous function).
In my example, accumarray does not sum the resulting values, it extracts the series of coordinates exactly as you want. The accumulation function I've specified simply wrap the accumulated vectors (all the values that match a depth) into a cell array.
find is indeed often unnecessary and using logical indexing directly will speed up your code by a small amount indeed.
By the way, I forgot to say, another way to write your initial loop
for loop = 1:numberofarrays
datacells(loop) = {info.ROIContourSequence.Item_9.ContourSequence.(names{loop}).ContourData(:,1)};
end
would be, assuming that numberofarrays == numel(fieldnames(info.ROIContourSequence.Item_9.ContourSequence)):
datacells = structfun(@(seq) {seq.ContourData(:, 1)}, info.ROIContourSequence.Item_9.ContourSequence);
structfun iterates over all the fields of ContourSequence and, again, the anonymous function simply wrap the ContourData of each field into a cell array. I don't expect any significant gain in speed with that syntax, the looping may be faster but you now have the cost of a function call (to the anonymous function).
Più risposte (1)
geotocho
il 28 Ott 2017
Rather than curly brace indexing, the vectorized way of assigning a command to all cells uses parentheses. Much like the traditional array but in this example A and B are cell arrays of the same size. I wish to assign the row of cells in A to B. In this manner dot indexing is allowed.
B(1,:) = A(1,:);
Vedere anche
Categorie
Scopri di più su Data Type Conversion in Help Center e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!