Divide matrix in to vectors using for-loop

So, i have a 12*X matrix where each row represents a month (jan-dec) and each column represents a year (could be any amount of years). I want to divide these into separate vectors of months and years using a for-loop.
This is my thought on how to do it but it doesnt work, basically i want to create variables for each year where y1 represents year 1, y2 represents year 2 and so on. I get a error message as soon as i try to run this and i think the problem is in the y(i) part which is supposed to make the different variables.
for i=1:length(x)
y(i)=x(:, i);
end

1 Comment

Creating several variables from one matrix = a very bad idea.
In all likelyhood, even splitting the matrix into a cell array or similar is also a bad idea. If you're trying to obtain statistics per month/year/whatever keeping the data together in the matrix would be much simpler. Tools like findgroups and splitapply can let you get monthtly/annually/etc. stats.

Sign in to comment.

 Accepted Answer

OCDER
OCDER on 21 Sep 2017
Edited: OCDER on 21 Sep 2017
Almost had it right. Use cell instead of y1, y2, y3, etc. Your "y1" can be accessed as y{1}. This is much simpler than naming many variables y1, y2, etc.
Also, use size(x, 2) instead of length(x) because length(x) takes the larger of the dimension of x. Ex: if x = 12x1 matrix, length (x) = 12. if x = 12x100 matrix, length(x) = 100.
for i = 1:size(x, 2)
y{i} = x(:, i);
end

6 Comments

Thank you very much! Is it possible to do this but name the variables jan, feb, ... , dec (easy to understand) or should i just name them m{1}, m{2}, ... ,m{12}?
While this is the correct way to do what is asked. I'm fairly certain that the question asked is the wrong one. It's most likely that Olle wants to compute monthly/yearly/something statistics in which case, splitting the matrix will only make it more difficult.
Hi Olle, Guillaume does have a good point. Do you have to do split this matrix? There are ways to directly access month and year by row and column. But I guess that'll depend on what you want to do with the data.
If you want to access a month by name instead of by integer, consider using a containersMap, or enumeration, or nonscalar structure with field names as month names and values as integer 1 to 12. Or you could use tables .
Download the Month.m enumeration class attached here, and save it to your working directory. Now, Month.jan is the same as 1, Month.feb is the same as 2. You can access 1st row, 1st year in the matrix x as
x(Month.jan, 1)
x(1, 1) %same thing
But if you split x into cell array y, then you'll have to do this:
y{1}(Month.jan)
y{1}(1) %same thing
I don't recommend splitting your data further by month name though. The good thing about splitting by year is that you can use cellfun to do some operation by year.
Also read about differences between matrix, cell, structure, and tables for storing data before settling on the data structure. Hope this helps!
Hmm, maybe i dont need to split the matrix. The values in my matrix is the monthly developement of the stock market. My final result is a table displayed in the command window which shows the average developement for each month/year and it shall also mark the best and worst developement.
I think i can do this by a version of this code which i stumbeled uppon while searching information about the size function:
LastName = {'Smith';'Johnson';'Williams';'Jones';'Brown'};
Age = [38;43;38;40;49];
Height = [71;69;64;67;64];
Weight = [176;163;131;133;119];
BloodPressure = [124 93; 109 77; 125 83; 117 75; 122 80];
A = table(Age,Height,Weight,BloodPressure,'RowNames',LastName)
The problem is that i dont always know how long the matrix is and my code needs to work for all types. I will try to do this without splitting the matrix and come back to you tomorrow.
Thanks for your help, much appreciated!
You're welcome!
"maybe i dont need to split the matrix"
Splitting the matrix will almost certainly be the wrong approach. Data should always be kept together as much as possible, because this actually makes processing it much easier. You can easily perform all sorts of numeric and statistical calculations on one array of data, but this will become a nightmare to do on lots of separate little arrays, even if they are split into a cell array.
Guillaume's answer shows a much better approach.

Sign in to comment.

More Answers (1)

"The values in my matrix is the monthly developement of the stock market. My final result is a table displayed in the command window which shows the average developement for each month/year and it shall also mark the best and worst developement".
In which case, splitting the matrix is the wrong way to approach this:
%build demo table
date = datetime + (0:-4:-800)';
stock = randi([0 100], size(date));
dailystock = table(date, stock); %note that table is ordered here. It doesn't even have to be
%compute monthly average min and max:
[bin, bindates] = discretize(dailystock.date, 'month');
[daterow, ~, group] = unique(bin);
months = bindates(daterow)';
months.Format = 'MM/yyyy';
monthlystock = table(months, ...
splitapply(@mean, dailystock.stock, group), ...
splitapply(@max, dailystock.stock, group), ...
splitapply(@min, dailystock.stock, group), ...
'VariableNames', {'month', 'monthly_mean', 'monthly_max', 'monthly_min'})

Asked:

on 21 Sep 2017

Commented:

on 22 Sep 2017

Community Treasure Hunt

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

Start Hunting!