Generate vectors from single values in Matlab - arrays

I have vector c:
c = [2 5 3];
I want to generate vectors with their lengths equal to each value in c in a consecutive order. So, I should obtain 3 vectors:
c1 = [1 2];
c2 = [3 4 5 6 7];
c3 = [8 9 10];
Next, I want to align these vectors in a 1x3 cell array:
out = {c1 c2 c3};
This may seem straightforward, but I can't figure how to do it automatically. Any ideas?

You could use mat2cell to accomplish this. We first create an array from 1 to sum(c) and then use mat2cell to group the array into pieces where each piece is the size of each element of c.
out = mat2cell(1:sum(c), 1, c);
This reduces the need for intermediate variables and gives you your cell array directly.
out{1} =
1 2
out{2} =
3 4 5 6 7
out{3} =
8 9 10

Related

MATLAB - Get every N elements in a vector

I have an array
a = [1 2 3 4 5 6 7 8]
I want to get every group of 4
so the result is as such
[1 2 3 4]
[5 6 7 8]
I do not know how many elements there will be but I know it is divisible by 4
so something like a(1:4) and a(5:8) wont work, I can use a loop, but is there a way to not use a loop?
For an unknown number of elements in a you can use reshape you just need to figure out how many rows you will have in the final matrix or (better for your case) the number of columns.
a = 1:4*10;
a2 = reshape(a, 4, []).';
If you went the rows routine you would do this.
a = 1:4*10;
a2 = reshape(a, [], numel(a) / 4).';
You just need to be sure that a has the proper number of elements. numel simply tells you the total element count.

Create strings from the indices of two vectors in Matlab

