summaryrefslogtreecommitdiff
path: root/numpy/lib/io.py
diff options
context:
space:
mode:
authorStefan van der Walt <stefan@sun.ac.za>2008-04-28 23:27:11 +0000
committerStefan van der Walt <stefan@sun.ac.za>2008-04-28 23:27:11 +0000
commite311e8d2d6e5f45184022ecba2f975c81caaca37 (patch)
tree9d0bd96f644521b041968759efd2ab65e1db346c /numpy/lib/io.py
parente844ca27a66e34bede3e90b5591d28aa0ae1a0e2 (diff)
downloadnumpy-e311e8d2d6e5f45184022ecba2f975c81caaca37.tar.gz
Support for multi formatting elements in savetxt [patch by David Huard].
Closes #663.
Diffstat (limited to 'numpy/lib/io.py')
-rw-r--r--numpy/lib/io.py100
1 files changed, 60 insertions, 40 deletions
diff --git a/numpy/lib/io.py b/numpy/lib/io.py
index 4c7180245..1ec5766d1 100644
--- a/numpy/lib/io.py
+++ b/numpy/lib/io.py
@@ -1,4 +1,3 @@
-
__all__ = ['savetxt', 'loadtxt',
'load', 'loads',
'save', 'savez',
@@ -322,7 +321,6 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, converters=None,
else: return X
-# adjust so that fmt can change across columns if desired.
def savetxt(fname, X, fmt='%.18e',delimiter=' '):
"""
@@ -332,49 +330,55 @@ def savetxt(fname, X, fmt='%.18e',delimiter=' '):
Parameters
----------
fname : filename or a file handle
- If the filename ends in .gz, the file is automatically saved in
- compressed gzip format. The load() command understands gzipped files
- transparently.
+ If the filename ends in .gz, the file is automatically saved in
+ compressed gzip format. The load() command understands gzipped
+ files transparently.
X : array or sequence
- Data to write to file.
- fmt : string
- A format string %[flags][width][.precision]specifier. See notes below for
- a description of some common flags and specifiers.
+ Data to write to file.
+ fmt : string or sequence of strings
+ A single format (%10.5f), a sequence of formats, or a
+ multi-format string, e.g. 'Iteration %d -- %10.5f', in which
+ case delimiter is ignored.
delimiter : str
- Character separating columns.
+ Character separating columns.
Examples
--------
- >>> savetxt('test.out', x, delimiter=',') # X is an array
- >>> savetxt('test.out', (x,y,z)) # x,y,z equal sized 1D arrays
- >>> savetxt('test.out', x, fmt='%1.4e') # use exponential notation
+ >>> savetxt('test.out', x, delimiter=',') # X is an array
+ >>> savetxt('test.out', (x,y,z)) # x,y,z equal sized 1D arrays
+ >>> savetxt('test.out', x, fmt='%1.4e') # use exponential notation
Notes on fmt
------------
flags:
- - : left justify
- + : Forces to preceed result with + or -.
- 0 : Left pad the number with zeros instead of space (see width).
+ - : left justify
+ + : Forces to preceed result with + or -.
+ 0 : Left pad the number with zeros instead of space (see width).
+
width:
- Minimum number of characters to be printed. The value is not truncated.
+ Minimum number of characters to be printed. The value is not truncated.
+
precision:
- For integer specifiers (eg. d,i,o,x), the minimum number of digits.
- For e, E and f specifiers, the number of digits to print after the decimal
- point.
- For g and G, the maximum number of significant digits.
- For s, the maximum number of characters.
+ - For integer specifiers (eg. d,i,o,x), the minimum number of
+ digits.
+ - For e, E and f specifiers, the number of digits to print
+ after the decimal point.
+ - For g and G, the maximum number of significant digits.
+ - For s, the maximum number of charac ters.
+
specifiers:
- c : character
- d or i : signed decimal integer
- e or E : scientific notation with e or E.
- f : decimal floating point
- g,G : use the shorter of e,E or f
- o : signed octal
- s : string of characters
- u : unsigned decimal integer
- x,X : unsigned hexadecimal integer
+ c : character
+ d or i : signed decimal integer
+ e or E : scientific notation with e or E.
+ f : decimal floating point
+ g,G : use the shorter of e,E or f
+ o : signed octal
+ s : string of characters
+ u : unsigned decimal integer
+ x,X : unsigned hexadecimal integer
This is not an exhaustive specification.
+
"""
if _string_like(fname):
@@ -388,17 +392,33 @@ def savetxt(fname, X, fmt='%.18e',delimiter=' '):
else:
raise ValueError('fname must be a string or file handle')
-
X = np.asarray(X)
- origShape = None
- if len(X.shape)==1 and X.dtype.names is None:
- origShape = X.shape
- X.shape = len(X), 1
- for row in X:
- fh.write(delimiter.join([fmt%val for val in row]) + '\n')
+ if X.ndim == 1:
+ if X.dtype.names is None:
+ X = np.atleast_2d(X).T
+ ncol = 1
+ else:
+ ncol = len(X.dtype.descr)
+ else:
+ ncol = X.shape[1]
+
+ # Fmt can be a string with multiple insertion points or a list of formats.
+ # E.g. '%10.5f\t%10d' or ('%10.5f', '$10d')
+ if type(fmt) in (list, tuple):
+ if len(fmt) != ncol:
+ raise AttributeError, 'fmt has wrong shape. '+ str(fmt)
+ format = delimiter.join(fmt)
+ elif type(fmt) is str:
+ if fmt.count('%') == 1:
+ fmt = [fmt,]*ncol
+ format = delimiter.join(fmt)
+ elif fmt.count('%') != ncol:
+ raise AttributeError, 'fmt has wrong number of % formats. ' + fmt
+ else:
+ format = fmt
- if origShape is not None:
- X.shape = origShape
+ for row in X:
+ fh.write(format%tuple(row) + '\n')
import re
def fromregex(file, regexp, dtype):