I'm trying to read data from a .txt file. The sample data is given below. I need an algorithm to read just M-N row numbers. While I can use while/for loops, I'm afraid that it might become very slow. Thanks!
a=[ 1 6 11 16 ;
2 7 12 17 ;
3 8 13 18 ;
4 9 14 19 ;
5 10 15 20] ; % data is in Test.txt -->
% fid = fopen('Test.txt');
% a=a.'; fprintf(fid, '%.3f\t%.3f\t%.3f\t%.3f\r\n', a(:)) ;
fid = fopen('Test.txt') ;
AnsMat = fscanf(fid, '%f %f %f %f')
AnsMat = [2 7 12 17 ; 3 8 13 18] ; % Read row-numbers 2 to 4 this time
You could try textscan which allows a HeaderLines parameter telling matlab how many lines to skip.
For example to read lines n (=2) to m(=4), you could do:
fid = fopen('Test.txt');
C = textscan(fid,'%f %f %f %f\n',m-n+1,'HeaderLines',n-1);
fclose(fid);
This does return the data as a cell array though so you have to convert it:
AnsMat = cell2mat(C);
If your data were in csv format instead of text format, you could use the command:
text=csvread('yourfile.csv',1,1,[1 1 m n])
Obviously, if your data is only available in text format, it would be just as much work to manually convert it as it would be to use the textscan option, but if your text file is being generated elsewhere where you would have control over the output format, this may streamline the process.
Related
I need to save a 3D matrix in a text file that will be loaded in Matlab (which I don't master). My first idea was to do it with a .csv like this, (consider a 3x3x3 matrix):
row 1: v[0][0][0],v[0][0][1] ,v[0][0][2]
row 2: v[0][1][0],v[0][1][1] ,v[0][1][2]
row 3: v[0][2][0],v[0][2][1] ,v[0][2][2]
row4: v[1][0][0],v[1][0][1] ,v[1][0][2]
...
Like this, I must inform the user separately about the number of x an y dimensions. Not too clean, but not a big drama.
My question is, how could I load and plot in Matlab a dataset like this? Values are 1/0.
Is there any smarter way of doing this. I am exporting from Java.
Thanks!
I can't think of a way that you can omit storing the dimensions of the matrix (at least two of them should be mentioned). But when it comes to storing values in a file, I suggest that you do not bother to even write them in tabular format. All you need to know about MATLAB is the order of elements in a matrix. Take a look at this example:
%% create a 3d matrix
% a = 1+randi(5);
% b = 1+randi(5);
% c = 1+randi(5);
a = 2; b = 3; c = 4;
M = reshape(1:a*b*c, a, b, c)
This is how the matrix looks like:
M(:,:,1) =
1 3 5
2 4 6
M(:,:,2) =
7 9 11
8 10 12
M(:,:,3) =
13 15 17
14 16 18
M(:,:,4) =
19 21 23
20 22 24
Now let's write it in a text file:
%% writing matrix in the text file,
% translate it to your target language
fid = fopen('matrix.txt', 'w');
fprintf(fid, '%d,%d,%d\n', a, b, c);
for k=1:c
for j=1:b
for i=1:a
fprintf(fid, '%-.8g\n', M(i, j, k));
end
end
end
fclose(fid);
This is the contents of the file:
2,3,4
1
2
3
4
...
21
22
23
24
Now, to read the file:
%% read the file back in MATLAB
fid = fopen('matrix.txt', 'r');
sz = str2num(fscanf(fid, '%s\n', 1)); % read dimensions
M2 = reshape(fscanf(fid, '%f\n', inf), sz); % read values
fclose(fid);
%% test the imported matrix
disp(sz)
if all(all(all(M == M2)))
disp('OK')
else
disp('Test failed.')
end
I have a problem with my code in matlab.
I have a matrix C (make reshape as a vector) and I want to save several C vectors to one file. This is my code
wynik = reshape(C',1,[]);
fileID = fopen('Desktop\test.txt','r');
fileID_out = fopen('Desktop\test_out.txt','r');
fprintf(fileID, '%d \r', wynik);
fprintf(fileID, '\n');
fprintf(fileID_out, ' %d \r\n', 2);
end
I made a loop at the begin so in a console I have for example 2 different matrix, but using this code it overwrite my file and I save only the last one vector. I would like to have sth like this (shorter example)
A = [ 1 2 3; 4 5 6 ] ( first loop)
A = [7 8 9; 1 2 3 ] ( second loop)
In my file(with spaces between values and with \n on the end of line) :
1 2 3 4 5 6
7 8 9 1 2 3
The example in your question is quite unclear because you ask about saving data but all your file opening instructions use only reading permissions.
I'll give you an example which works for your 2nd (shorter) example because it is clearer what you are trying to achieve.
I strongly recommend to read the documentation for:
fopen, and particularly the usage of the parameter permission.
fprintf the the parameter formatSpec will be useful.
Armed with that documentation, you will realise that to write to an existing file already containing data is called append to the file. So for your usage: The first time you create the file, open it with the permission 'w'. For all the other time you want to add (=append) something to the file, open it with the permission 'a', then write normally to it.
Your second example in code:
%% Initial data
A = [1,2,3;4,5,6];
%% prepare format specifier for a complete line
nElem = numel(A) ;
baseformat = '%d ' ; % base number format
writeFormat = repmat( baseformat , 1 , nElem ) ; % replicated "nElem" times
writeFormat = [writeFormat(1:end-1) '\n'] ; % remove last trailing space and replace by newline
% => now writeFormat = "%d %d %d %d %d %d\n"
%% Open the file the first time to write the first line
% permission 'w' => Open or create new file for writing. Discard existing contents, if any.
fidout = fopen('myfileout.txt', 'w') ;
fprintf( fidout , writeFormat , A(:) ) ;
fclose(fidout) ;
%% Now let's write 5 additional lines
for iLine=1:5
% simulate a different matrix [A]
A = A + nElem ; % A will continue counting
% permission 'a' => Open or create new file for writing. Append data to the end of the file.
fidout = fopen('myfileout.txt', 'a') ;
fprintf( fidout , writeFormat , A(:) ) ;
fclose(fidout) ;
end
Which should give you the file myfileout.txt, containing:
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30
31 32 33 34 35 36
I have 2 matrices, with one having floating point numbers and the other, integer numbers. Both the matrices have the same number of rows but different number of columns.
I want to write both the matrices together to a file with each single line consisting of a single row from each matrix printed side-by-side.
How should I do this?
My try (unsuccessful) :
fid = fopen(nameF, 'w'); % Open for writing
fprintf('%d\n',fid);
for i=1:size(FloatMat,1)
fprintf(fid, '%f %d ', FloatMat(i,:),IntMat(i,:));
fprintf(fid, '\n');
end
fclose(fid);
Your problem is that the %f and %d of your fprintf only refers to the first and second columns. If there are more columns Matlab will repeat the pattern.
So you are saving the first column of FloatMat as float, the second column of FloatMat as Integer, etc...
You must specify the type of each column, but don't worry, you don't have to do it manually, use repmat instead
fprintf(fid, [repmat('%f ',1,size(FloatMat,2)) ' ' ...
repmat('%d ',1,size(IntMat,2)) '\n'], ...
FloatMat(i,:), IntMat(i,:));
PD: Note that I have separated the columns with space, as you did. Feel free to use \t or comma to separate them if needed.
PD: Also you can include the \n in the same line, so you can save one line of code.
This one actually writes both in float format with 8 digits precision, you will not get %d effect here but is only two lines:
BothMat = [FloatMat IntMat]
save(nameF, 'BothMat', '-ascii')
You don't need to complicate things using repmat int his case, just fprintf the float matrix first followed by the int matirx:
nRows = 5;
Mint = magic(nRows);
Mfloat = rand(nRows, 3);
fid = fopen('test.txt','w');
for row = 1:nRows
fprintf(fid,'%f\t', Mfloat(row,:));
fprintf(fid,'%d\t',Mint(row,1:end-1)); % only go to end to prevent trailing delimiter after final value of the row
fprintf(fid,'%d\n',Mint(row,end));
end
fclose(fid);
example output
0.392227 0.276923 0.317099 17 24 1 8 15
0.655478 0.046171 0.950222 23 5 7 14 16
0.171187 0.097132 0.034446 4 6 13 20 22
0.706046 0.823458 0.438744 10 12 19 21 3
0.031833 0.694829 0.381558 11 18 25 2 9
M=[2 5 6
4 8 9
11 55 4
89 2 47]
S = {[2 5 6],[4 8 9],[11 55 4],[89 2 47]}
How from the matrix M, I can have the format S in a text file?
Giving few shots here, whichever works for you!
Shot #1
%// Form the cell array version of the input matrix, M
S = mat2cell(M,ones(1,size(M,1)),size(M,2))
%// Write to text file
output_file = 'results.txt'
dlmwrite(output_file,S,' ');
Code run -
>> type results.txt
2 5 6
4 8 9
11 55 4
89 2 47
Shot #2
If you would like to have an output that exactly resembles the cell array version, you can use a fprintf based solution -
%// S used in this code would come from the earlier codes
output_file = 'results.txt'
fid = fopen(output_file, 'w+');
fprintf(fid, '{') %// Write the starting curly bracket
for ii=1:numel(S)-1
fprintf(fid, '[%s],',num2str(S{ii})); %// Write all data except the final cell
end
fprintf(fid, '[%s]',num2str(S{end})); %// Write the data for final cell,
%// as it does not need any comma after it
fprintf(fid, '}') %// Write the ending curly bracket
fclose(fid);
Code run -
>> type results.txt
{[2 5 6],[4 8 9],[11 55 4],[89 2 47]}
Shot #3
If you are not too happy about the irregular spacings between the numerals inside the square brackets, you can directly use M, to replace S at the two lines that use fprintf with the data -
Inside the loop -
fprintf(fid, '[%d %d %d]',M(ii,1),M(ii,2),M(ii,3));
After the loop exits -
fprintf(fid, '[%d %d %d]',M(end,1),M(end,2),M(end,3));
Code run -
>> type results.txt
{[2 5 6][4 8 9][11 55 4][89 2 47]}
One-liner using mat2str for the basic work and regexprep or strrep for the fine tuning (thanks to #Divakar for reminding me about the latter function):
S = regexprep(['{' mat2str(M) '}' ], ';', '],[');
or
S = strrep(['{' mat2str(M) '}' ], ';', '],[');
Then, to write to file, use
dlmwrite('tmp.txt', S, '')
Another question on fprintf
I have a matrix s(n,5) that I want to shorten (just take columns 3,4 and 5) into s1(n,3) and save with a different name.
s1=s(:,3:5);
txtfilename = [Filename '-1.txt'];
% Open a file for writing
fid = fopen(txtfilename, 'w');
% print values in column order
% two values appear on each row of the file
fprintf(fid, '%f %f %f\n', s1);
fclose(fid);
I don't think I understood the way to use fprintf and rewrite my new matrix, because it is sorting the values.
Thanks for your help
The problem is that MATLAB stores data in column-major order, meaning that when you do s1(:), the first three values are the first three values in the first column not the first row. (This is how fprintf will read values out of s1.) For example:
>> M = magic(3)
M =
8 1 6
3 5 7
4 9 2
>> M(:)
ans =
8
3
4
1
5
9
6
7
2
You can simply transpose the matrix to output the way you want:
fprintf(fid, '%f %f %f\n', s1.');