Divide matrix in subgroups

Hello everyone, just a simple question : having a matrix X ,how can I divide the total number of columns in 24 subgroups and each subgroup give a number as variable name? Thanks.

 Accepted Answer

The mat2cell function will likely do what you want.
Note that assigning each matrix to a different variable is not advisable. Keep them as the cell array, and refer to them as elements of it, using subscripts.
Dividing a (9x9) matrix into 9 (3x3) matrices would work as:
A = randi(9, 9);
Adiv = mat2cell(A, [1 1 1]*3, [1 1 1]*3);
.

14 Comments

@Star Strider it works good because you know the number of rows and columns, but for example; in the case you don't know the number of rows, and you just want to divide the number of rows according to a vector time, in this case 24 hours. How could you do it?
I would need more information as to what your matrix contains, and how you want to divide it.
It is necessary to know all the dimensions of the matrix in order to use the mat2cell function.
Ok, I have a matrix (R) of size (249X1451), I need to divide the number of columns in 24. The matter is that normally I don’t know the number of columns, sometimes are more or sometimes are less this is aleatory, but always the number of columns fits into 24h because is the data for one day.
Here is an example of the way I cut the data, I know that for this especific case (:,1:151.1457) it means the first 2.5 hours(00:00 - 2:30). But sometimes that number of columns are no the same (1451) it changes and I have to recalculate the process when the matrix has another different number of columns. Thank you
P.S the number of rows is always equal.
smoothdata(((R(:,1:151.1457))),'movmedian',3,'omitnan');
I have no idea what is in the matrix, or how the columns are designated.
If the first row are time values, it might be possible to use findgroups or unique to label the columns by the hour value, and then mat2cell could divide them appropriately given the number of common hours in each group. That would require a bit of extra code, however would likely not be a significant problem.
If there is no such designation, then it would likely not be possible to divide the columns correctly.
it is a matrix (R) like the one is attached. size (249X1451) the time vector is (t) 24 hours, and the vector for altitude is (y) also both attached to this message.
This turned out to be much more straightforward than I anticipated:
L1 = load('Fercho_Sala R.mat');
L2 = load('Fercho_Sala t.mat');
L3 = load('Fercho_Sala y.mat'); % Not Required For This
R = L1.A;
t = L2.A;
t = datevec(t);
[Ut,ia,idx] = unique(t(:,4)); % Unique Hours
Counts = accumarray(idx, 1); % Items In Each Hour
C = mat2cell(R, size(R,1), Counts); % Cell Array Of Partitioned ‘R’ Matrix
producing:
C =
1×24 cell array
Columns 1 through 5
{249×60 double} {249×57 double} {249×60 double} {249×61 double} {249×60 double}
...
Columns 21 through 24
{249×61 double} {249×61 double} {249×60 double} {249×61 double}
This was easier to do with datevec and accumarray than with findgroups and splitapply, at least for me.
@Star Strider thank you so much for your help, this is the right answer !! :)
As always, my pleasure!
@Star Strider how can I modify the script in the case I'd like to use this for every 3 or 6 hours?
Interesting problem!
This works:
L1 = load('R.mat');
L2 = load('t.mat');
L3 = load('y.mat');
R = L1.A;
t = L2.A;
t = datevec(t);
[Ut,ia,idx] = unique(t(:,4)); % Unique Hours
Counts = accumarray(idx, 1); % Items In Each Hour
HoursGroup = 3; % Number Of Hours In Each Group
Countsmtx = reshape(Counts, HoursGroup, []); % Reshape ‘Counts’ Vector To Matrix
Counts = sum(Countsmtx); % Sum Columns To Get New ‘Groups’ Vector
C = mat2cell(R, size(R,1), Counts); % Cell Array Of Partitioned ‘R’ Matrix By ‘Groups’ Vector
It works by using reshape to create ‘Countsmtx’, and then sums the columns of the matrix to create a new ‘Counts’ vector.
Choose how you want to divide them with the ‘grouping’ variable ‘HoursGroup’ (here 3) that must be an integral divisor of 24 , so (1, 2, 3, 4, 6, 8, 12, 24). The code will fail for any other values.
@Star Strider that's the issue,, because normaly for this case it works good with an integral divisor of 24, however sometimes I just have to do it for every 30 minutes; in this case it will be a (0.5).
for the 30minutes option the easiest way is the one you provided before and I was wondering how I can divide each colum of the "C" (1X24) array, by the middle? Saying that this is just 30 minutes. Thanks.
Try this:
L1 = load('R.mat');
L2 = load('t.mat');
L3 = load('y.mat');
R = L1.A;
t = L2.A;
tdn = datevec(t); % Date Vectors
MinutesGroup = 30; % Number Of Minutes In Each Group
group = rem(tdn(:,5), MinutesGroup)==0; % Grouping Variable ‘Steps’
[Ut,ia,idx] = unique(cumsum(+group)); % Unique Groups
Counts = accumarray(idx, 1); % Items In Each Group
C = mat2cell(R, size(R,1), Counts); % Cell Array Of Partitioned ‘R’ Matrix By ‘Groups’ Vector
It took a few minutes to figure out how to do this, and make it as robust as possible. This should allow any integer value of ‘MinutesGroup’ between 1 and numel(t) to define the partitions. (I checked it a number of different values for ‘MinutesGroup’ using the time vector as datevec rows, and it partitions everything correctly, at least with the data set provided.)
It might be possible to do a similar analysis with retime, however you requested a way to partition the data, not analyse it, and this code does exactly that.
@Star Strider yes, analysis of data is another different thing, thanks a lot for your knowledge. :)
As always, my pleasure!

Sign in to comment.

More Answers (0)

Products

Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!