1

次のような状況では、配列の 1 つに要素として配列が含まれる 2 つの配列を要素単位で乗算します。

>>> import numpy as np
>>> base = np.array( [100., 111.,] )
>>> c = np.array( [9., 11.] )
>>> n0 = np.zeros(len(base))
>>> nn = 3 + n0     # This is the gist of a bunch of intermediate operations
>>> grid = [np.ones(i) for i in nn]
>>> base
array([ 100.,  111.])
>>> c
array([  9.,  11.])
>>> nn
array([ 3.,  3.])
>>> grid
[array([ 1.,  1.,  1.]), array([ 1.,  1.,  1.])]

これまでのところ、すべてが良さそうです。gridには 2 つの要素があり、それぞれに 3 つの要素があります。私はそれを掛けることができるはずだと感じていますc

>>> a = grid * c
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (2,3) (2) 

それは私が望んでいたようにはいきません。エラーは有望です。いくつかの転置トリックを実行して、結果を得ることができます。

a = (grid.T * c).T トレースバック (最新の呼び出しが最後): ファイル ""、1 行目、AttributeError: 'list' オブジェクトに属性 'T' がありません

それは私が予想したよりも見事に失敗します。配列で作業していると思っていましたが、リストがあることがわかりました。私は古き良き昔ながらのブルートフォースで手を試します:

>>> grid_mod = np.array( [np.ones(3), np.ones(3) ] )
>>> grid_mod
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])
>>> grid_mod * c
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (2,3) (2) 

私はそれがうまくいくと確信していました!最後の要素の後に不要なスペースがあることに気付いたので、それを削除します。

>>> grid_mod2 = np.array( [np.ones(3), np.ones(7)] )
>>> grid_mod2
array([array([ 1.,  1.,  1.]), array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.])], dtype=object)
>>> grid_mod2 * c
array([array([ 9.,  9.,  9.]),
       array([ 11.,  11.,  11.,  11.,  11.,  11.,  11.])], dtype=object)

その最後のものは期待どおりに機能します。

私の質問は次のとおりです。

  1. grid結果が配列のリストではなく配列の配列になるように定義するにはどうすればよいですか。
  2. このすべてで実際に何が起こっているのでしょうか? 配列の末尾に余分なスペースがあると、まったく異なる結果が得られるのはなぜですか。
  3. これについてもっとpythonicな方法はありますか?
4

1 に答える 1

2

これら 2 つのコードは異なるものを生成しますが、スペースは影響しません。

>>> np.array([np.ones(3), np.ones(3)])
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])

リスト内の両方の配列が同じ次元であるため、これは 2 行 3 列の 1 つの配列に変換されます。

>>> np.array([np.ones(3), np.ones(7)])
array([array([ 1.,  1.,  1.]), array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.])], dtype=object)

この場合、配列の長さが一致しないため、numpy は 2 項目の長さの 1D 配列を作成し、objectそれらのオブジェクトのそれぞれがたまたま numpy 配列になります。

最初のものをで乗算すると、 shape の配列cに shape の配列を乗算しようとしていますが、numpy にはその方法がわかりません。配列を形状に変更すると、必要なものを得ることができます。(2, 3)(2,)c(2, 1)

>>> grid_mod * c[:, np.newaxis]
array([[  9.,   9.,   9.],
       [ 11.,  11.,  11.]])

2 番目をcで乗算すると、 shape の 2 つの配列を乗算しようとしている(2,)ため、numpy は要素ごとの乗算を問題なく実行します。また、配列の各項目自体が配列であるため、それをスカラーで乗算しようとすると、numpy もその方法を知っています。これは機能しますが、前のアプローチよりもはるかに遅く、10000 行配列の場合は約 100 倍です。

c = np.random.rand(10000)
a = np.random.rand(10000, 3)
b = np.empty((10000,), dtype=object)
for j in xrange(10000):
    b[j] = a[j]

%timeit a*c[:, np.newaxis]
10000 loops, best of 3: 176 us per loop

%timeit b*c
10 loops, best of 3: 16.5 ms per loop
于 2013-10-29T16:21:34.173 に答える