同じ形状の2つの入力配列xとyがあります。関数を介して一致するインデックスを持つ各要素を実行し、それらのインデックスで結果を3番目の配列zに格納する必要があります。これを達成する最もPython的な方法は何ですか?現在、4つの4つのループがあります。もっと簡単な方法があるはずです。
x = [[2, 2, 2],
[2, 2, 2],
[2, 2, 2]]
y = [[3, 3, 3],
[3, 3, 3],
[3, 3, 1]]
def elementwise_function(element_1,element_2):
return (element_1 + element_2)
z = [[5, 5, 5],
[5, 5, 5],
[5, 5, 3]]
関数が個々のデータペアでしか機能しないため、混乱しています。 x配列とy配列を関数に単純に渡すことはできません。
「より簡単な方法」の1つは、 numpy.vectorize
を使用してNumPy対応の関数を作成することです。 「ufunc」は、要素ごとの関数のNumPy用語です(ドキュメント こちら を参照)。 numpy.vectorize
を使用すると、要素ごとの関数を使用して独自のufuncを作成できます。これは、他のNumPy ufuncと同じように機能します(標準の加算など):ufuncは配列を受け入れ、それを適用します要素の各ペアに対して関数を実行すると、標準のNumPy関数などと同じように配列形状のブロードキャストが行われます。 ドキュメントページ には、役立つと思われる使用例がいくつかあります。
In [1]: import numpy as np
...: def myfunc(a, b):
...: "Return 1 if a>b, otherwise return 0"
...: if a > b:
...: return 1
...: else:
...: return 0
...: vfunc = np.vectorize(myfunc)
...:
In [2]: vfunc([1, 2, 3, 4], [4, 3, 2, 1])
...:
Out[2]: array([0, 0, 1, 1])
In [3]: vfunc([1, 2, 3, 4], 2)
...:
Out[3]: array([0, 0, 1, 1])
(私はあなたの単純なpython list
について話していると思いますが、numpy.array
ではありません)
再帰は常に私たちの生活を楽にします:
def operate_on_Narray(A, B, function):
try:
return [operate_on_Narray(a, b, function) for a, b in Zip(A, B)]
except TypeError as e:
# Not iterable
return function(A, B)
使用法:
>>> x = [[2, 2, 2],
... [2, 2, 2],
... [2, 2, 2]]
>>>
>>> y = [[3, 3, 3],
... [3, 3, 3],
... [3, 3, 1]]
>>> operate_on_Narray(x, y, lambda a, b: a+b)
[[5, 5, 5], [5, 5, 5], [5, 5, 3]]
他の種類の次元配列でも機能します。
>>> operate_on_Narray([1, 2, 3], [4, 5, 6], lambda a, b: a*b)
[4, 10, 18]
python 2.7.3インタプリタセッションからの次のトランスクリプトは、組み込み関数map
を使用して、要素ごとの操作を2Dマトリックス要素に適用する方法を示しています。(注:operator.add
は、指定されたelementwise_function
と同等であり、applier
の2番目の使用におけるラムダ式とも同等です。)
>>> import operator
>>> def applier(a, b, op):
... return map(lambda ro: map(op, ro[0], ro[1]), Zip(a,b))
...
>>> applier(x, y, operator.add)
[[5, 5, 2], [5, 4, 5], [6, 5, 5]]
>>> x; y
[[2, 2, 1], [2, 2, 2], [3, 2, 2]]
[[3, 3, 1], [3, 2, 3], [3, 3, 3]]
>>> applier(x, y, lambda p,q: p+q)
[[5, 5, 2], [5, 4, 5], [6, 5, 5]]
>>> applier(x, y, lambda p,q: p-q)
[[-1, -1, 0], [-1, 0, -1], [0, -1, -1]]
>>> applier(x, y, lambda p,q: p*q)
[[6, 6, 1], [6, 4, 6], [9, 6, 6]]
上記のx、yは次のとおりです。
x=[[2, 2, 1], [2, 2, 2], [3, 2, 2]]
y=[[3, 3, 1], [3, 2, 3], [3, 3, 3]]
前述のように、上記のトランスクリプトはpython 2.7.3インタープリターセッションからのものです。このコードをpython 3で実行すると、代わりにマップオブジェクトが返されます。 。次のような関数を使用して、数値を表示できます。
def itemize(m):
return [itemize(e) for e in m] if hasattr(m, '__iter__') else m
その関数を配置すると、ステートメント
itemize(applier(x, y, operator.add))
戻り値
[[5, 5, 2], [5, 4, 5], [6, 5, 5]]