I have two vectors a and b as an example:
a = [1 2 3 4];
b = [5 6 7 8];
I want to create strings from the indices of a and b:
c1 = a(1):b(1) = [1 2 3 4 5];
c2 = a(2):b(2) = [2 3 4 5 6];
c3 = a(3):b(3) = [3 4 5 6 7];
c4 = a(4):b(4) = [4 5 6 7 8];
Then I want to concatenate the obtained strings:
C = cat(2, c1, c2, c3, c4) = [1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8];
I would like a general solution to help me automatize this algorithm.
Solution
This should do the trick without using a loop:
>> a = [1 3 4 5];
>> b = [5 6 7 8];
>> resultstr = num2str(cell2mat(arrayfun(#(x,y) x:y,a,b,'UniformOutput',false)))
resultstr =
1 2 3 4 5 3 4 5 6 4 5 6 7 5 6 7 8
Performance
I tried to do a quick comparison between this method, Luis Mendo's method and the for loop (see e.g. A. Visser's answer). I created two arrays with pseudo-random numbers from 1 to 50 and 501 to 1000 and timed the calculation for array sizes from 1 to 300, disregarding the string conversion.
Luis Mendo's anwer is the clear winner, in terms of time complexity arrayfun seems to be on par with bsxfun. The for loop fares much worse, except for very small array sizes, but I'm not sure the timing can be trusted there.
The code can be found here. I'd be very happy to get some feedback, I'm a bit unsure about those measurements.
This can be done without loops (be they for, arrayfun or cellfun) using bsxfun's masking capability. This works also if the "strings" have different lengths, as in the following example.
a = [1 2 3];
b = [3 5 6];
m = (0:max(b-a)).'; %'
C = bsxfun(#plus, a, m);
mask = bsxfun(#le, m, b-a);
C = C(mask).';
The result in this example is:
C =
1 2 3 2 3 4 5 3 4 5 6
Try something like:
A = [1:5; 5:8];, C = [];
for i = A, C = [C i(1):i(2)]; end
Cstr = num2str(C);
I would do this:
a = [1 3 4 5]; b = [5 6 7 8];
c =[];
for i =1:length(a)
c = [c [a(i):b(i)]];
end
num2str(c)
First of all, don't assign variables as C1, C2, C3 etc, use cells for that.
I'd use a for-loop for this, though there probably is a better alternative.
a = [1 3 4 5]; b = [5 6 7 8];
C = [];
for ii = 1:length(a)
tmp = a(ii):b(ii);
C = [C tmp];
end
This way tmp stores your separate arrays, then the following line adds it to the pre-existing array C.
Just for fun:
a = [1 2 3 4]; b = [5 6 7 8];
A=fliplr(gallery('circul',fliplr([a,b])));
B=A(1:numel(a)+1,1:numel(a));
C=num2str(B(:).')

Merge arrays with unequal number of columns

I have around 100 1D arrays I'd like to merge to a matrix.
The arrays have 140 to 180 columns.
Is it possible to merge these 1 x (140-180) arrays to a matrix with a dimension of 100 (amount of arrays) x 180 ?
All the arrays contain numbers. I want to expand the 1x140 array to a 1x180 array by means of interpolation.
In a simplified form, it should be something like this:
A = [1 5 7 8 3]
B = [1 3 5]
result=
[1 5 7 8 3
1 2 3 4 5]
The array B (1x3) is expanded to an 1x5 matrix. And the values in between are interpolated.
Basically, I thought of using "vertcat" after all arrays are expanded by a same amount of columns.
Thanks in advance,
Koen
How about this?
array = {[1 5 7 8 3],[1 3 5]}; % example data
N = 5; % desired length (180 in your case)
aux = cellfun(#(v) interp1(linspace(0,1,length(v)),v,linspace(0,1,N)), array, 'uni', false);
result = cat(1,aux{:});
It uses linear interpolation. For your example, this gives
>> result
result =
1 5 7 8 3
1 2 3 4 5
Note that linear interpolation modifies all values of the vector except first and last, in general. For example, with N=5 the vector [1 3 4 5] would get interpolated to [1 2.5 3.5 4.25 5]. You could use other forms of interpolation by passing an extra argument to interp1, see help interp1.

Matlab, matrix of arrays

There are 3 matrices A,B,C:
A=[0 1;2 3]
B=[4 5;6 7]
C=[8 9;10 11]
How to create a new matrix D(2,2) so as its elements are arrays of a type
D = [{A(1,1), B(1,1), C(1,1)} {{A(1,2), B(1,2), C(1,12};
{A(2,1), B(2,1), C(2,1)} {A(2,2), B(2,2), C(2,2)}]
For example: Using an operator D(1,1) gives the result
0, 4, 8
The bracket {} are only illustrative and do not represent a matlab syntax...
You could stack the matrices along the third dimension:
D = cat(3,A,B,C);
Then you could access as:
>> D(1,1,:)
ans(:,:,1) =
0
ans(:,:,2) =
4
ans(:,:,3) =
8
if you want to get a 1D-vector:
>> squeeze(D(1,1,:)) %# or: permute(D(1,1,:),[1 3 2])
ans =
0
4
8
If you prefer to use cell arrays, here is an easier way to build it:
D = cellfun(#squeeze, num2cell(cat(3,A,B,C),3), 'UniformOutput',false);
which can be accessed as:
>> D{1,1}
ans =
0
4
8
You are almost there:
D = [{[A(1,1), B(1,1), C(1,1)]} {[A(1,2), B(1,2), C(1,2)]};
{[A(2,1), B(2,1), C(2,1)]} {[A(2,2), B(2,2), C(2,2)]}]
(you see the additional branches?)
D is now a cell array, with each cell containing a 1x3 matrix.
To access the cell array use this syntax:
D{1,1}

MATLAB: 2-D array of structs (containing vectors) to 3-D Array?

I have a 2-dimensional array of structs 'cell' which each contain a number of vectors:
cell(1,1).U = [1 2 3];
cell(1,2).U = [4 5 6];
cell(2,1).U = [7 8 9];
cell(2,2).U = [0 1 2];
I would like to extract the data into a 3-D array A(i,j,k).
Using cell-style extraction returns a 1x3 cell, the contents of which are
>> {cell.U}
ans = {[cell(1,1).U] [cell(1,2).U] [cell(2,1).U] [cell(2,2).U]}
And thus, converting this to a matrix using cell2mat(), as in:
cell2mat(ans)
Returns a 3x4 array.
Ideally, I would like a 2x2x3 array so that the indices i and j are preserved. Is there any way (short of looping) to accomplish this?
Use CAT and RESHAPE. Also, don't call your variable cell, since that's a built-in function.
>> c(1,1).U = [1 2 3];
c(1,2).U = [4 5 6];
c(2,1).U = [7 8 9];
c(2,2).U = [0 1 2];
>> out = cat(1,c.U)
>> out = reshape(out,2,2,3)
out(:,:,1) =
1 4
7 0
out(:,:,2) =
2 5
8 1
out(:,:,3) =
3 6
9 2

Resources