MATLAB Answers

How to convert a structure array into vector

171 views (last 30 days)
SS
SS on 9 Aug 2019
Edited: Jos (10584) on 9 Aug 2019
Hello.
I have a structure array (1 x 50000) with 10 fields. The elements in the fields are arrays (1 x 50). I want to convert this structure array into a scalar structure with same fields such that, its size is (50000*50 x 1).

  5 Comments

Show 2 older comments
SS
SS on 9 Aug 2019
Hi.
For example,
I have a structure array Main (1 x 500) with 2 fields (fel1,fel2). The elements of these fields (fel1,fel2) are vectors of size 1 x 5. I want to convert the structure Main to a scalar structure (2500 x 1) with same fields.
Jos (10584)
Jos (10584) on 9 Aug 2019
This is not a small example :-)
Provide 1x3 Main structure (the input) and expected out. That would help
SS
SS on 9 Aug 2019
Hi.
The input is something like,
Main(1).fel1=[1,2,3,4,5];
Main(2).fel1=[10,20];
Main(1).fel2=[2,4,6,8,10];
Main(2).fel2=[150,200];
The output should be,
Main(1).fel1=1, Main(2).fel1=2, Main(3).fel1=3.........Main(7).fel1=20
Main(2).fel2=2, Main(2).fel2=4, ..........................Main(7).fel2=200

Sign in to comment.

Accepted Answer

Stephen Cobeldick
Stephen Cobeldick on 9 Aug 2019
Edited: Stephen Cobeldick on 9 Aug 2019
S(1).F1 = [1,2,3,4,5];
S(2).F1 = [10,20];
S(1).F2 = [2,4,6,8,10];
S(2).F2 = [150,200];
F = fieldnames(S);
C = num2cell(struct2cell(S),3);
C = cellfun(@(c)[c{:}],C,'uni',0);
C = num2cell(vertcat(C{:}));
T = cell2struct(C,F,1)
Giving:
T =
7x1 struct array with fields:
F1
F2
Checking the first field's values:
>> S.F1 % input
ans =
1 2 3 4 5
ans =
10 20
>> T.F1 % output
ans = 1
ans = 2
ans = 3
ans = 4
ans = 5
ans = 10
ans = 20

  3 Comments

SS
SS on 9 Aug 2019
I have another question. How can this be implemented if, the size of the arrays is not same throughtout. For example, if the input is
Main(1).fel1=[1,2,3,4,5];
Main(2).fel1=[10,20,30];
Main(1).fel2=[2,4,6,8];
Main(2).fel2=[150,200];
The output should be,
Main(1).fel1=1, Main(2).fel1=2, Main(3).fel1=3.........Main(8).fel1=30
Main(2).fel2=2, Main(2).fel2=4, ..........................Main(6).fel2=200
Stephen Cobeldick
Stephen Cobeldick on 9 Aug 2019
"How can this be implemented if, the size of the arrays is not same throughtout."
Something like this should work:
  1. decide what default value/array should go into those fields that are unassigned (e.g. empty numeric, NaN).
  2. measure the sizes of all vectors
  3. preallocate a cell array of the correct size, using your default value.
  4. loop over the fieldnames
  5. concatenate the data (comma-separated lists will likely be useful here), convert to cell.
  6. assign to the cell array using the length of the concatenated data.
  7. convert to structure using struct2cell.

Sign in to comment.

More Answers (1)

Jos (10584)
Jos (10584) on 9 Aug 2019
Why on earth store scalar values like that? Why not have a simple, highly efficient M-by-N matrix, rather than a cumbersome M-by-1 structure array, with N fields, each storing a single scalar value.
% a structure array with N = 2 fields. Each field holds overall and in total 7 elements
S(1).F1 = [1,2,3,4,5];
S(2).F1 = [10,20];
S(1).F2 = [2,4,6,8,10];
S(2).F2 = [150,200];
A = arrayfun(@(f) [S.(f{:})].', fieldnames(S), 'un', 0)
A = [A{:}] % a 7-by-2 matrix

  3 Comments

SS
SS on 9 Aug 2019
Hi. What if the size of the fields is not same? Like, I have given in the above message
Main(1).fel1=[1,2,3,4,5]; % 5 elements
Main(2).fel1=[10,20,30]; % 3 elements
Main(1).fel2=[2,4,6,8]; % 4 elements
Main(2).fel2=[150,200]; % 2 elements
Jos (10584)
Jos (10584) on 9 Aug 2019
You should store values in a way that make sense to you. What is the relationship between the two fields of a particular element of the structure array (example: what do fel1 and fel2 of Main(k) have in common.) The same holds for the values inside a field. What do Main(J).fel1(K) and Main(J).fel2(K) have in common?
In your example, I (we?) assumed that there is a direct relations ship between the position in the output (either as matrix or a structure) and the position in the input. However, this does not seem to be the case.
Think about that and then describe what kind of output you need for further processing...
Jos (10584)
Jos (10584) on 9 Aug 2019
One option is to keep the fields blank, or fille the empty spots in my output with NaNs.
One can use my function PADCAT to pad shorter vectors (being concatenated fields) with NaNs:
S(1).F1 = [1,2,3,4,5];
S(2).F1 = [10,20];
S(1).F2 = 2 ;
S(2).F2 = [150,200];
A = arrayfun(@(f) [S.(f{:})].', fieldnames(S), 'un', 0)
A = padcat(A{:}) % a 7-by-2 matrix
PADCAT can be found on the File Exchange:

Sign in to comment.

Sign in to answer this question.


Translated by