tprintf writes tabular data to a text file
tprintf provides a more intuitive interface to fprintf for writing tabular data to a text file. tprintf(filespec,format,A1,...,An) creates a tabular text file by writing the columns of A1,...,An to columns in the text file.
Contents
Background
Design goals
- its interface shall be easy to grasp and remember
- its interface shall be close to that of fprintf
- it shall require a minimum of code in the calling function
- it shall be fast
fprintf( fid, format, v1,v2, ... ), where v1,v2,... are scalars, writes one row. To print several rows one may put the function in a for-loop. That code is easy to read and understand. However, with large files speed becomes a problem. fprintf(...,C{:}), where C is a cell array containing numeric and character data, writes the text file much faster. With pure numerical data fprintf(...,M), where M is matrix writes even faster. However, the cell array, C, and the matrix, M, come at a price. It takes some effort to create them and the resulting code is not all that easy to read and understand - IMO. With tprintf I try to combined the best of the two.
Installation
This submission consists of three m-files and this documentation. Copy the m-files to a folder on the Matlab search path.
Examples
These examples show different uses of tprintf. Browsing through them gives a good notion of the capability of tprintf.
Sample data: Create column oriented data of different kinds. All data variables have five rows to keep the printed files small.
N = 5; ffs = 'c:\tmp\tprintf.txt'; f1 = rand( N, 1 ); f2 = rand( N, 2 ) * 2; f3 = rand( N, 3 ) * 3; i1 = ones( N, 1, 'int8' ); i2 = ones( N, 2, 'int8' ) * 2; i3 = ones( N, 3, 'int8' ) * 3; cs1 = {'ABC';'DEF';'GHI';'JKL';'MNO'}; s1 = ['MNO';'PQR';'STU';'VWX';'YZZ']; cs2 = cat( 2, cs1, lower(cs1) ); whos f1 f2 f3 i1 i2 i3 cs1 cs2 s1
Name Size Bytes Class Attributes cs1 5x1 590 cell cs2 5x2 1180 cell f1 5x1 40 double f2 5x2 80 double f3 5x3 120 double i1 5x1 5 int8 i2 5x2 10 int8 i3 5x3 15 int8 s1 5x3 30 char
Formatted double
tprintf( ffs, '%6.3f,%6.3f,%6.3f,%6.1f,%6.2f,%6.2f\n', f3, f1, f2 );
type( ffs )
0.381, 0.631, 2.506, 0.6, 1.94, 1.77 2.405, 0.887, 1.134, 0.1, 1.54, 1.43 0.316, 0.454, 2.452, 0.1, 0.43, 0.01 0.885, 0.332, 0.707, 0.7, 0.84, 1.12 0.008, 0.802, 2.801, 0.6, 1.94, 1.29
Integers
tprintf( ffs, '%d,%d,%d,%d,%d,%d\n', i3, i1, i2 );
type( ffs )
3,3,3,1,2,2 3,3,3,1,2,2 3,3,3,1,2,2 3,3,3,1,2,2 3,3,3,1,2,2
Strings
tprintf( ffs, '%s,%s,%s,%s\n', cs2, cs1, s1 );
type( ffs )
ABC,abc,ABC,MNO DEF,def,DEF,PQR GHI,ghi,GHI,STU JKL,jkl,JKL,VWX MNO,mno,MNO,YZZ
Combination of the classes with an extra space between the columns
tprintf( ffs, '%s, %d, %s, %f, %f, %f, %s, %s\n', cs1, i1, s1, f3, cs2 );
type( ffs )
ABC, 1, MNO, 0.380620, 0.630681, 2.505789, ABC, abc DEF, 1, PQR, 2.404988, 0.886882, 1.133766, DEF, def GHI, 1, STU, 0.315689, 0.454042, 2.451792, GHI, ghi JKL, 1, VWX, 0.884717, 0.331564, 0.706787, JKL, jkl MNO, 1, YZZ, 0.007668, 0.801814, 2.800864, MNO, mno
And with a header row.
delete( ffs ) fid = fopen( ffs, 'a' ); fprintf( fid, '%s\n', 'Col1, Col2, Col3, Col4, Col5, Col6' ); tprintf( fid, '%s, %d, %s, %f, %f, %f\n', cs1, i1, s1, f3 ); fclose( fid ); type( ffs )
Col1, Col2, Col3, Col4, Col5, Col6 ABC, 1, MNO, 0.380620, 0.630681, 2.505789 DEF, 1, PQR, 2.404988, 0.886882, 1.133766 GHI, 1, STU, 0.315689, 0.454042, 2.451792 JKL, 1, VWX, 0.884717, 0.331564, 0.706787 MNO, 1, YZZ, 0.007668, 0.801814, 2.800864
Comarison of speed between tprintf, csvwrite, save(...,'-ascii') and for,fprintf,end
The results below indicate that tprintf and save(...,'-ascii') are an order of magnitude faster than, csvwrite and for,fprintf,end.
warning( 'off', 'MATLAB:DELETE:FileNotFound') N = 1e5; ffs = 'c:\tmp\tprintf.txt'; num = rand( N, 6 ); n1 = num(:,1); n2 = num(:,2); n3 = num(:,3); n4 = num(:,4); n5 = num(:,5); n6 = num(:,6); fprintf( '\ntprintf\n' ); delete( ffs ) tic tprintf( ffs, '%f,%f,%f,%f,%f,%f\n', n1,n2,n3,n4,n5,n6 ); toc fid = fopen( ffs ); tpr = textscan( fid, '%f%f%f%f%f%f', 'Delimiter',',', 'CollectOutput',true ); tpr = tpr{1}; fclose( fid ); max(abs(tpr-num)) fprintf( '\ncsvwrite\n' ); delete( 'c:\tmp\tprintf.csv' ) tic csvwrite( 'c:\tmp\tprintf.csv', num ); toc csv = csvread( 'c:\tmp\tprintf.csv' ); max(abs(csv-num)) fprintf( '\nsave\n' ); delete( 'c:\tmp\tprintf.mat' ) tic save( 'c:\tmp\tprintf.mat', 'num', '-ASCII' ); toc msl = load( 'c:\tmp\tprintf.mat', '-ASCII' ); max(abs(msl-num)) fprintf('\nfor,fprintf,end\n'); delete('c:\tmp\loop_fprintf.txt') tic fid = fopen('c:\tmp\loop_fprintf.txt','W'); for jj = 1 : N fprintf( fid, '%f,%f,%f,%f,%f,%f\n' ... , n1(jj,:),n2(jj,:),n3(jj,:),n4(jj,:),n5(jj,:),n6(jj,:) ); end fclose( fid ); toc fid = fopen('c:\tmp\loop_fprintf.txt'); ffe = textscan( fid, '%f%f%f%f%f%f', 'Delimiter',',', 'CollectOutput',true ); ffe = ffe{1}; fclose( fid ); max(abs(ffe-num)) warning( 'on', 'MATLAB:DELETE:FileNotFound')
tprintf Elapsed time is 0.592410 seconds. ans = 1.0e-06 * 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 csvwrite Elapsed time is 5.012890 seconds. ans = 1.0e-05 * 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 save Elapsed time is 0.508718 seconds. ans = 1.0e-08 * 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000 for,fprintf,end Elapsed time is 3.999473 seconds. ans = 1.0e-06 * 0.5000 0.5000 0.5000 0.5000 0.5000 0.5000