How can I split a matrix into N different parts?

44 次查看(过去 30 天)
I have a 120x30 matrix of data points, how can I split the matrix into nine equal parts of 400 data chunks and store them as separate matrices?
  2 个评论
Stephen23
Stephen23 2017-7-20
编辑:Stephen23 2017-7-20
"how can I split the matrix into nine equal parts of 400 data chunks and store them as separate matrices?"
While this is possible it would make your code slow, buggy, inefficient, hard to read, hard to debug, etc, etc. Here is what the MATLAB documentation says about magically creating variable names like that: "A frequent use of the eval function is to create sets of variables such as A1, A2, ..., An, but this approach does not use the array processing power of MATLAB and is not recommended. The preferred method is to store related data in a single array."
As you can read, the much better alternative is use one array and indexing. Indexing is simple, very efficient, neat, easy to read, easy to debug, etc, etc.
You can read more explanations and discussions here:
Just use indexing: simple, efficient, neat, easy to debug, easy to understand,... Or you could split the array into a cell array of numeric arrays: see mat2cell and num2cell.
Stephen23
Stephen23 2017-7-24
编辑:Stephen23 2017-7-24
Note to browsers of this thread: If you want to write fast, neat, efficient, and robust code then scroll down to Jan Simon's answer. It is not required to use slow and buggy code to solve this task.

请先登录,再进行评论。

采纳的回答

