Nicole Leung
Nicole Leung

Reputation: 33

Matlab: select submatrix from matrix by certain criteria

I have a matrix A

A=[f magic(10)]
    A=

931142103          92          99           1           8          15          67          74          51          58          40
931142103          98          80           7          14          16          73          55          57          64          41
931142103           4          81          88          20          22          54          56          63          70          47
459200101          85          87          19          21           3          60          62          69          71          28
459200101          86          93          25           2           9          61          68          75          52          34
459200101          17          24          76          83          90          42          49          26          33          65
459200101          23           5          82          89          91          48          30          32          39          66
37833100          79           6          13          95          97          29          31          38          45          72
37833100          10          12          94          96          78          35          37          44          46          53
37833100          11          18         100          77          84          36          43          50          27          59

The first column are firm codes. The rest columns are firms' data, with each row referring to the firm in Column 1 in a given year. Notice that years may not be balance for every firms. I would like to subtract sub-matrices according to the first column. For instance, for A(1:3,2:11) for 931142103:

 A(1:3,2:11)

ans =

    92    99     1     8    15    67    74    51    58    40
    98    80     7    14    16    73    55    57    64    41
     4    81    88    20    22    54    56    63    70    47 

Same as 459200101 (which would be A(4:7,2:11)) and A(8:10,2:11) for 37833100.

I get a sense that the code should like this:

  indices=find(A(:,1));
    obs=size(A(:,1));
    for i=1:obs,
        if i==indices(i ??)
            A{i}=A(??,2:11);
        end
    end

I have difficulties in indexing these complicated codes: 459200101 and 37833100 in order to gather them together. And how can I write the rows of my submatrix A{i}?

Thanks so much!

Upvotes: 3

Views: 351

Answers (3)

knedlsepp
knedlsepp

Reputation: 6084

If you don't mind the results internally not being ordered, you can use accumarray for this:

[~,~,I] = unique(A(:,1),'stable');
partitions = accumarray(I, 1:size(A,1), [], @(I){A(I,2:end)});

Upvotes: 2

Luis Mendo
Luis Mendo

Reputation: 112659

If values in column 1 always appear grouped (as in your example), you can use mat2cell as follows:

result = mat2cell(A, diff([0; find(diff(A(:,1))); size(A,1)]));

If they don't, just sort the rows of A according to column 1 before applying the above:

A = sortrows(A,1);
result = mat2cell(A, diff([0; find(diff(A(:,1))); size(A,1)]));

Upvotes: 3

Divakar
Divakar

Reputation: 221514

One approach with arrayfun -

%// Get unique entries from first column of A and keep the order 
%// with 'stable' option i.e. don't sort
unqA1 = unique(A(:,1),'stable') 

%// Use arrayfun to select each such submatrix and store as a cell 
%// in a cell array, which is the final output
outA = arrayfun(@(n) A(A(:,1)==unqA1(n),:),1:numel(unqA1),'Uni',0)

Or this -

[~,~,row_idx] = unique(A(:,1),'stable')
outA = arrayfun(@(n) A(row_idx==n,:),1:max(row_idx),'Uni',0)

Finally, you can verify results with a call to celldisp(outA)

Upvotes: 3

Related Questions