141 lines
4.2 KiB
Python
141 lines
4.2 KiB
Python
|
"""
|
||
|
Input/Output tools for working with binary data.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
numpy.lib.io
|
||
|
"""
|
||
|
import numpy as np
|
||
|
|
||
|
from statsmodels.iolib.openfile import get_file_obj
|
||
|
|
||
|
|
||
|
def savetxt(fname, X, names=None, fmt='%.18e', delimiter=' '):
|
||
|
"""
|
||
|
Save an array to a text file.
|
||
|
|
||
|
This is just a copy of numpy.savetxt patched to support structured arrays
|
||
|
or a header of names. Does not include py3 support now in savetxt.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
fname : filename or file handle
|
||
|
If the filename ends in ``.gz``, the file is automatically saved in
|
||
|
compressed gzip format. `loadtxt` understands gzipped files
|
||
|
transparently.
|
||
|
X : array_like
|
||
|
Data to be saved to a text file.
|
||
|
names : list, optional
|
||
|
If given names will be the column header in the text file.
|
||
|
fmt : str or sequence of strs
|
||
|
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.
|
||
|
|
||
|
See Also
|
||
|
--------
|
||
|
save : Save an array to a binary file in NumPy ``.npy`` format
|
||
|
savez : Save several arrays into a ``.npz`` compressed archive
|
||
|
|
||
|
Notes
|
||
|
-----
|
||
|
Further explanation of the `fmt` parameter
|
||
|
(``%[flag]width[.precision]specifier``):
|
||
|
|
||
|
flags:
|
||
|
``-`` : 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
|
||
|
if it has more characters.
|
||
|
|
||
|
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.
|
||
|
|
||
|
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`` : str of characters
|
||
|
|
||
|
``u`` : unsigned decimal integer
|
||
|
|
||
|
``x,X`` : unsigned hexadecimal integer
|
||
|
|
||
|
This explanation of ``fmt`` is not complete, for an exhaustive
|
||
|
specification see [1]_.
|
||
|
|
||
|
References
|
||
|
----------
|
||
|
.. [1] `Format Specification Mini-Language
|
||
|
<http://docs.python.org/library/string.html#
|
||
|
format-specification-mini-language>`_, Python Documentation.
|
||
|
|
||
|
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
|
||
|
"""
|
||
|
|
||
|
with get_file_obj(fname, 'w') as fh:
|
||
|
X = np.asarray(X)
|
||
|
|
||
|
# Handle 1-dimensional arrays
|
||
|
if X.ndim == 1:
|
||
|
# Common case -- 1d array of numbers
|
||
|
if X.dtype.names is None:
|
||
|
X = np.atleast_2d(X).T
|
||
|
ncol = 1
|
||
|
|
||
|
# Complex dtype -- each field indicates a separate column
|
||
|
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 isinstance(fmt, (list, tuple)):
|
||
|
if len(fmt) != ncol:
|
||
|
raise AttributeError('fmt has wrong shape. %s' % str(fmt))
|
||
|
format = delimiter.join(fmt)
|
||
|
elif isinstance(fmt, str):
|
||
|
if fmt.count('%') == 1:
|
||
|
fmt = [fmt, ]*ncol
|
||
|
format = delimiter.join(fmt)
|
||
|
elif fmt.count('%') != ncol:
|
||
|
raise AttributeError('fmt has wrong number of %% formats. %s'
|
||
|
% fmt)
|
||
|
else:
|
||
|
format = fmt
|
||
|
|
||
|
# handle names
|
||
|
if names is None and X.dtype.names:
|
||
|
names = X.dtype.names
|
||
|
if names is not None:
|
||
|
fh.write(delimiter.join(names) + '\n')
|
||
|
|
||
|
for row in X:
|
||
|
fh.write(format % tuple(row) + '\n')
|