2011-01-07 6 views
2

Ich habe einige Numpy C-Erweiterungen zuvor mit großer Hilfe von dieser site gemacht, aber soweit ich sehen kann, sind die zurückgegebenen Parameter alle feste Länge.Array variabler Länge in Numpy C-Erweiterung zurückgeben?

Gibt es eine Möglichkeit, eine Numpy C-Erweiterung stattdessen ein numpy Array variabler Länge zurückzugeben?

+2

Was bezeichnen Sie als "variable Länge numpy Array"? Soweit ich weiß, können numpy Arrays nicht in der Größe geändert werden, sobald ihre Größe eingestellt ist. – albertov

Antwort

3

Sie können es einfacher finden, in Cython mit Hilfe der Numpy C-API numplige Erweiterungen zu erstellen, was den Prozess vereinfacht, da Sie damit Python- und C-Objekte mischen können. In diesem Fall ist es sehr schwierig, ein Array mit variabler Länge zu erstellen. Sie können einfach ein Array mit einer beliebigen Form angeben. Die Cython numpy tutorial ist wahrscheinlich die beste Quelle zu diesem Thema.

Zum Beispiel, hier ist eine Funktion, die ich vor kurzem schrieb:

import numpy as np 
cimport numpy as np 
cimport cython 

dtype = np.double 
ctypedef double dtype_t 

np.import_ufunc() 
np.import_array() 

def ewma(a, d, axis): 
    #Calculates the exponentially weighted moving average of array a along axis using the parameter d. 
    cdef void *args[1] 

    cdef double weight[1] 
    weight[0] = <double>np.exp(-d) 


    args[0] = &weight[0] 

    return apply_along_axis(&ewma_func, np.array(a, dtype = float), np.double, np.double, False, &(args[0]), <int>axis) 

cdef void ewma_func(int n, void* aData,int astride, void* oData, int ostride, void** args): 
    #Exponentially weighted moving average calculation function 

    cdef double avg = 0.0 
    cdef double weight = (<double*>(args[0]))[0] 
    cdef int i = 0 

    for i in range(n): 

     avg = (<double*>((<char*>aData) + i * astride))[0]*weight + avg * (1.0 - weight) 


     (<double*>((<char*>oData) + i * ostride))[0] = avg 

ctypedef void (*func_1d)(int, void*, int, void*, int, void **) 

cdef apply_along_axis(func_1d function, a, adtype, odtype, reduce, void** args, int axis): 
    #generic function for applying a cython function along a particular dimension 

    oshape = list(a.shape) 

    if reduce : 
     oshape[axis] = 1 

    out = np.empty(oshape, odtype) 

    cdef np.flatiter ita, ito 

    ita = np.PyArray_IterAllButAxis(a, &axis) 
    ito = np.PyArray_IterAllButAxis(out, &axis) 

    cdef int axis_length = a.shape[axis] 
    cdef int a_axis_stride = a.strides[axis] 
    cdef int o_axis_stride = out.strides[axis] 

    if reduce: 
     o_axis_stride = 0 

    while np.PyArray_ITER_NOTDONE(ita): 

     function(axis_length, np.PyArray_ITER_DATA (ita), a_axis_stride, np.PyArray_ITER_DATA (ito), o_axis_stride, args) 

     np.PyArray_ITER_NEXT(ita) 
     np.PyArray_ITER_NEXT(ito) 

    if reduce: 
     oshape.pop(axis) 
     out.shape = oshape 

    return out 

Wenn dies bei Ihnen nicht paßt, gibt es eine Funktion ist, ein neues leeres Array mit beliebiger Form zur Herstellung von (link).