2012-02-23 12 views
6

私は比較的経験豊富なPythonプログラマですが、C言語を書いたことがなく、Cythonを理解しようとしています。私は、NumPy再配列の列で動作するCython関数を記述しようとしています。CythonのNumPyレコード配列のカラムへのアクセス

私がこれまでに持っているコードは以下の通りです。

recarray_func.pyx:インタプリタプロンプト

import numpy as np 
cimport numpy as np 

cdef packed struct rec_cell0: 
    np.float32_t f0 
    np.int64_t i0, i1, i2 

def sum(np.ndarray[rec_cell0, ndim=1] recarray): 
    cdef Py_ssize_t i 
    cdef rec_cell0 *cell 
    cdef np.float32_t running_sum = 0 

    for i in range(recarray.shape[0]): 
     cell = &recarray[i] 
     running_sum += cell.f0 
    return running_sum 

array = np.recarray((100,), names=['f0', 'i0', 'i1', 'i2'], 
          formats=['f4', 'i8', 'i8', 'i8']) 
recarray_func.sum(array) 

これは単にrecarrayのf0列を合計します。コンパイルして問題なく実行します。

私の質問は、これをどのように変更してどのカラムでも動作できるようにすることです。上記の例では、合計する列はハードコーディングされ、ドット表記によってアクセスされます。列と和がパラメータとして渡されるように関数を変更することは可能ですか?

答えて

1

弱い型指定が必要なものは、Cにはありません。すべてのレコードタイプが同じ場合は、次のようなものを取り除くことができます。(免責事項私はこのマシンにCythonを持っていないので、私は盲目的にコーディングしています)

import numpy as np 
cimport numpy as np 

cdef packed struct rec_cell0: 
    np.float32_t f0 
    np.int64_t i0, i1, i2 

def sum(np.ndarray[rec_cell0, ndim=1] recarray, colname): 
    cdef Py_ssize_t i 
    cdef rec_cell0 *cell 
    cdef np.float32_t running_sum = 0 

    loc = recarray.dtype.fields[colname][1] 

    for i in range(recarray.shape[0]): 
     cell = &recarray[i] 
     running_sum += *(int *)(&cell+loc); 
    return running_sum 
+0

これはうまくいくかもしれません - あなたはrun_sumの型として融合型を渡してポインタとして渡すと、その型にキャストすることができます。 – shaunc

2

これはCythonのmemoryviewsを使用して行う必要があります。これらの線に沿って何か動作します(コードテストされていません):

import numpy as np 
cimport numpy as np 

cdef packed struct rec_cell0: 
    np.float32_t f0 
    np.int64_t i0, i1, i2 

def sum(rec_cell0[:] recview): 
    cdef Py_ssize_t i 
    cdef np.float32_t running_sum = 0 

    for i in range(recview.shape[0]): 
     running_sum += recview[i].f0 
    return running_sum 

速度は、おそらくあなたはCythonに渡すレコードの配列が連続していることを確実にすることによって増加させることができます。 Python(呼び出し側)側では、np.requireを使用できますが、関数シグネチャはrec_cell0[::1] recviewに変更して、配列が連続していると見なすことができることを示します。そして、いつものように、コードがテストされたら、Cythonのboundscheck,wraparoundおよびnonecheckcompiler directivesをオフにすると、スピードがさらに向上する可能性があります。

関連する問題