8

列にさまざまなデータ型が含まれているnumpy.arrays があり、列にもさまざまな関数を適用する必要があります。配列にも関数があります。

まあ言ってみれば:

a = array([[ 1, 2.0, "three"],
           [ 4, 5.0, "six"  ]], dtype=object)

functions_arr = array([act_on_int, act_on_float, act_on_str])

物事を分割することでこれを行う方法は確かに考えられますが、私にとって最も自然に思えるのは、ブロードキャストとの要素ごとの乗算、および演算子としての機能と考えることです。だから私は次のようなことをしたい

functions_arr*a

の効果を得る

array([[act_on_int(1), act_on_float(2.0), act_on_str("three")],
       [act_on_int(4), act_on_float(5.0), act_on_str("six")  ]])

それらの線に沿って何かを達成する方法を知っていますか?

編集:質問の配列の定義を変更して、dtype=[object]人々が指摘したように、配列が意図した方法で型を格納することが重要であると指摘しました。

回答とコメントありがとうございます!私は送信者の回答を受け入れましたが、これは私が考えていたものに非常に近いと感じています.

演算が乗算に似ていると考える方法について混乱があったように思われるので、別の例でそれを明確にしましょう。

ご存じのとおり、次のような操作です。

v = array([1,2,3])
u = array([[5,7,11],
           [13,17,19]])
v*u

とyieldvの行をブロードキャストしますu

array([[ 1*5, 2*7,  3*11],
       [1*13, 2*17, 3*19]])

すなわち

array([[ 5, 14, 33],
       [13, 34, 57]])

vたとえば、del 演算子に置き換えるとしたら、次のようになります (以下は実際には動作する Python コードではありません:)

V = array([(d/dx),(d/dy),(d/dz)])
u = array([[5,7,11],
           [13,17,19]])
V*u

屈服する(精神的に)

array([[(d/dx)5, (d/dy)7, (d/dz)11]],
       [(d/dx)13,(d/dy)17,(d/dz)19]])

一連の定数の導関数をとることは、最もu興味深い操作ではないことを認めます。いずれにせよ、これが少なくとも私の推論と、タイトルの「(python 関数を演算子として使用する?)」に関するビットの両方をより明確にすることを願っています。xyz

4

3 に答える 3

4

Sven Marnachが私に思い出させたように、あなたが作成した配列はおそらくPythonオブジェクトの配列です。それらに対する操作は、純粋な操作よりもはるかに遅くなる可能性がありますnumpy。ただし、これが非常に高速であると実際に期待しない限り、要求したことを非常に簡単に実行できます。AFogliaが提案したものとそれほど違いはありませんが、まさにあなたが求めていたものに近いです。

>>> a = numpy.array([[ 1, 2.0, "three"],
...                  [ 4, 5.0, "six"  ]], dtype=object)
>>> funcs = [lambda x: x + 10, lambda x: x / 2, lambda x: x + '!']
>>> apply_vectorized = numpy.vectorize(lambda f, x: f(x), otypes=[object])
>>> apply_vectorized(funcs, a)
array([[11, 1.0, three!],
       [14, 2.5, six!]], dtype=object)

また、ここにAFogliaをエコーすると、レコード配列を使用したほうがよい可能性が高くなります。これにより、配列を好きなように分割し、numpyufuncsを使用してより自然な方法で操作できます。 Python関数よりも高速で、通常は次のようになります。

rec.array([(1, 2.0, 'three'), (4, 5.0, 'six')], 
      dtype=[('int', '<i8'), ('float', '<f8'), ('str', '|S10')])
>>> a['int']
array([1, 4])
>>> a['float']
array([ 2.,  5.])
>>> a['str']
rec.array(['three', 'six'], 
      dtype='|S10')
>>> a['int'] += 10
>>> a['int']
array([11, 14])
于 2012-07-05T15:22:06.580 に答える
3

元の配列は 1 次元しかないため、ブロードキャストではありません。各要素に 3 つのメンバー (int、float、string) があるため 2 次元に見えますが、numpy にすると、それは単に型であり、次元数は 1 です。

関数を各要素に適用しているため、乗算でもありません。(これは加算よりも乗算ではないため、functions_arr * a誤解を招く構文です。)

それでも、あなたが望むものに類似したものを書くことができます。numpy.vectorize を試してみます。テストせずに、出力 dtype が元の配列と同じであると仮定します。私はそれが次のようになると想像します...

def act_on_row(row) :
    return (act_on_int(row["int_field"]),
            act_on_float(row["float_field"]),
            act_on_str(row["str_field"]))

act_on_array = numpy.vectorize(act_on_row, otypes=[a.dtype])

acted_on = act_on_array(a)

ベクトル化を試したことはありません。構造化された dtype を扱うのが難しいかどうかはわかりませんが、これで始められるはずです。

ただし、より簡単な解決策は、フィールドごとに配列をループすることです。

rslt = numpy.empty((len(a),), dtype=a.dtype)

rslt["int_field"] = act_on_int(a["int_field"])
rslt["float_field"] = act_on_float(a["float_field"])
rslt["str_field"] = act_on_str(a["str_field"])

(機能によっては、個々の関数をベクトル化する必要がある場合があります。)

于 2012-07-05T14:33:30.247 に答える
3

組み込み関数zip()を探している

を使用した簡単な例lists:

>>> a=[[ 1, 2.0, "three"],[ 4, 5.0, "six"  ]]

>>> funcs=[lambda x:x**2,lambda y:y*2,lambda z:z.upper()]

>>> [[f(v) for v,f in zip(x,funcs)]for x in a]
[[1, 4.0, 'THREE'], [16, 10.0, 'SIX']]
于 2012-07-05T13:55:08.733 に答える