1

I have a 3-dimensional array filled with strings, mostly of numbers but also some text. If a string contains only one digit (ie. 1, 5), I want to add a zero to it (01,05,14,etc.). I can't get it to work for my NumPy array though.

I tried (among others):

strlist = ['1','2','3','4','5','6','7','8','9']
arr[np.isin(arr, strlist)] = '0' + arr[np.isin(arr, strlist)] 

But this doesn't work. Does anyone have any tips?

2 Answers 2

5

NumPy has several useful functions for arrays of strings. See NumPy docs on String operations. The function you are looking for is np.core.defchararray.zfill or its alias np.char.zfill.

Taking an example array from David Buck's answer:

>>> import numpy as np
>>> arr = np.array([[['3', '6', '12'],
                     ['0', '1', '3'],
                     ['5', 'T', '8'],
                     ['19', '15', '11']],
                    [['6', '3', '1'],
                     ['10', '10', 'QR'],
                     ['7', '11', '9'],
                     ['12', '13', '11']],
                    [['1', 'G', '3'],
                     ['10', '9', '2'],
                     ['18', '12', '17'],
                     ['6', '1', '10']]])
>>> np.char.zfill(arr, 2)
array([[['03', '06', '12'],
        ['00', '01', '03'],
        ['05', '0T', '08'],
        ['19', '15', '11']],

       [['06', '03', '01'],
        ['10', '10', 'QR'],
        ['07', '11', '09'],
        ['12', '13', '11']],

       [['01', '0G', '03'],
        ['10', '09', '02'],
        ['18', '12', '17'],
        ['06', '01', '10']]], dtype='<U2')

If you want to avoid adding zeros to elements that are not digits, we can use boolean array indexing and np.core.defchararray.isdigit function or its alias np.char.isdigit:

>>> mask = np.char.isdigit(arr)
>>> mask
array([[[ True,  True,  True],
        [ True,  True,  True],
        [ True, False,  True],
        [ True,  True,  True]],

       [[ True,  True,  True],
        [ True,  True, False],
        [ True,  True,  True],
        [ True,  True,  True]],

       [[ True, False,  True],
        [ True,  True,  True],
        [ True,  True,  True],
        [ True,  True,  True]]])
>>> arr[mask] = np.char.zfill(arr[mask], 2)
>>> arr
array([[['03', '06', '12'],
        ['00', '01', '03'],
        ['05', 'T', '08'],
        ['19', '15', '11']],

       [['06', '03', '01'],
        ['10', '10', 'QR'],
        ['07', '11', '09'],
        ['12', '13', '11']],

       [['01', 'G', '03'],
        ['10', '09', '02'],
        ['18', '12', '17'],
        ['06', '01', '10']]], dtype='<U2')
Sign up to request clarification or add additional context in comments.

Comments

3

You can define a function that pads integers/passes over non integers and then use vectorize to apply it to the whole array.

import numpy as np

def pad(value):
    try:
        return '{0:0>2}'.format(int(value))
    except:
        return value

vfunc = np.vectorize(pad)
arr = vfunc(arr)
print(arr)

Applying that to an input of:

arr = np.array([[['3', '6', '12'],
                 ['0', '1', '3'],
                 ['5', 'T', '8'],
                 ['19', '15', '11']],
                [['6', '3', '1'],
                 ['10', '10', 'QR'],
                 ['7', '11', '9'],
                 ['12', '13', '11']],
                [['1', 'G', '3'],
                 ['10', '9', '2'],
                 ['18', '12', '17'],
                 ['6', '1', '10']],])

returns

[[['03' '06' '12']
  ['00' '01' '03']
  ['05' 'T' '08']
  ['19' '15' '11']]
 [['06' '03' '01']
  ['10' '10' 'QR']
  ['07' '11' '09']
  ['12' '13' '11']]
 [['01' 'G' '03']
  ['10' '09' '02']
  ['18' '12' '17']
  ['06' '01' '10']]]

Comments

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.