Matlab: how to write cell array of matrices to file - matlab

i have a cell of several matrices (all double and with the same dimension)
my_cell =
[172x15 double] [172x15 double] [172x15 double] [172x15 double]
I would to write the matrices on txt file side by side and tabulated, to obtain a .txt file with 172 rows and 60 columns (in this case)

use dlmwrite and cell2mat
mat = cell2mat(my_cell);
delimiter = ' '; % // used to separate two values in a row in the file
filename = 'test.txt';
dlmwrite(filename,mat,delimiter);

>> dlmwrite('file1.txt', [c{:}],'delimiter','\t','precision','%.5f')
or
>> dlmwrite('file2.txt', c(:)','delimiter','\t','precision','%.5f')
You have to choose a precision, otherwise you'll get non-uniform lines because of different numbers of decimal places.

Code
%// output_filepath is the name of your output text file
c1 = horzcat(my_cell{:})
datacell = mat2cell(c1,ones(1,size(c1,1)),ones(1,size(c1,2)))
dlmwrite(output_filepath,datacell,'\t'); %// a TAB delimiter is used

Related

How do I read comma separated doubles from text file into MATLAB?

I have a text file called Output.txt that looks like this:
0.000000,0.550147,0.884956
1.000000,0.532486,0.847458
2.000000,0.501333,0.800000
3.000000,0.466418,0.746269
4.000000,0.409492,0.662252
5.000000,0.327257,0.520833
6.000000,0.267376,0.425532
7.000000,0.188427,0.296736
8.000000,0.115824,0.180505
9.000000,0.062768,0.099108
I need to read in the three values separated by commas into MATLAB as 3 different vectors. They can be called anything but C1, C2, and C3 could work.
C1 would contain [0.000000,1.000000,2.000000, ...], C2 would contain [0.550147,0.532486,...] and C3 would contain the values in the third column [0.884956,0.847458,...].
I tried using the following but I'm having problems getting it to work correctly:
File = 'Output.txt';
f = fopen(File, 'r');
C = textscan(f, '%f%f%f', 'Delimiter', ',');
fclose(f);
This gives me a 1x3 Cell array C but each of the cells in C are 1x100 and do not contain the correct numbers.
You have a Comma Separated Value file, so you can simply use csvread to read in your matrix:
C = csvread('Output.txt');
where C now is a matrix containing all your values, which you can of course index through columns and rows. I'd recommend against creating the column vectors rather use C(:,1) for the first column etc.

splitting a character array into a cell array and matrix

I have a text file.
In the file is approx 20,000 rows of data. Each row has one column & contains 256 characters (which are all numbers).
I need to split each row into a cell array or matrix. So each 8 characters are "one piece" of information. I want to split the first 3 characters into a cell array and the next 5 characters into a double, then same again for the next 8 characters.
example
1653256719812345
myCellArray (1 x 2) myDoubleArray (1 x 2)
[165, 198] [32567, 12345]
What is the best way to do this?
Use textscan.
fid = fopen(MyFileName.txt);
data = textscan(fid, '%3d%5d', 'Delimiter', '');
fclose(fid);
testing:
% Test with string of 256 random digits that all happen to be 1:8 repeated 32 times
x = '1234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678';
>> y = textscan(x, '%3d%5d', 'Delimiter', '')
y =
[32x1 int32] [32x1 int32]
>> y{1}
ans =
123
123
123
123
...
I don't know the exact format of your files, so you may have to do this line-by-line within a loop (in which case you would get each line using fgetl and then replace fid in the textscan statement with the output from fgetl).
In general, whenever you find yourself having to read in data that was produced by FORTRAN code (fixed field width text files), textscan's 'Delimiter, '' and 'Whitespace', '' parameters are your friend.
Use regexp. If the file data.txt contains
1653256719812345
1563256719812345
1233256719812345
1463256719812345
Then the following MATLAB statements will read the numbers.
>> txt = fileread('data.txt') % Read entire file in txt
>> out = regexp(txt,'(\d{3})(\d{5})(\d{3})(\d{5})','tokens') % Match regex capturing groups
out =
{1x4 cell} {1x4 cell} {1x4 cell} {1x4 cell}
Each cell in out is a row from the file containing the parsed numbers as strings.You can use str2double to convert the numbers to a numeric data type in MATLAB
>> nums = cellfun(#str2double,out,'uni',0)
nums =
[1x4 double] [1x4 double] [1x4 double] [1x4 double]
Iterate over your rows one by one and run something like the following code.
k=int2str(1653256719812345);
> myCellArray{1}=k(1:3)
myCellArray =
'165'
>> mydoublearray(1)=str2num(k(4:9))
mydoublearray =
325671
If there's some formulaic pattern you should incorporate that instead of manually hard coding it.

cellarray to matrix in matlab

I want to import some data in an m file. So for I have managed to create a cell array of the data. I want to convert it into a matrix. I used cell2mat but I get an error. I'm new to Matlab, so I would like some help. Here is my complete code
fid = fopen('vessel-movements.csv');
C = textscan(fid, '%f %f %f %f %f %s %s %s', 'HeaderLines', 1, 'Delimiter', ',')
fclose(fid);
iscell(C)
T = cell2mat(C)
The answer I get is:
C =
Columns 1 through 4
[300744x1 double] [300744x1 double] [300744x1 double] [300744x1 double]
Columns 5 through 8
[300744x1 double] {300744x1 cell} {300744x1 cell} {300744x1 cell}
ans =
1
??? Error using ==> cell2mat at 46
All contents of the input cell array must be of the same data type.
Error in ==> test at 5
T = cell2mat(C)
My question is how I can do that? The data is in the following link vessel-movements.csv. It contains numbers, as ids and coordinates, and timestamps.
As the error message says:
All contents of the input cell array must be of the same data type.
Columns 6, 7 and 8 are chars (datestrings). It's not possible to convert them into a Matrix. Leave them in a cell.
You can transform only the numerical data into a matrix: data = cell2mat(C(:,1:5)). The three left columns have to be converted with datenum() into a numerical time to add it to data matrix.
When you've got >=R2013b, you can use as datatype a table like: data = readtable('vessel-movements.csv');
I assume you only want to convert the first five columns of C, which are the ones that contain numeric data. You can use cell2mat as follows:
M = cell2mat(C(:,1:5));
or equivalently
M = [C{:,1:5}];
The main difference between a matrix and a cell array (in MATLAB parlance) is that a matrix holds elements of the same type and size, while a cell array holds elements of different types and sizes.
You read numbers and strings. The numbers do have the same type and size (double, 1×1) while the strings are different (they're all char type, but usually different sizes).
To group your numeric data, you must select only the numeric elements of your cell array:
N = horzcat(C{1:5});
while for the strings you should keep the cell array structure:
S = horzcat(C{6:8});
Later edit: Since you admit that you're new to MATLAB, I'm going to make a general recommendation: every time you see a function that you don't know what it does—or behaves unexpectedly from your point of view—mark its name and press F1. The MATLAB documentation is quite comprehensive, and contains also lots of examples depicting the typical uses for that function.

Exporting blank values into a .txt file - MATLAB

I'm currently trying to export multiple matrices of unequal lengths into a delimited .txt file thus I have been padding the shorter matrices with 0's such that dlmwrite can use horzcat without error:
dlmwrite(filename{1},[a,b],'delimiter','\t')
However ideally I do not want the zeroes to appear in the .txt file itself - but rather the entries are left blank.
Currently the .txt file looks like this:
55875 3.1043e+05
56807 3.3361e+05
57760 3.8235e+05
58823 4.2869e+05
59913 4.3349e+05
60887 0
61825 0
62785 0
63942 0
65159 0
66304 0
67509 0
68683 0
69736 0
70782 0
But I want it to look like this:
55875 3.1043e+05
56807 3.3361e+05
57760 3.8235e+05
58823 4.2869e+05
59913 4.3349e+05
60887
61825
62785
63942
65159
66304
67509
68683
69736
70782
Is there anyway I can do this? Is there an alternative to dlmwrite which will mean I do not need to have matrices of equal lengths?
If a is always longer than b you could split vector a into two vectors of same length as vector b and the rest:
a = [1 2 3 4 5 6 7 8]';
b = [9 8 7 ]';
len = numel(b);
dlmwrite( 'foobar.txt', [a(1:len), b ], 'delimiter', '\t' );
dlmwrite( 'foobar.txt', a(len+1:end), 'delimiter', '\t', '-append');
You can read in the numeric data and convert to string and then add proper whitespaces to have the final output as string based cell array, which you can easily write into the output text file.
Stage 1: Get the cell of strings corresponding to the numeric data from column vector inputs a, b, c and so on -
%// Concatenate all arrays into a cell array with numeric data
A = [{a} {b} {c}] %// Edit this to add more columns
%// Create a "regular" 2D shaped cell array to store the cells from A
lens = cellfun('length',A)
max_lens = max(lens)
A_reg = cell(max_lens,numel(lens))
A_reg(:) = {''}
A_reg(bsxfun(#le,[1:max_lens]',lens)) = cellstr(num2str(vertcat(A{:}))) %//'
%// Create a char array that has string data from input arrays as strings
wsp = repmat({' '},max_lens,1) %// Create whitespace cell array
out_char = [];
for iter = 1:numel(A)
out_char = [out_char char(A_reg(:,iter)) char(wsp)]
end
out_cell = cellstr(out_char)
Stage 2: Now, that you have out_cell as the cell array that has the strings to be written to the text file, you have two options next for the writing operation itself.
Option 1 -
dlmwrite('results.txt',out_cell(:),'delimiter','')
Option 2 -
outfile = 'results.txt';
fid = fopen(outfile,'w');
for row = 1:numel(out_cell)
fprintf(fid,'%s\n',out_cell{row});
end
fclose(fid);

How to import data with row and column headers

I want to import data from a text file with row and column headers, and it in a matrix. For instance, the input file looks as follows:
data c1 c2 c3 c4
r1 1 2 3 4
r2 5 6 7 8
Also, is it possible to access the row and column names with the corresponding data element? And is it possible to modify that based on the result of operations?
Thanks in advance.
I would use textscan with an extra %*s in the format string to gobble up the first header column in each row. The first header row should be used to count the number of columns, in case it is unknown:
fid = fopen('input.txt'); %// Open the input file
%// Read the first header row and calculate the number of columns in the file
C = textscan(fid, '%s', 1, 'Delimiter', '\n', 'MultipleDelimsAsOne', true);
cols = numel(regexp(C{1}{1}, '\s*\w+'));
%// Read the rest of the rows and store the data values in a matrix
C = textscan(fid, ['%*s', repmat('%f', 1, cols - 1)]);
A = [C{:}]; %// Store the data in a matrix
fclose(fid); %// Close the input file
The data is stored in matrix A.
From the documentation on readtable see http://www.mathworks.com/help/matlab/ref/readtable.html
T = readtable(filename, 'ReadVariableNames', true) if the first column has the headers
or
T = readtable(filename, 'ReadRowNames', true) if the first row has the headers
You may also be interested into the 'HeaderLines' name-value pair if you'd like to drop more than just the first line.
You could use importdata, for example, supposing the delimiter is "tab",
rawdata = importdata(filename, '\t');
row_names = rawdata.textdata(2:end,1);
col_names = rawdata.textdata(1, 2:end);
data_mat = rawdata.data;
The row_names and col_names are cell array types. If you like them to be one string delimited by \t or ,, etc., you could use strjoin on them.