1

Say I have the following numpy structured array:

>>> a = numpy.array((1, 2.0, 'buckle_my_shoe'),dtype=('i4,f8,a14')) 
array((1, 2.0, 'buckle_my_shoe'), 
  dtype=[('f0', '<i4'), ('f1', '<f8'), ('f2', 'S14')])

and I want to save it to a single space or tab delimited row in a text file. If the array were all of the same type I could use numpy.savetxt('myfile.dat,myarray,newline=" "). However, this seems to not like mixed data types/structured arrays, for example:

file('myfile.dat', 'a')
numpy.savetxt('myfile.dat',a,newline=" ")

gives this error:

IndexError: tuple index out of range

Can anyone recommend a way of doing this?

2 Answers 2

5

Edit: For whatever reason I can't seem to be able to leave this answer alone, so here's a cleaner version that doesn't use the csv module unnecessarily. For the record, @askewchan's answer is still better!

a = numpy.array([(1, 2.0, 'buckle_my_shoe'),
                 (3,4.0,'lock_the_door')],dtype=('i4,f8,a14'))
with open('test.txt','w') as f:
     f.write(' '.join([str(item) for sublist in a for item in sublist]))
print open('test.txt','r').read()

Output:

1 2.0 buckle_my_shoe 3 4.0 lock_the_door
Sign up to request clarification or add additional context in comments.

Comments

1

If you have a zero-d array like your example, then you can just do this:

b = np.array((1, 2.0, 'buckle_my_shoe'), 
         dtype=[('f0', '<i4'), ('f1', '<f8'), ('f2', 'S14')])

with open('myfile.dat','w') as f:
    for el in b[()]:
        f.write(str(el)+' ') # or `f.write(repr(el)+' ') to keep the quote marks

This works by accessing the elements of 0d arrays using [()]:

>>> b.ndim
0

>>> b[0]
IndexError: 0-d arrays cannot be indexed

>>> b[()]
(1, 2.0, 'buckle_my_shoe')

If you are using numpy arrays with zero dimensions regularly, in order to have the complex dtype, I might suggested the NamedTuple from collections.

>>> import collections
>>> A = collections.namedtuple('A', ['id', 'val', 'phrase'])
>>> a = A(1, 2.0, 'buckle_my_shoe')

>>> a
A(id=1, val=2.0, phrase='buckle_my_shoe')
>>> a.id
1
>>> a.val
2.0
>>> a.phrase
'buckle_my_shoe'

with open('myfile.dat','w') as f:
    for el in a:    
        f.write(repr(el)+' ')

If the array has more than one element:

a = np.array([(1, 2.0, 'buckle_my_shoe'),
              (3, 4.0, 'lock_the_door')],
        dtype=('i4, f8, a14'))

I'm not sure what exactly you want your file to look like. If you want the space-separated tuples, this is the best way I think:

with open('myfile.dat','w') as f:
    for row in a:
        f.write(repr(row)+' ')

which results in a file like:

(1, 2.0, 'buckle_my_shoe') (3, 4.0, 'lock_the_door')

Perhaps you wanted to have no commas or parentheses, in which case you can do:

with open('myfile.dat','w') as f:
    for row in a:
        for el in row:
            f.write(str(el)+' ')

which gives this file:

1 2.0 buckle_my_shoe 3 4.0 lock_the_door 

Use repr to keep the qutoes around the strings

with open('myfile.dat','w') as f:
    for row in a:
        for el in row:
            f.write(repr(el)+' ')

which gives this file:

1 2.0 'buckle_my_shoe' 3 4.0 'lock_the_door' 

Bonus: If your dtype has field names, you can print those too:

a.dtype.names = "index value phrase".split()
a.dtype
#dtype([('index', '<i4'), ('value', '<f8'), ('phrase', 'S14')])

with open('myfile.dat','w') as f:
    for name in a.dtype.names:
        f.write(name + ' ') # or write(repr(name)) to keep the quote marks
    for row in a:
        for el in row:
            f.write(repr(el)+' ')

Note, if you copy these files be warned I used 'w' not 'a', so that I could overwrite each one in my test cases.

3 Comments

Great answer, however doesn't seem to work with a 0-d array. E.g. [f.write(str(el)) for el in a] gives a TypeError: iteration over a 0-d array. Works well with >1 row though.
@atomh33ls Sorry, that was intentional as I thought the 0d array was a mistake. I fixed it to allow for that.
@atomh33ls Note my suggestion for using Named Tuples instead of 0d numpy arrays if you do this often.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.