I have a <1 x 29> cell array. Within each cell there is a <310x2000 double> matrix. Because of memory issues I would like to break these matrices up into smaller "chunks" (let's say approx. 5 x 2000 each) starting at row 4 and ending at row 309.
My data is therefore stored in the format of data{i}(j,:) where i refers to the cell number, and j refers to the desired row.
I created a matrix (let's call it A) in which each column gives me the values of the rows I want in each "chunk"
4 10 15 20 25
5 11 16 21 26
6 12 17 22 27 ...
7 13 18 23 28
8 14 19 24 29
For example, matrix 1 will include rows 4, 5, 6, 7 and 8.
nCells refers to the number of cells I have (29) & nCol refers to the number of columns in matrix A. Therefore:
for i = 1:nCells
for k = 1:nCol
for j = A(:,k)
B{i,k}(j,:) = [data{i}(j,:)];
end
end
end
Unfortunately this gives me the following error:
??? Error using ==> horzcat
CAT arguments dimensions are not consistent.
I really appreciate it if someone could tell me what the problem is or/ESPECIALLY if there's a much better way of going about doing this because I run into memory problems:
??? Out of memory. Type HELP MEMORY for your options.
First, the error you are getting is a result of how for loop indices are taken out of an array. In your third nested loop, you are setting j to a column vector. If you replaced this with A(:,k)', then it would probably work. See the following demonstration:
>> for i=([1;2;3;4]), disp(['i=' int2str(i)]); end;
??? Error using ==> horzcat
CAT arguments dimensions are not consistent.
>> for i=([1,2,3,4]), disp(['i=' int2str(i)]); end;
i=1
i=2
i=3
i=4
Second, you might want to do this a different way. My first instinct is to make a function such as this:
>> splitcell = #(C,range)(cellfun( #(X)(X(range,:)), C, 'UniformOutput', false) )
This uses the excellent cellfun command to call a function on each element of a cell array. Here, we are using matlab's anonymous function syntax (the # part) to make a function that takes in a matrix and slices it with a given range. You can make splitcell a normal function in its own m-file, I just used # here for compactness. splitcell has the following usage:
>> data = cell(1,5);
>> X = [1,2,3,4;5,6,7,8;9,10,11,12;13,14,15,16]
X =
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
>> for i=1:5, data{i} = (X+i*ones(4)); end;
>> data{1:2}
ans =
2 3 4 5
6 7 8 9
10 11 12 13
14 15 16 17
ans =
3 4 5 6
7 8 9 10
11 12 13 14
15 16 17 18
>> data2 = splitcell(data,3:4)
data2 =
[2x4 double] [2x4 double] [2x4 double] [2x4 double] [2x4 double]
>> data2{1:2}
ans =
10 11 12 13
14 15 16 17
ans =
11 12 13 14
15 16 17 18
Related
I have a matrix A in Matlab of dimension Nx(N-1), e.g.
N=5;
A=[1 2 3 4;
5 6 7 8;
9 10 11 12;
13 14 15 16;
17 18 19 20];
I want to rearrange the elements of A in a certain way. Specifically I want to create a matrix B of dimension (N-1)xN such that:
for i=1,...,N,
B(:,i) collects
1) the first i-1 elements of the i-1th column of A and
2) the last N-i elements of the ith column of A.
Notice that for i=1 the i-1th column of A does not exist and therefore 1) is skipped; similarly, for i=N theith column of A does not exist and therefore 2) is skipped.
In the example above
B=[5 1 2 3 4
9 10 6 7 8
13 14 15 11 12
17 18 19 20 16];
This code does what I want. I am asking your help to vectorise it in an efficient way.
B=zeros(N-1,N);
for i=1:N
if i>1 && i<N
step1=A(1:i-1,i-1);
step2=A(i+1:N,i);
B(:,i)=[step1;step2];
elseif i==1
B(:,i)=A(i+1:N,i);
elseif i==N
B(:,i)=A(1:i-1,i-1);
end
end
Extract the lower and upper triangular matrices of A. Then reassemble them with a "diagonal shift":
u = triu(A);
l = tril(A,-1);
B = padarray(u(1:end-1,:),[0 1],'pre') + padarray(l(2:end,:),[0 1],'post');
Another valid approach using logical indexing combined with tril and triu:
B = zeros(size(A'));
B(tril(true(size(B)))) = A(tril(true(size(A)), -1));
B(triu(true(size(B)), 1)) = A(triu(true(size(A))));
Result:
>> B
B =
5 1 2 3 4
9 10 6 7 8
13 14 15 11 12
17 18 19 20 16
I am trying to write three different arrays into 3 columns in a csv file. This what I have tried :
str = 'This is the matrix: ' ;
a= [1 2 3 4 5 6 ]';
csvwrite('C:\Users\ganesh\Desktop\data.csv', a);
b= [11 12 13 14 15 16]';
csvwrite('C:\Users\ganesh\Desktop\data.csv', b, 1, 0);
c= [21 22 23 24 25 26]';
csvwrite('C:\Users\ganesh\Desktop\data.csv', c, 2, 0);
But it does not work. Only last data is coming that too in a row. I have tried to put offset for columns.
Did I made a mistake somewhere ? ALso is there a way I can write these data in a single function call , rather than calling three time as shown here.
You should put your data in a matrix:
m = [1 2 3 4 5 6
11 12 13 14 15 16
21 22 23 24 25 26];
csvwrite('data.csv', m);
I have a 2 dimensional matrix and I want to get the data along a particular line. Similar to what 'Slice' does to a 3D matrix. Is there a a way to do a similar thing on a 2D matrix.
Thanks in advance.
Extracting all values of a column or a line:
>> M = magic(4)
M =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
>> particular_row = 3;
>> M(particular_row,:)
ans =
9 7 6 12
>> particular_column = 2;
>> M(:,particular_column)
ans =
2
11
7
14
Extracting values along a diagonal:
What if I want to get the data along any direction say along a line joining matrix index (1,1) to (4,4) of a 5x5 matrix?
I'd use linear indexing and the sub2ind function for this task. Demo:
(1,1) to (4,4):
>> M = magic(5)
M =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
>> M(sub2ind(size(M), 1:4, 1:4))
ans =
17 5 13 21
Another example: (1,2) to (3,4):
M(sub2ind(size(M), 1:3, 2:4))
ans =
24 7 20
Having the values of time sequence, I would like to reshape it into a nx4 matrix [X y], for the purpose of using these values as input and output values for machine learning algorithm.
X(i) is a 1x3 input vector and y is output scalar value.
The algorithm takes as an input every 2nd sequence value (3 values) in order to predict the 4th value.
To give a practical example, let's say we have a sequence
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
The [X y] matrix should be the following:
[1 3 5 7; 2 4 6 8; 9 11 13 15; 10 12 14 16]
To get every second row I wrote the following code:
vec1 = timeSeries(1:2:end);
XyVec1 = reshape(vec1,4,[])'
similarly it could be written to get even numbers:
vec2 = timeSeries(2:2:end);
XyVec2 = reshape(vec2,5,[])'
The thing that I don't know how to do is to interleave matrix vec1 and vec2 rows to get
[vec(1,:); vec2(1,:);vec1(2,:), vec2(2,:)...]
Does anyone know how to interleave the rows of two (or more) matrices?
Try
result = zeros(size(vec1,1)+size(vec2,1),size(vec1,2));
result(1:2:end,:) = vec1;
result(2:2:end,:) = vec2;
Reuse matlab indexing facilities ot insert elements in correct rows
Sample octave mock-up: http://ideone.com/RVgmYA
There is this one-liner option
result = kron(vec1, [1;0]) + kron(vec2, [0;1]);
However, #Joel Falcou is faster. Having set the input vectors as
vec1 = rand(1000,1000);
vec2 = -rand(1000,1000);
it gives
Elapsed time is 0.007620 seconds. (indexing)
Elapsed time is 0.054607 seconds. (kron)
Good luck :) figuring out what's going on with those reshape(), permutes():
a = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16];
reshape(permute(reshape(a,2,4,[]),[2,1,3]),4,[])'
the result
ans =
1 3 5 7
2 4 6 8
9 11 13 15
10 12 14 16
To interleave the vectors as mentioned in the end of your question you can use
reshape([vec1, vec2]', 4, [])'
for
vec1 =
1 3 5 7
9 11 13 15
vec2 =
2 4 6 8
10 12 14 16
it returns
>> reshape([vec1, vec2]', 4, [])'
ans =
1 3 5 7
2 4 6 8
9 11 13 15
10 12 14 16
I made a matrix in Matlab, say,
A = magic(5);
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
Now I found the indices I want using the find function as:
ind = find(A(:,5)>3 & A(:,4)>= 8);
ind =
1
2
3
Now if I want to get a subset of matrix A for those indices using B = A(ind) function, I only get the first column of the matrix:
B = A(ind)
B =
17
23
4
How can I get all the columns as subset??
Oops ... I got it
B = A(ind,:);