Parse text file in MATLAB - matlab

I am parsing multiple text files in MATLAB and each time I store the result in the main array, but the problem that the data haven't the same size!
example:
t(i,:) = x;
% x data array from file i
ex:
t(1,:) = [ 5 4 3 2 1];
t(2,:) = [ 10 9 8 7 6 5];
t(3,:) = [ 11 12 13 14];
the size of x's is different, how i can store such these data (dynamic size) in the array!
Thanks,

you can store it in a cell array like this:
t{1} = [ 5 4 3 2 1];
t{2} = [ 10 9 8 7 6 5];
t{3} = [ 11 12 13 14];
and use them like this:
>> t(1)
ans =
[1x5 double]
>> t{2}
ans =
10 9 8 7 6 5
>> t
t =
[1x5 double] [1x6 double] [1x4 double]
>> t{:}
ans =
5 4 3 2 1
ans =
10 9 8 7 6 5
ans =
11 12 13 14
>> t{2}(1,2)
ans =
9
>> t{2}(1,2:end)
ans =
9 8 7 6 5

You can use a cell array to hold numeric arrays of various sizes. For instance
rows_cell = {};
rows_cell{1} = [ 5 4 3 2 1];
rows_cell{2} = [ 10 9 8 7 6 5];
rows_cell{3} = [ 11 12 13 14];
To access data:
rows_cell{2}(1,2)
ans =
9
rows_cell{3}(1,4)
ans =
14

Related

Reshaping vector to n-d matrix in row-wise order

