Create numpy array of arrays with leading zeros and different start- and stop-points

Viewed 461

I have different integer start and stop values and need all integer values in between as arrays in one array of shape (theRange, finalLength).

Example:

finalLength = 6
start = 2
stop = 3456
theRange = (stop - start) + 1


>>> array([[0, 0, 0, 0, 0, 2],
           [0, 0, 0, 0, 0, 3],
           [0, 0, 0, 0, 0, 4],
           ...,
           [0, 0, 3, 4, 5, 4],
           [0, 0, 3, 4, 5, 5],
           [0, 0, 3, 4, 5, 6]])

>>> array.shape (3455, 6)

As I need to run this function billions of times the current way is to slow.

At the moment I create the desired range using np.linspace. The integers are split into digits following (Split integer into digits using numpy.

If the number of digits of the largest number is not equal to finalLength, leading zeros are added. Finally, the resulting array is flipped and transposed to the desired output format. I think the integer splitting and transposing takes the most computation time.

Time increases with longer finalLength: Timeit 10000 reps

finalLength = 6 --> time: 2.815263898999546

finalLength = 12 --> time: 4.158567378000043

finalLength = 24 --> time: 5.038266787999419

Is there a faster way to create the final array?

Reproducable code:

import numpy as np

finalLength = 6
start = 2
stop = 3456
theRange = (stop - start) + 1

def makeRangeArray(start, stop, theRange, finalLength):
    # create integers within range
    ll = np.array(np.linspace(start=start, stop=stop, num=theRange), dtype=np.int64)

    # split integers into arrays
    b = 10
    n = np.ceil(np.max(np.log(ll) / np.log(b))).astype(np.int64)
    d = np.arange(n)
    d.shape = d.shape + (1,) * ll.ndim
    out = ll // b ** d % b

    # add leading zeros if necessary
    if finalLength - out.shape[0] != 0:
        addZeros = np.zeros([finalLength - out.shape[0], out.shape[1]], dtype=np.int64)
        out = np.append(out, addZeros, axis=0)  # insert zeros at the end of array

    # flip
    out = np.flip(out, axis=0)

    # transpose to desired final output format
    aaa = out.transpose().reshape((theRange, finalLength))

    return aaa
0 Answers
Related