0

Is there a way to convert a double array to a struct array and place it under one field?

For example, suppose we get a double array from a call of cellfun and the output array looks like

data=[1,2;3,4];

Can we get a struct S where

S=struct;
for i=1:numel(data)
        S(i).data=data(i);
    end
end

with native functions or just get S efficiently? (visual at the end)

If there is a method, can the resultant struct array preserve the dimensions of the original double array? Can the method apply to output of cellfun where the output is a double array?

In my particular application, my data is the (uniform) output of a call to cellfun and when I set S.data=cellfun(...), the result is a 1-element struct array where S.data is the m-by-n double array from cellfun(...). What can I do to distribute the array elements?

(My task at hand involves processing 10k data points per query and for each task, it's about 16 queries. So speed is important. If there is no efficient method, I'll know to avoid struct for this particular type of tasks. So comments on that front is helpful too.)

enter image description here

2
  • 1
    Just an FYI: this is highly inefficient memory wise. Each matrix has an overhead of 114 bytes (as of R2017a, not sure if this has changed more recently). So a matrix with a single double value takes up 122 bytes. A cell array where each cell is a single value, or a struct array where each element is a single value, therefore take up at least 122 bytes per element (plus whatever overhead the cell array or struct add on top of that). So, instead of using 8 bytes per element, you are using 122, more than 15 times as much memory. Commented Apr 21, 2020 at 6:26
  • @CrisLuengo: Thank you for chiming in! The info is very helpful for me. I'll keep it in mind. Commented Apr 21, 2020 at 6:28

2 Answers 2

2

Use struct and num2cell:

data = [1,2;3,4];
S = struct ('data', num2cell(data));
Sign up to request clarification or add additional context in comments.

8 Comments

@Argyll: The cellfun solution you added is likely much slower.
@CrisLuengo: even if it starts off from cellfun? Will 'UniformOuput', true + num2cell be quicker than 'UniformOuput', false? I know it may sound strange that I start off with cellfun. On that note, I don't have a choice. That's the beginning of interfacing with a third-party API.
@Argyll I think instead of posting your note as a comment you edited my post. I rolled back the changes.
@Argyll: cellfun calls a function handle for each cell, this carries a large overhead. rahnema1's solution is simple and likely the most efficient one you can build. num2cell creates a cell array, but each of its elements (one-value matrices) will be re-used in the struct (MATLAB's lazy copying), so even though it looks like double work (matrix -> cell array -> struct array), it's not a lot of overhead.
@rahnema1: ok. Np.
|
0

As you want to have an individual field for every element of the matrix, I have to say: no there is no standard solution for this. If you don't absolutely need it, I would not recommend doing so, see this post. It simply requires more memory and is a bit of a pain when looking.

Nevertheless, it is possible but you have to start each name of your field with a character.

data = [1,2;3,4];
% create empty struct
S = struct();
%% create new structure
for i = 1:length(data)
    % create field name (must start with a character!)
    fld = num2str(i,'F%d');
    % write to field (note the brackets)
    S.(fld) = data(i);
end

I case, you want o access the data by looping, use the MATLAB-buildin function fieldnames for a more general approach than building the filed names by yourself (and avoid shortfalls, when your delete one field;) )

%% access new structure (looping over field names)
% get all field names
FlNms = fieldnames(S);
for i = 1:length(FldNames)
    % access field names (this is a cell!)
    fld = FldNms{i};
    % access struct
    data_element = S.(fld);
    % do something
end

5 Comments

Hi, thanks for replying. Sorry I am struggling to understand. Per query, I would be storing maybe 6 n-by-1 double arrays into a single n-by-1 struct array with 6 fields. I'll repeat the same kind of queries but every time it will be a new struct. Is that still bad?
storing it in a n-by-6 matrix will always be more efficient in terms of memory and probably in terms of further processing than filling the arrays into a struct. If you can afford it and it helps your to keep the overview of your code, than go ahead and use structs
No. That is again a higher structure. If you don't have large data, just pick the structure that suits you best
I'll stick with table for now then. And no, I wouldn't call my datasets large. Just a dozen 10k-by-6 arrays at a time. Large enough for me to care about efficiency when manipulating the data. But not large enough to require every last effort on that front.
Than table is the most convenient option as you can give meaningful names to you columns (making it easier to follow your code) and still you can loop through it like a cell.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.