I'm trying to convert a vector into a 3d matrix in a row-wise manner.
For example, my vector is:
a = 1:18;
and I'd like to convert this to a 2x3x3 matrix:
b(:,:,1) = [1 2 3; 4 5 6];
b(:,:,2) = [7 8 9; 10 11 12];
b(:,:,3) = [13 14 15; 16 17 18];
but the reshape function (i.e. reshape(a, 2,3,3)) arranges the elements in a column-wise fashion as:
val(:,:,1) =
1 3 5
2 4 6
val(:,:,2) =
7 9 11
8 10 12
val(:,:,3) =
13 15 17
14 16 18
How can I obtain the matrix b from vector a?
Use combination of reshape and permute.
b = permute(reshape(a,3,2,3),[2 1 3]);
b(:,:,1) =
1 2 3
4 5 6
b(:,:,2) =
7 8 9
10 11 12
b(:,:,3) =
13 14 15
16 17 18
I found a (or the) solution:
b = permute(reshape(reshape(a,3,[])',2,3,[]), [1,3,2])
b(:,:,1) =
1 2 3
4 5 6
b(:,:,2) =
7 8 9
10 11 12
b(:,:,3) =
13 14 15
16 17 18

Stacking matrices from a cell array on top of one another (MATLAB)

I have a cell array, with each cell containing a 3 column matrix.
How can I stack all of these matrices together, so that there are 3 very long columns of data?
I know I could do:
stacked_matrix = [cellArray{1,1} ; cellArray{1,2} ; cellArray{1,N}];
but I want to avoid manually writing everything out because the cell array is 1x40
You can achieve this using cat along the first dimension like this:
cat(1,cellArray{:})
Let's test it:
>> cellArray{1} = [ 1 2 3];
>> cellArray{2} = [ 4 5 6];
>> cellArray{3} = [ 7 8 9];
>> cellArray{4} = [10 11 12];
>> stacked_matrix = cat(1,cellArray{:})
stacked_matrix =
1 2 3
4 5 6
7 8 9
10 11 12
You can also use vertcat as well:
out = vertcat(cellArray{:});
However, doing vertcat is essentially syntactic sugar for cat(1,cellArray{:}) as per Matt's answer.
To test:
cellArray{1} = [ 1 2 3];
cellArray{2} = [ 4 5 6];
cellArray{3} = [ 7 8 9];
cellArray{4} = [10 11 12];
out = vertcat(cellArray{:});
... and we get:
out =
1 2 3
4 5 6
7 8 9
10 11 12

How to combine matrix of different size in a cell array into a matrix in MATLAB

Similarly to How to combine vectors of different length in a cell array into matrix in MATLAB I would like to combine matrix having different dimension, stored in a cell array, into a matrix having zeros instead of the empty spaces. Specifically, I have a cell array {1,3} having 3 matrix of size (3,3) (4,3) (4,3):
A={[1 2 3; 4 5 6; 7 8 9] [1 2 3; 4 5 6; 7 8 9; 9 9 9] [1 2 3; 4 5 6; 7 8 9; 4 4 4]}
and I would like to obtain something like:
B =
1 2 3 1 2 3 1 2 3
4 5 6 4 5 6 4 5 6
7 8 9 7 8 9 7 8 9
0 0 0 9 9 9 4 4 4
I tried using cellfun and cell2mat but I do not figure out how to do this. Thanks.
Even if other answers are good, I'd like to submit mine, using cellfun.
l = max(cellfun(#(x) length(x),A))
B = cell2mat(cellfun(#(x) [x;zeros(l-length(x),3)], A, 'UniformOutput', 0));
Using bsxfun's masking capability -
%// Convert A to 1D array
A1d = cellfun(#(x) x(:).',A,'Uni',0) %//'
%// Get dimensions of A cells
nrows = cellfun('size', A, 1)
ncols = cellfun('size', A, 2)
%// Create a mask of valid positions in output numeric array, where each of
%// those numeric values from A would be put
max_nrows = max(nrows)
mask = bsxfun(#le,[1:max_nrows]',repelem(nrows,ncols)) %//'
%// Setup output array and put A values into its masked positions
B = zeros(max_nrows,sum(ncols))
B(mask) = [A1d{:}]
Sample run
Input -
A={[1 2 3 5 6; 7 8 9 3 8] [1 2 3; 4 5 6; 7 8 9; 9 9 9] [1 2 3; 4 5 6; 7 8 9; 4 4 4]}
Output -
B =
1 2 3 5 6 1 2 3 1 2 3
7 8 9 3 8 4 5 6 4 5 6
0 0 0 0 0 7 8 9 7 8 9
0 0 0 0 0 9 9 9 4 4 4
I would be surprised if this is possible in one or a few lines. You will probably have to do some looping yourself. The following achieves what you want in the specific case of incompatible first dimension lengths:
A={[1 2 3; 4 5 6; 7 8 9] [1 2 3; 4 5 6; 7 8 9; 9 9 9] [1 2 3; 4 5 6; 7 8 9; 4 4 4]}
maxsize = max(cellfun(#(x) size(x, 1), A));
B = A;
for k = 1:numel(B)
if size(B{k}, 1) < maxsize
tmp = B{k};
B{k} = zeros(maxsize, size(tmp,1));
B{k}(1:size(tmp,1),1:size(tmp,2)) = tmp;
end
end
B = cat(2, B{:});
Now B is:
B =
1 2 3 1 2 3 1 2 3
4 5 6 4 5 6 4 5 6
7 8 9 7 8 9 7 8 9
0 0 0 9 9 9 4 4 4
I would do it using a good-old for loop, which is quite intuitive I think.
Here is the commented code:
clc;clear var
A={[1 2 3; 4 5 6; 7 8 9] [1 2 3; 4 5 6; 7 8 9; 9 9 9] [1 2 3; 4 5 6; 7 8 9; 4 4 4]};
%// Find the maximum rows and column # to initialize the output array.
MaxRow = max(cell2mat(cellfun(#(x) size(x,1),A,'Uni',0)));
SumCol = sum(cell2mat(cellfun(#(x) size(x,2),A,'Uni',0)));
B = zeros(MaxRow,SumCol);
%// Create a counter to keep track of the current columns to fill
ColumnCounter = 1;
for k = 1:numel(A)
%// Get the # of rows and columns for each cell from A
NumRows = size(A{k},1);
NumCols = size(A{k},2);
%// Fill the array
B(1:NumRows,ColumnCounter:ColumnCounter+NumCols-1) = A{k};
%// Update the counter
ColumnCounter = ColumnCounter+NumCols;
end
disp(B)
Output:
B =
1 2 3 1 2 3 1 2 3
4 5 6 4 5 6 4 5 6
7 8 9 7 8 9 7 8 9
0 0 0 9 9 9 4 4 4
[max_row , max_col] = max( size(A{1}) , size(A{2}) , size(A{3}) );
A{1}(end:max_row , end:max_col)=0;
A{2}(end:max_row , end:max_col)=0;
A{3}(end:max_row , end:max_col)=0;
B=[A{1} A{2} A{3}];
for this specific problem, simply this will do:
B=cat(1,A{:});
or what I often just give a try for 2D cells, and works for your example as well:
B=cell2mat(A');
if you literally don't give a f* what dimension it will be cut in (and you're exceedingly lazy): put the same into a try-catch-block and loop over some dims as below.
function A=cat_any(A)
for dims=1:10% who needs more than 10 dims? ... otherwise replace 10 with: max(cellfun(#ndims,in),[],'all')
try, A=cat(dims,A{:}); end
if ~iscell(A), return A; end
end
disp('Couldn''t cat!') %if we can't cat, tell the user
end
Beware, this might lead to unexpected results ... but in most cases simply just worked for me.

How can i store results from a loop in a matrix?

I have the following loop
x = [1 2 3 4 5;4 5 6 8 9;8 7 6 3 1;5 6 7 9 1;6 4 2 9 6]
y=[10 30 24 35 40]'
one=[]
for i=1:5
a=i;
ind=[a]
one=x(:,[i])
[b_LS, sigma_b_LS, s_LS] = lscov(one,y)
s = s_LS
aicx1=size(one,1)*log(s)+2*size(one,2)
end
I want to store result as :
A=[ind;aicx1] for example A=[1 2 3 4 5; 26 34 24 325]
You could add at the end of the loop:
x = [1 2 3 4 5; 4 5 6 8 9; 8 7 6 3 1; 5 6 7 9 1; 6 4 2 9 6];
y = [10 30 24 35 40]';
one=[];
for ii=1:5
one = x(:,ii);
[b_LS, sigma_b_LS, s_LS] = lscov(one,y);
s = s_LS;
aicx1 = size(one,1) * log(s) + 2 * size(one,2);
%% Add this
A(1,ii) = ii;
A(2,ii) = aicx1;
end
Notes
Avoid using i or j as variables since they are used for complex numbers
Add an ; at the end of the sentence if you don't want/need the values to appear in the command window

Reading data file with rows of variable sizes

I have a data file containing rows of variable sizes:
16 54 1 -3 5
15 5
1 9 10 5
How can I load it into a cell array data so that
data{1} = [16 54 1 -3 5];
data{2} = [15 5];
data{3} = [1 9 10 5];
?
Let data.txt contains
16 54 1 -3 5
15 5
1 9 10 5
You can read it into a cell array data with the following:
fid = fopen('datatest.txt');
allData = textscan(fid,'%s','Delimiter','\n');
data = cellfun(#str2num, allData{1}, 'UniformOutput', false);
fclose(fid);
>> data =
ans =
[1x5 double]
[1x2 double]
[1x4 double]
>> data{1}
ans =
16 54 1 -3 5
You can try impordata appproach that is short and concise -
%// Assuming filepath1 is the path to your file
data = cellfun(#str2num,importdata(filepath1,'%s'),'uni',0)
You can visualize the data, using celldisp tool that displays contents of a cell array, like this - celldisp(data). The output would be -
data{1} =
16 54 1 -3 5
data{2} =
15 5
data{3} =
1 9 10 5