fish_bu
fish_bu

Reputation: 25

How to write several variables with the same format in a line to the file?

I have a matrix named t. I want to write it into a text file row by row. Also, each element in the matrix has a same format, for example 10.3f. The problem is that each row has 48 elements that I cannot write explicitly.

I tried to use {f}*{}:

for i in range(len(t[0][:])) :
    result.write( "'{8.3f}'*{per}\n".format( t[:][i],per=len(t[:][i]) ) )

I got the error as follow:

IndexError: tuple index out of range

Upvotes: 1

Views: 268

Answers (3)

CristiFati
CristiFati

Reputation: 41116

Although using [Scipy.Docs]: numpy.savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='', footer='', comments='# ', encoding=None) would be the recommended way, it's also possible using Python formatting. Note that I assumed it's an NumPy array because of pieces of code like len(t[:][i]), but the code will work the same for a Python matrix as well.

Referencing [Python 3.Docs]: string - Format String Syntax.

There are 3 problems:

  • Missing a colon (":") in the float format specifier
  • "*" from inside the string format is just what it is, a string, and doesn't do what you want (multiplying the previous part). In order to do that, you must take it out of the format
  • The sequence argument must be unpacked ([Python 3.Docs]: More Control Flow Tools - Unpacking Argument Lists)

Example (I also cleaned your code a bit):

>>> import sys
>>> import numpy as np
>>>
>>> t = np.array([[1, 2, 3, 4], [5, 6, 7, 8, 9]])
>>>
>>> result = sys.stdout  # Use stdout to mimic file write
>>>
>>> for line in t:
...     result.write(("{:8.3f}" * len(line) + "\n").format(*line))
...
   1.000   2.000   3.000   4.000
33
   5.000   6.000   7.000   8.000   9.000
41

Note: The 2 unwanted lines in the output, are result.write's return value (number of written chars) which gets automatically printed.

Upvotes: 1

martineau
martineau

Reputation: 123393

I think you're on the right track—and here's how to make that work:

import sys

result = sys.stdout

t = [[3, 1.2, 3.45, 6.789],
     [863.202, 730.2, 833.67]]

for row in t:
    fmtspec = '{:8.3f}' * len(row)
    result.write(fmtspec.format(*row) + '\n')

Output:

   3.000   1.200   3.450   6.789
 863.202 730.200 833.670

If all the rows are the same length, you only need to create the formatting specification once:

t2 = [[3, 1.2, 3.45, 6.789],
     [863.202, 730.2, 833.67, 23.1456]]

fmtspec = '{:8.3f}' * len(t2[0])  # Use length of first row.
for row in t2:
    result.write(fmtspec.format(*row) + '\n')
   3.000   1.200   3.450   6.789
 863.202 730.200 833.670  23.146

Upvotes: 1

I would suggest DictWriter if applicable.

Other option would be similar to previously given:

import os
FORMAT = "{:10.3f}"

t = [ [123, 1.2, 3.45, 6.789],
    [3863.202, 730.2, 833.67],
    [863.202, 7230.2, 833.67], ]

def numbers_to_line(*args):
    template = FORMAT * len(args) + os.linesep
    return template.format(*args)

with open("result.txt", "w") as fh:
    for row in t:
        fh.write(numbers_to_line(*row))

and the output:

   123.000     1.200     3.450     6.789
  3863.202   730.200   833.670
   863.202  7230.200   833.670

Upvotes: 0

Related Questions