0

I am using structures in Matlab to organize my results in an intuitive way. My analysis is quite complex and hierarchical, so this works well---logically. For example: resultObj.multivariate.individual.distributed.raw.alpha10(1).classification(1). Each level of the structure has several fields. Each alpha field is a structured array, indexed for each dataset, and classification is also a structured array, one for each cross validation run on the data.

To simplify, consider the the classification field:

>> classification
ans = 

1x8 struct array with fields:
    bestLambda
    bestBetas
    scores
    statObj
    fitObj

In which statObj has fields (for example):

           dprime: 6.5811
              hit: 20
             miss: 0
      falseAlarms: 0
correctRejections: 30

Of course, the fields have different values for each subject and cross validation run. Given this structure, is there a good way to find the mean of dprime over cross validation runs (i.e. the elements of classification) without needing to construct a for loop to extract, store, and finally compute on?

I was hoping that reshape(struct2array(classification.statObj),5,8) would work, so I could construct a matrix with stats as rows and cross validations runs as columns, but this won't work. I put these items in their own structure specifically because the fields of classification hold elements of various types (matrices, structures, integers).

I am not opposed to restructuring my output entirely, but I'd like it to be done in such a way that the organization is fairly self-commenting, and I could say return to this structure a year from now and remember what and where everything is.

Chris Cox
  • 390
  • 3
  • 14
  • Writing a function to handle this was easy enough, but it did require looping. I don't know if there is any way to coerce the data so that structfun() or struct2array() can work magic, unless I at least loop over the elements of `classification`. – Chris Cox Jul 29 '12 at 21:05
  • can you post your loop-based function, as well as a minimal structure-array example we can play with? For example its not clear what the sizes 5 and 8 represent – Amro Jul 29 '12 at 21:09
  • Sorry, 5 is the number of elements in `statObj` and 8 is the number of elements of `classification`. My function loops over the 8 elements of `classification` and pulls each `.statObj.dprime` into a new vector, which I just take the mean of. Simplicity itself, but your solution is better. – Chris Cox Jul 29 '12 at 21:40

2 Answers2

3

I came up with the following, although I'm not sure if it is what you are looking for:

%# create a structure hierarchy similar to yours
%# (I ignore everything before alpha10, and only create a part of it)
alpha10 = struct();
for a=1:5
    alpha10(a).classification = struct();
    for c=1:8
        alpha10(a).classification(c).statObj = struct('dprime',rand());
    end
end

%# matrix of 'dprime' for each alpha across each cross-validation run
st = [alpha10.classification];
st = [st.statObj];
dp = reshape([st.dprime], 8, 5)'    %# result is 5-by-8 matrix

Next you can compute mean across the second dimension of this matrix dp

Amro
  • 123,847
  • 25
  • 243
  • 454
  • This worked great! Knowing when and how to use `[]` or `{}` to coerce things to behave in particular ways is an art I'm still learning. Thank you! – Chris Cox Jul 29 '12 at 21:36
  • 1
    @ChrisCox: perhaps this [doc page](http://www.mathworks.com/help/techdoc/matlab_prog/bs6e2p_.html) can provide some help. This [post](http://stackoverflow.com/a/4169216/97160) has some info as well. – Amro Jul 29 '12 at 21:47
2

For anyone who happens across this post, and is wrestling with something similar, it is worth asking yourself if such a nested structure-of-structures is really your best option. It may be easier to flatten the hierarchy and include descriptive fields as labels. For instance

resultObj.multivariate.individual.distributed.raw.alpha10(1).classification(1)

might instead be

resultObj(1).
    AnlaysisType    = 'multivariate'
    GroupSolution   = false
    SignalType      = 'distributed'
    Processing      = 'raw'
    alpha           = 10
    crossvalidation = 1
    dprime          = 6.5811
    bestLambda      = []
    bestBetas       = []
    scores          = []
    fitObj          = []

That's not valid Matlab syntax there, but it get's the point across. Rather than building a hierarchy out of nested structures, create a 1xN structure with labels and data. It is a more general solution that is easier to query and work with.

Chris Cox
  • 390
  • 3
  • 14