1. ホーム
  2. python

[解決済み] Pythonでのa -= bとa = a - bの違い

2023-03-31 17:43:49

質問

私は最近 この を適用しました。 この解決策は一般的にはうまくいきますが、7x1の配列に適用したときに問題が発生しました。私は,この問題は -= 演算子を使用したときに問題が発生することに気づきました。 小さな例を挙げますと

import numpy as np

a = np.array([1,2,3])
b = np.copy(a)

a[1:] -= a[:-1]
b[1:] = b[1:] - b[:-1]

print a
print b

と出力します。

[1 1 2]
[1 1 1]

つまり、配列の場合 a -= b とは異なる結果をもたらします。 a = a - b . 私は今まで、この2つの方法は全く同じだと思っていました。何が違うのでしょうか?

私が述べている行列のN行ごとの合計を求める方法は、例えば7x4の行列では動作しますが、7x1の配列では動作しないのはなぜでしょうか。

どのように解決するのですか?

注意:バージョン 1.13.0 以降では、メモリを共有する NumPy 配列に対してインプレース操作を行うことは問題ではなくなりました(詳しくは ここで ). この2つの操作は同じ結果をもたらします。この回答は、NumPyの以前のバージョンにのみ適用されます。


計算で使用している間に配列を変異させると、予期しない結果になることがあります!

問題の例では、引き算に -= の2番目の要素を変更します。 a を修正し、すぐにその を修正した の 3 番目の要素に対する操作で、2 番目の要素である a .

以下は a[1:] -= a[:-1] を一歩一歩進めていきます。

  • a はデータを含む配列 [1, 2, 3] .

  • このデータには2つのビューがあります。 a[1:][2, 3] であり、かつ a[:-1][1, 2] .

  • インプレース減算の -= が始まります。の最初の要素は a[:-1] の最初の要素である 1 が減算される。 a[1:] . これによって a[1, 1, 3] . 今、私たちは a[1:] はデータのビューです [1, 3] であり a[:-1] はデータのビュー [1, 1] (配列の 2 番目の要素 a が変更されました)。

  • a[:-1] は現在 [1, 1] となり、NumPy はその2番目の要素である であり、1 (もう2じゃない!)の2番目の要素から a[1:] . これによって a[1:] という値のビューになります。 [1, 2] .

  • a は配列になり、値は [1, 1, 2] .

b[1:] = b[1:] - b[:-1] にはこの問題はありません。 b[1:] - b[:-1] 新しい の配列を作成し、この配列の値を b[1:] . これは b を変更しないので、ビュー b[1:]b[:-1] は変更しない。


一般的なアドバイスとして、あるビューと別のビューが重なっている場合、それらをインプレースで変更することは避けてください。これには演算子 -= , *= などを使用し out パラメータをユニバーサル関数(例えば np.subtractnp.multiply ) を使って配列の1つに書き戻します。