Writing string from numpy structured array with different delimiter
I have some data stored in a numpy structured array that I would like to write to a file. Since I am generating some code to match an existing output format that exported a more visually pleasing table, I need to output this data using a different space delimiter.
Using a basic example:
import numpy as np
x = np.zeros((2,),dtype=('i4,f4,a10'))
x[:] = [(1,2.,'Hello'),(2,3.,'World')]
With the desired output:
1 2.00 Hello
2 3.00 World
Now I know I can do this:
for row in x:
print('%i %.2f %s' % (row[0], row[1], row[2]))
Which works great, but seems too verbose if you have a lot of columns. Now my output is 8.
I'm new to Python (from MATLAB), is there a more general operator I could use to "collapse" all columns? I was thinking something like strings print('%i %.2f %s' % val for val in row)
, but this just prints 2 generators. When I came across a generator in use re.split
, I could use list()
to get the desired output, but I don't think using something similar, say str()
for this case, would do what I'm looking for.
source to share
If you wrap row
in tuple
, you don't need to list all the elements. %
formats are accepted tuple
. row
may appear like tuple
, but it actually is numpy.void
.
for row in x:
print('%i %.2f %s'%tuple(row))
Printing or writing lines in a loop like this is perfectly normal Python.
Class __str__
methods are often written as:
astr=['a header line']
for row in x:
astr.append('%i %.2f %s'%tuple(row))
astr='\n'.join(astr)
creating a string of concatenated strings.
The equivalent of understanding could be:
'\n'.join('%i %.2f %s'%tuple(row) for row in x)
Since you are using Python3 you can also use the approach .format
, but I suspect the style is %
closer to what you are using in MATLAB.
source to share
First:
Regarding your implicit question with generators; you can "tweak" the generator, for example, with str.join
:
>>> gen = (i.upper() for i in "teststring")
>>> print(''.join(gen))
TESTSTRING
Second: To the real question: It's a bit more general than your approach, but it's still not very satisfying.
formats = [
("{}", 1), # format and number of spaces for row[0]
("{.2f}", 4), # the same for row[1]
("{}", 0) # and row[2]
]
for row in x:
lst = [f.format(d) + (" "*s) for (f, s, d) in zip(formats, row)]
print(*lst, sep='')
It simply provides a better overview for each format.
source to share