Mapping a NumPy array in place

前端 未结 5 931
北海茫月
北海茫月 2020-11-30 20:13

Is it possible to map a NumPy array in place? If yes, how?

Given a_values - 2D array - this is the bit of code that does the trick for

5条回答
  •  没有蜡笔的小新
    2020-11-30 20:32

    This is just an updated version of mac's write-up, actualized for Python 3.x, and with numba and numpy.frompyfunc added.

    numpy.frompyfunc takes an abitrary python function and returns a function, which when cast on a numpy.array, applies the function elementwise.
    However, it changes the datatype of the array to object, so it is not in place, and future calculations on this array will be slower.
    To avoid this drawback, in the test numpy.ndarray.astype will be called, returning the datatype to int.

    As side note:
    Numba isn't included in Python's basic libraries and has to be downloaded externally if you want to test it. In this test, it actually does nothing, and if it would have been called with @jit(nopython=True), it would have given an error message saying that it can't optimize anything there. Since, however, numba can often speed-up code written in a functional style, it is included for integrity.

    import timeit
    from numpy import array, arange, vectorize, rint, frompyfunc
    from numba import autojit
    
    # SETUP
    get_array = lambda side : arange(side**2).reshape(side, side) * 30
    dim = lambda x : int(round(x * 0.67328))
    
    # TIMER
    def best(fname, reps, side):
        global a
        a = get_array(side)
        t = timeit.Timer('%s(a)' % fname,
                         setup='from __main__ import %s, a' % fname)
        return min(t.repeat(reps, 3))  #low num as in place --> converge to 1
    
    # FUNCTIONS
    def mac(array_):
        for row in range(len(array_)):
            for col in range(len(array_[0])):
                array_[row][col] = dim(array_[row][col])
    
    def mac_two(array_):
        li = range(len(array_[0]))
        for row in range(len(array_)):
            for col in li:
                array_[row][col] = int(round(array_[row][col] * 0.67328))
    
    def mac_three(array_):
        for i, row in enumerate(array_):
            array_[i][:] = [int(round(v * 0.67328)) for v in row]
    
    
    def senderle(array_):
        array_ = array_.reshape(-1)
        for i, v in enumerate(array_):
            array_[i] = dim(v)
    
    def eryksun(array_):
        array_[:] = vectorize(dim)(array_)
    
    @autojit
    def numba(array_):
        for row in range(len(array_)):
            for col in range(len(array_[0])):
                array_[row][col] = dim(array_[row][col])
    
    
    def ufunc_ed(array_):
        multiplied = array_ * 0.67328
        array_[:] = rint(multiplied)
    
    def ufunc_frompyfunc(array_):
        udim = frompyfunc(dim,1,1)
        array_ = udim(array_)
        array_.astype("int")
    
    # MAIN
    r = []
    totest = ('mac', 'mac_two', 'mac_three', 'senderle', 'eryksun', 'numba','ufunc_ed','ufunc_frompyfunc')
    for fname in totest:
        print('\nTesting `%s`...' % fname)
        r.append(best(fname, reps=50, side=50))
        # The following is for visually checking the functions returns same results
        tmp = get_array(3)
        eval('%s(tmp)' % fname)
        print (tmp)
    tmp = min(r)/100
    results = list(zip(totest,r))
    results.sort(key=lambda x: x[1])
    
    print('\n===== ...AND THE WINNER IS... =========================')
    for name,time in results:
        Out = '{:<34}: {:8.4f}ms [{:5.0f}%]'.format(name,time*1000,time/tmp)
        print(Out)
    print('=======================================================\n')
    



    And finally, the results:

    ===== ...AND THE WINNER IS... =========================
    ufunc_ed                          :   0.3205ms [  100%]
    ufunc_frompyfunc                  :   3.8280ms [ 1194%]
    eryksun                           :   3.8989ms [ 1217%]
    mac_three                         :  21.4538ms [ 6694%]
    senderle                          :  22.6421ms [ 7065%]
    mac_two                           :  24.6230ms [ 7683%]
    mac                               :  26.1463ms [ 8158%]
    numba                             :  27.5041ms [ 8582%]
    =======================================================
    

提交回复
热议问题