1

I want to write a 2D numpy array into a human-readable text file format. I came across this question asked before but it only specifies equal number of space to be associated with each element in the array. In it all elements are spaced out with 10 spaces. What I want is different number of space for each column in my array.

Writing white-space delimited text to be human readable in Python

For example, I want 7 spaces for my 1st column, 10 spaces for my 2nd column, 4 spaces for my 3rd column, etc. Is there an analogy to numpy.savetxt(filename, X, delimiter = ',', fmt = '%-10s'), but where instead of '%-10s' I have say '%-7s, %-10s, %-4s' etc?

Thank you

Community
  • 1
  • 1
Ron
  • 57
  • 1
  • 7
  • you could always write your own for-loop structure to do it, but it will be slow in case of big files (in which case you should go binary instead of ascii anyways) – usethedeathstar Feb 17 '14 at 07:43
  • Thanks. My numpy array has thousands of rows. May I ask what do you mean by "go binary instead of ascii"? Thanks! – Ron Feb 17 '14 at 07:56
  • worst case i saw was a ~3.6Gb txtfile, which contained a full database of photometry of stars(a few million i guess). If you tried to open it you crashed the system - you had to use grep (linux command to search) to find the right lines of data you needed. If that database had been in some binary format (.fits in that case), it would have been easy to write some python scripts around it to get whatever you wanted. It worked fine though. Bottomline: if its larger than 1Mb, go binary instead of an ascii format, since its stored more efficiently and works easier too. – usethedeathstar Feb 17 '14 at 09:17

1 Answers1

0

Here is an example of what it can look like (Python2&3):

l = [[1,2,3,4], [3,4,5,6]]
for row in l:
    print(u'{:<7} {:>7} {:^7} {:*^7}'.format(*row))

1             2    3    ***4***
3             4    5    ***6***

The formatting options are taken from http://docs.python.org/2/library/string.html

>>> '{:<30}'.format('left aligned')
'left aligned                  '
>>> '{:>30}'.format('right aligned')
'                 right aligned'
>>> '{:^30}'.format('centered')
'           centered           '
>>> '{:*^30}'.format('centered')  # use '*' as a fill char
'***********centered***********'

If you need a file, then do this:

l = [[1,2,3,4], [3,4,5,6]]
with open('file.txt', 'wb') as f:
    f.write(u'\ufeff'.encode('utf-8'))
    for row in l:
        line = u'{:<7} {:>7} {:^7} {:*^7}\r\n'.format(*row)
        f.write(line.encode('utf-8'))

The content of the file is

1             2    3    ***4***
3             4    5    ***6***

And the encoding is UTF-8. This means that you can have not only numbers but also any letter in your heading: ☠ ⇗ ⌚ ② ☕ ☃ ⛷

heading = [u'☠', u'⇗', u'⌚', u'②']
with open('file.txt', 'wb') as f:
    f.write(u'\ufeff'.encode('utf-8'))
    line = '{:<7} {:>7} {:^7} {:*^7}\r\n'.format(*heading)
    f.write(line.encode('utf-8'))
    for row in l:
        line = '{:<7} {:>7} {:^7} {:*^7}\r\n'.format(*row)
        f.write(line.encode('utf-8'))

☠             ⇗    ⌚    ***②***
1             2    3    ***4***
2             3    4    ***5***
User
  • 14,131
  • 2
  • 40
  • 59