4

I have a numpy array of hex string (eg: ['9', 'A', 'B']) and want to convert them all to integers between 0 255. The only way I know how to do this is use a for loop and append a seperate numpy array.

import numpy as np

hexArray = np.array(['9', 'A', 'B'])

intArray = np.array([])
for value in hexArray:
    intArray = np.append(intArray, [int(value, 16)])

print(intArray) # output: [ 9. 10. 11.]

Is there a better way to do this?

2
  • Could there be strings for numbers that are equal to or greater than 10? Also, by better, what are you looking for? Compact or more performant? Commented Mar 26, 2020 at 13:57
  • @Divakar I want it to take the least amount of time to convert. This example only has a few values but I'll have arrays with 1000s of values. Commented Mar 26, 2020 at 14:12

5 Answers 5

4

A vectorized way with array's-view functionality -

In [65]: v = hexArray.view(np.uint8)[::4]

In [66]: np.where(v>64,v-55,v-48)
Out[66]: array([ 9, 10, 11], dtype=uint8)

Timings

Setup with given sample scaled-up by 1000x -

In [75]: hexArray = np.array(['9', 'A', 'B'])

In [76]: hexArray = np.tile(hexArray,1000)

# @tianlinhe's soln
In [77]: %timeit [int(value, 16) for value in hexArray]
1.08 ms ± 5.67 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# @FBruzzesi soln
In [78]: %timeit list(map(functools.partial(int, base=16), hexArray))
1.5 ms ± 40.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# From this post
In [79]: %%timeit
    ...: v = hexArray.view(np.uint8)[::4]
    ...: np.where(v>64,v-55,v-48)
15.9 µs ± 294 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Sign up to request clarification or add additional context in comments.

4 Comments

hexArray = np.array(['9', 'A', '1B']) where 1B-->27 using thise code I get output array([ 9, 208, 10, 208, 1, 11], dtype=uint8).How to make it work for any value not just for 1,2,3,4,5,6,7,8,9,a,b,c,d,e,f
@Ch3steR That was my question as comment, there was no response and also since the title had hex strings, I assumed it's all one character strings. I guess OP would come back if they have such scenarios too.
I'm not saying this answer is bad or complaining. I just wanted to know how to convert every hex string to int.
@Ch3steR I didn't assume you were. For that, we need to process further on v, won't be very pretty tho.
3

With the use of list comprehension:

 array1=[int(value, 16) for value in hexArray]
 print (array1)

output:

[9, 10, 11]

Comments

1

Alternative using map:

import functools

list(map(functools.partial(int, base=16), hexArray))
[9, 10, 11]

Comments

0
intArray = [int(hexNum, 16) for hexNum in list(hexArray)]

Try this, uses list comprehension to convert each hexadecimal number to an integer.

Comments

0

Here is another good one:

int_array = np.frompyfunc(int, 2, 1) #Can be used, for example, to add broadcasting to a built-in Python function 
int_array(hexArray,16).astype(np.uint32)

If you want to know more about it: https://numpy.org/doc/stable/reference/generated/numpy.frompyfunc.html?highlight=frompyfunc#numpy.frompyfunc

Check out the speed:

import numpy as np
import functools
hexArray = np.array(['ffaa', 'aa91', 'b1f6'])
hexArray = np.tile(hexArray,1000)
def x_test(hexArray):
    v = hexArray.view(np.uint32)[::4]
    return np.where(v > 64, v - 55, v - 48)
int_array = np.frompyfunc(int, 2, 1)
%timeit -n 100 int_array(hexArray,16).astype(np.uint32)
%timeit -n 100 np.fromiter(map(functools.partial(int, base=16), hexArray),dtype=np.uint32)
%timeit -n 100 [int(value, 16) for value in hexArray]
%timeit -n 100 x_test(hexArray)
print(f'\n\n{int_array(hexArray,16).astype(np.uint32)=}\n{np.fromiter(map(functools.partial(int, base=16), hexArray),dtype=np.uint32)=}\n{[int(value, 16) for value in hexArray][:10]=}\n{x_test(hexArray)=}')
460 µs ± 2.42 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.25 ms ± 2.66 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.11 ms ± 6.56 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
16.8 µs ± 165 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)
int_array(hexArray,16).astype(np.uint32)=array([65450, 43665, 45558, ..., 65450, 43665, 45558], dtype=uint32)
np.fromiter(map(functools.partial(int, base=16), hexArray),dtype=np.uint32)=array([65450, 43665, 45558, ..., 65450, 43665, 45558], dtype=uint32)
[int(value, 16) for value in hexArray][:10]=[65450, 43665, 45558, 65450, 43665, 45558, 65450, 43665, 45558, 65450]
x_test(hexArray)=array([47, 42, 43, ..., 47, 42, 43], dtype=uint32)

Divakar's answer is the fastest, but, unfortunately, does not work for bigger hex numbers (at least for me)

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.