John BG
John BG 2017-7-20
编辑:John BG 2017-7-20
Hi matlabkid602
to split 120x30 matrix into chunks of 400 pixels, there are many different ways, like for instance selecting 400 random points and removing the just selected points from the matrix iterating until no points left, or using masks or patterns for similar elimination.
One can also sequentially pull strings of 400 pixels at a time, like Jan has concisely shown above, with a resulting cell.
For rectangular matrices, it is reasonable to aim at splitting the matrix into smaller rectangle chunks.
The following splits your 3600 points matrix into sub-rectangles of 400 points each
1.
loading example matrix
clear all;clc;close all
A=imread('001.jpg');
imshow(A)
2.
Scaling down to 120x30 pixels
the rulers are in pixels
.
.
3.
Simplifying to single RGB layer, made available in attached image 003.jpg
A=imread('003.jpg')
A=A(:,:,1);
fh=figure(1);imshow(A);ax=gca
fh.MenuBar='none'
fh.ToolBar='none'
fh.Position=[500 500 1440 360]
ax.OuterPosition=[0 0 1 1]
.
3.
Finding out how many rectangle chunks have 400 pixels area
L1=120 % x, horizontal
L2=30 % y, vertical
A0=400 % target area
K=L1*L2/A0 % how many equal area chunks, K is your N
x=[1:10]
y=[1:10]
[X,Y]=meshgrid(x,y)
L=(L1./X).*(L2./Y);
figure(4);S=surf(L)
.
N1=find(S.ZData==A0)'
% N1 =
% 9 23 81
It turns out vertical and horizontal slicing may also be possible
L(N1)
% =
% 400 400 400
% the slicing
a=X(N1)
% =
% 1 3 9
b=Y(N1)
% =
% 9 3 1
But since it's reasonable to assume that data points cannot be split, for the case pixels, the horizontal and vertical slicing cases a=1 b=9, a=9 a=1 have to be excluded.
Choosing the elements that are neither 1 or K
a=3;b=3
4.
Generating variable containing the rectangles
La=[1:L1/a:L1];
Lb=[L2:L2/b:L2];
D=zeros(L2/b,L1/a,K);
s=1
for j=1:1:b
for i=1:1:a
n2=[(j-1)*L2/b+[1:1:L2/b]]
n1=[(i-1)*L1/a+[1:1:L1/a]]
D(:,:,b*(j-1)+i)=A(n2,n1);
end
end
D=uint8(D) % for imshow to work correctly
close all;
for s=1:1:K
figure(s);imshow(D(:,:,s));
fh=figure(s);imshow(D(:,:,s));ax=gca
fh.MenuBar='none'
fh.ToolBar='none'
fh.Position=[500 500 480 120]
ax.OuterPosition=[0 0 1 1]
end
fh=figure(10)
for s=1:1:K
subplot(b,a,s);imshow(D(:,:,s))
end
.
5.
Dynamic generation of variables
Some people like the dynamic generation of variables with for instance command e evalin, some other people don't like such approach.
evalin is a very powerful command and I am using it here to generate the separate matrices you have asked for
.
str1=repmat('Chunk_',K,1) % building strings for evalin
N0=num2str(100+[1:1:K]');N0(:,1)=[]
N1=repmat('=D(:,:,',K,1)
N2=repmat(')',K,1)
str2=[str1 N0 N1 num2str([1:1:K]') N2]
for s=1:1:K % running evalin
L2=str2(s,:);
evalin('base',L2);
end
.
Now you have a list of smaller matrices containing the rectangular chunks
Chunk_01
Chunk_02
Chunk_03
Chunk_04
Chunk_05
Chunk_06
Chunk_07
Chunk_08
Chunk_09
if you find this answer useful would you please be so kind to consider marking my answer as Accepted Answer?
To any other reader, if you find this answer useful please consider clicking on the thumbs-up vote link
thanks in advance
John BG
  1 个评论
Jan
Jan 2017-7-22
编辑:Jan 2017-7-22
The shown code works in the command window only, because evalin('base') creates the variables in the Base-WorkSpace. Hundreds of threads in this forum explain the drawbacks of the dynamic creation of variables exhaustively. See Stephen's comment above.

请先登录,再进行评论。

更多回答(2 个)

Jan
Jan 2017-7-20
编辑:Jan 2017-7-22
Storing in separate matrices might be a bad idea. Why not using the matrix itself?
data = rand(120, 30);
data9 = reshape(data, [], 9);
dataC = cell(1, 9);
for iC = 1:9
dataC{iC} = data9(:, iC);
end
Here you get the different vectors as a cell array. But I'd prefer to work with data9: The i.th block is data9(:, i).
[EDITED] You can split the matrix to a 3x3 set uf submatrices efficiently without nested loops by:
sM = size(M);
c = reshape(M, sM(1) / 3, 3, sM(2) / 3, 3);
M33 = permute(reshape(c, 4, 3, 3, 3), [1, 3, 2, 4]);
M9 = reshape(M33, [4, 3, 9]);
Now the matrix is divived in 3 x 3 submatrices of the same size, which can be addressed by M9(:, :, i) with the index 1 to 9 or by using M33(:, :, x, y) with x and y going from 1 to 3.
This is much faster then nested loops.
  2 个评论
Kodavati Mahendra
Kodavati Mahendra 2018-1-17
编辑:Kodavati Mahendra 2018-1-17
regarding the edit you made, c has more than 4*3*3*3 elements.
sM = size(M);
M33 = permute(reshape(M,sM(1)/3,3,sM(2)/3,3),[1,3,2,4]);
M9 = reshape(M33, [sM(1)/3,sM(2)/3,9]);
Is this the correct code or did I misunderstand it?

请先登录,再进行评论。


Image Analyst
Image Analyst 2017-7-22
You didn't specify how you wanted the matrix split up, since neither 120 nor 30 is a multiple of 9. So I just made 9 vectors taking the data column by column from upper left to lower right. Try this:
data = rand(120,30); % Sample data
% Now split up into 9 row vectors.
m1 = data(1:1*400);
m2 = data(1*400+1 : 2*400);
m3 = data(2*400+1 : 3*400);
m4 = data(3*400+1 : 4*400);
m5 = data(4*400+1 : 5*400);
m6 = data(5*400+1 : 6*400);
m7 = data(6*400+1 : 7*400);
m8 = data(7*400+1 : 8*400);
m9 = data(8*400+1 : 9*400);
If those aren't the 9 arrays you were thinking of them clarify the location of where the elements for each matrix are supposed to come from.

类别

Help CenterFile Exchange 中查找有关 Programming 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by