Adding elements to the ends of vectors inside a cell array of vectors

Is there a way to add elements to the ends of vectors that are inside a cell array of vectors which would be faster than the following code that uses a for-loop?
x = rand(1,20);
i1 = [1,7,11];
i2 = [6,10,20];
xLower = [0.1 0.2 0.3];
xUpper = [100 200 300];
tic();
for r = 1:length(i1)
xRegion{r} = [xLower(r) x(i1(r):i2(r)) xUpper(r)];
end
toc();
xRegion

 Accepted Answer

You could use arrayfun:
arrayfun(@(l,i1,i2,u) [l x(i1:i2) u], xLower,i1,i2, xUpper, uniform, false)
This is untested but should be faster.

8 Comments

Thanks for the attempt but on this example your code was almost 5x slower. For more typical problems I use this code on then your version is about 2x slower. Maybe when the sizes get large enough there is a speed gain but that might not be something I would encounter.
You are right. Arrayfun only speeds up the if the data is significantly larger. For speed improvements it is essential to know the problem best. Can you be a bit more specific on the size of the data?
Additionally in more recent versions for loops are optimized by matlab quite well when it comes to speed.
I will have better estimates on "size-of-data" after some more testing and integration. At least I have your alternative to try when that happens. Thx
Thank you Stephen for pointing out that arrayfun and cellfun are slower than for loops nowadays. My experience of matlab might be a bit rusty from times where it was necessary to avoid for loops to get performance. I guess I’m not the only one: Blogpost by Mike Croucher. When it comes to performance I think it is essential to write benchmarks and test using real or comparable data to test performance of different implementations. That would probably have prevented me from writing the above (untested) answer.
Thank you everyone for the input on for-loop speed and arrayfun. I was wondering if pre-allocation of the cell array would help. However, if that is the case then I am not sure how to set that cell-array pre-allocation up.
cell(length(i1), 1, i2 - i1 + 2)
doesn't work since the first value of i2 - i1 + 2 is used throughout.
maxSz = max(i2 - i1 + 2)
cell(length(i1), 1, maxSz)
sets all vectors to the same maximum size but not to the various sizes of i2 - i1 + 2 of the vectors in each row of the cell array.
You have to differentiate between allocating the cell array and allocating for the actual content of the cell array. Basically your cell array is just storing a bunch of pointers to the actual arrays of double you create in your for loop.
So it would only make sense to do the following which in your current example does not bring any benefit as i1 is quite small (I tried that on my machine):
xRegion = cell(size(i1))
I don't know a way to pre allocate memory for the created double arrays from your loop which would not involve a loop.
Depending on how you later processes the data it could could be worth trying just to use a pre-allocated doble array instead and set all not needed fields to nan. Again just gussing if that even does speed up your code.
arrSize = i2 - i1 + 3;
xRegion1 = nan(length(i1), max(i2 - i1 + 2));
for r = 1:length(i1)
xRegion1(r, 1:arrSize(r)) = [xLower(r) x(i1(r):i2(r)) xUpper(r)];
end
Thanks for the explanation on this type of pre-allocation.

Sign in to comment.

More Answers (0)

Categories

Products

Community Treasure Hunt

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

Start Hunting!