49

Trying to convert int arrays to string arrays in numpy

In [66]: a=array([0,33,4444522])
In [67]: a.astype(str)
Out[67]: 
array(['0', '3', '4'], 
      dtype='|S1')

Not what I intended

In [68]: a.astype('S10')
Out[68]: 
array(['0', '33', '4444522'], 
      dtype='|S10')

This works but I had to know 10 was big enough to hold my longest string. Is there a way of doing this easily without knowing ahead of time what size string you need? It seems a little dangerous that it just quietly truncates your string without throwing an error.

jpp
  • 159,742
  • 34
  • 281
  • 339
Dave31415
  • 2,846
  • 4
  • 26
  • 34

6 Answers6

56

You can stay in numpy, doing

np.char.mod('%d', a)

This is twice faster than map or list comprehensions for 10 elements, four times faster for 100. This and other string operations are documented here.

jorgeca
  • 5,482
  • 3
  • 24
  • 36
53

Again, this can be solved in pure Python:

>>> map(str, [0,33,4444522])
['0', '33', '4444522']

Or if you need to convert back and forth:

>>> a = np.array([0,33,4444522])
>>> np.array(map(str, a))
array(['0', '33', '4444522'], 
      dtype='|S7')
Niklas B.
  • 92,950
  • 18
  • 194
  • 224
18

Use arr.astype(str), as int to str conversion is now supported by numpy with the desired outcome:

import numpy as np

a = np.array([0,33,4444522])

res = a.astype(str)

print(res)

array(['0', '33', '4444522'], 
      dtype='<U11')
jpp
  • 159,742
  • 34
  • 281
  • 339
3

You can find the smallest sufficient width like so:

In [3]: max(len(str(x)) for x in [0,33,4444522])
Out[3]: 7

Alternatively, just construct the ndarray from a list of strings:

In [7]: np.array([str(x) for x in [0,33,4444522]])
Out[7]: 
array(['0', '33', '4444522'], 
      dtype='|S7')

or, using map():

In [8]: np.array(map(str, [0,33,4444522]))
Out[8]: 
array(['0', '33', '4444522'], 
      dtype='|S7')
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • For large arrays, `map()` is a better option than a list comprehension because it pushes the execution of the code into C. – Joel Cornett Mar 31 '12 at 19:33
  • 1
    @JoelCornett Sometimes `map` can be slightly faster (in this example it's about 3% faster than using a list comprehension for me), but this isn't always the case, and list comprehensions are considered more pythonic. See http://stackoverflow.com/a/1247490/1191119 – jorgeca Apr 01 '12 at 17:40
  • 2
    @jorgeca: Absolutely, it isn't always the case. Incidentally, as I was doing the research, I came upon [this enlightening article](http://www.python.org/doc/essays/list2str.html) by Guido. – Joel Cornett Apr 01 '12 at 18:07
  • 1
    @JoelCornett Definitely, that's a great read. I knew it but it's well worth revisiting. – jorgeca Apr 01 '12 at 18:13
  • @jorgeca the article seems to have moved/evaporated - any idea where it is now? I couldn't find it in [this list of essays](https://www.python.org/doc/essays/), nor searching list2str on python.org... – drevicko May 16 '15 at 00:54
  • 1
    @drevicko here's an [updated link](https://www.python.org/doc/essays/list2str/) – jorgeca Jan 25 '22 at 23:33
0

np.apply_along_axis(lambda y: [str(i) for i in y], 0, x)

Example

>>> import numpy as np

>>> x = np.array([-1]*10+[0]*10+[1]*10)
array([-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1])

>>> np.apply_along_axis(lambda y: [str(i) for i in y], 0, x).tolist()
['-1', '-1', '-1', '-1', '-1', '-1', '-1', '-1', '-1', '-1', '0', '0',
 '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1',
 '1', '1', '1', '1']
0

For those working with Python 3.9, the command should be:

list(map(str, [1,2,3]))
Filipe Pinto
  • 311
  • 3
  • 17