Goods
Goods

Reputation: 225

How can I merge redundant fields within a structure?

I have a data set with multiple fields of which several of the fields are different names for equivalent properties. I have rescaled and adjusted the data so that the quantities are comparable and want to merge them into a single field.

As a toy example, let's say I have:

s = struct('pounds', [nan nan 4.8], 'pennies', [120 370 nan]);
s.pennies = s.pennies/100;

How do I merge my incomplete fields to get the desired output:

snew = struct(pounds, [1.2 3.7 4.8]);

Upvotes: 1

Views: 62

Answers (3)

FangQ
FangQ

Reputation: 1544

try my two-liner below

c=struct2cell(s);
s=struct('pounds',unique([c{:}]));

even better, you can also do it using the below oneliner

s=struct('pounds',unique(cell2mat(cellfun(@(x) x(:), struct2cell(s),'UniformOutput',false)))')

Upvotes: 0

Luis Mendo
Luis Mendo

Reputation: 112759

The following works for any number of fields. Since it is guaranteed that only one field is not NaN at each position, you can

  1. Convert to a matrix such that each original field becomes a row of the matrix.
  2. Keep only the numbers, ignoring NaN's. By assumption, this gives exactly one number per column.
  3. Arrange that into a struct with the desired field name.

s = struct('pounds',[nan,nan,4.8], 'pennies', [120,370,nan])
s.pennies = s.pennies/100; % example data
target_field = 'pounds'; % field to which the conversion has been done

t = struct2cell(s); % convert struct to cell array
t = vertcat(t{:}); % convert cell array to matrix
t = t(~isnan(t)).'; % keep only numbers, ignoring NaN's
result = struct(target_field, t); % arrange into a struct

Upvotes: 1

gnovice
gnovice

Reputation: 125874

If you have modified your field values such that they should be equivalent, and simply need to combine the non-NaN values, one option is to vertically concatenate the fields then use min or max down each column (which will ignore the NaN values). Then just remove the unwanted field with rmfield:

>> s = struct('pounds', [nan,nan,4.8], 'pennies', [120,370,nan]);
>> s.pounds = min([s.pounds; s.pennies./100], [], 1);  % Scaling included here
>> s = rmfield(s, 'pennies')

s = 

  struct with fields:

    pounds: [1.2000 3.7000 4.8000]

Upvotes: 2

Related Questions