Reputation: 33
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
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
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
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