In [85]: arr = np.zeros((5,5))
...: arr[0,0] = 2
...: arr[2,2] = 1
...:
In [86]: arr
Out[86]:
array([[ 2., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.]])
容易にする必要があります:
最初の繰り返し、あなたのアイデアを試して
Python: Numpy slicing indepth explnation
今
In [89]: N = np.zeros_like(arr1)
In [90]: Z=arr1
In [91]: N[1:, 1:] += Z[:-1, :-1]
...: N[1:, :-1] += Z[:-1, 1:]
...: N[:-1, 1:] += Z[1:, :-1]
...: N[:-1, :-1] += Z[1:, 1:]
...: N[:-1, :] += Z[1:, :]
...: N[1:, :] += Z[:-1, :]
...: N[:, :-1] += Z[:, 1:]
...: N[:, 1:] += Z[:, :-1]
In [93]: N += Z
In [94]: N
Out[94]:
array([[ 2., 2., 2., 0., 0., 0., 0.],
[ 2., 2., 2., 0., 0., 0., 0.],
[ 2., 2., 3., 1., 1., 0., 0.],
[ 0., 0., 1., 1., 1., 0., 0.],
[ 0., 0., 1., 1., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0.]])
In [95]: N[1:-1, 1:-1]
Out[95]:
array([[ 2., 2., 0., 0., 0.],
[ 2., 3., 1., 1., 0.],
[ 0., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0.]])
を適応さ
In [87]: arr1 = np.zeros((arr.shape[0]+2, arr.shape[1]+2),arr.dtype)
In [88]: arr1[1:-1,1:-1]=arr
....
非ゼロ:それらの
In [124]: idx = np.argwhere(arr1)
In [125]: idx
Out[125]:
array([[1, 1],
[3, 3]], dtype=int32)
反復:
In [126]: N1 = np.zeros_like(arr1)
In [127]: for i in idx:
...: slc = (slice(i[0]-1,i[0]+2), slice(i[1]-1,i[1]+2))
...: N1[slc] += arr1[tuple(i)]
...:
In [128]: N1[1:-1,1:-1]
Out[128]:
array([[ 2., 2., 0., 0., 0.],
[ 2., 3., 1., 1., 0.],
[ 0., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0.]])
同じ繰り返しが、np.add.at
と:
In [132]: N1 = np.zeros_like(arr1)
In [133]: for i in idx:
...: slc = (slice(i[0]-1,i[0]+2), slice(i[1]-1,i[1]+2))
...: np.add.at(N1, slc, arr1[tuple(i)])
次のステップは、それらのslc
1に全体を統合することであろう、そうnp.add.at
が可能一度行った。
In [143]: for i in idx:
...: slc = (slice(i[0]-1,i[0]+2), slice(i[1]-1,i[1]+2))
...: ii = np.ix_(np.r_[slc[0]],np.r_[slc[1]])
...: np.add.at(N1,ii, arr1[tuple(i)])
...: print(ii)
...:
...:
(array([[0],
[1],
[2]]), array([[0, 1, 2]]))
(array([[2],
[3],
[4]]), array([[2, 3, 4]]))
(継続する)私は[0,1,2,2,3,4]
などを作るために、これらを連結でき考えていた。しかし、それは仕事に行くのではないです。その第一歩はnp.ix_
でスライスを拡大することです。 mgrid
配列を生成し、それらを連結する必要があります。
In [159]: slc=[np.mgrid[(slice(i[0]-1,i[0]+2), slice(i[1]-1,i[1]+2))] for i in idx]
In [160]: slc = tuple(np.hstack(slc))
In [161]: N2 = np.zeros_like(arr1)
In [162]: np.add.at(N2, slc,1)
In [163]: N2[1:-1,1:-1]
Out[163]:
array([[ 1., 1., 0., 0., 0.],
[ 1., 2., 1., 1., 0.],
[ 0., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0.]])
これは近いです。対応するarr
の値ではなく、各ポイントに1を加えています。私はそれらのポイントを正しい形でブロードキャストする必要があります。
これはまだゼロ以外の点を反復していますが、ブロードキャストされた追加でそのidx配列を生成することは想像できます。
私はこれらを追加する必要があります。そのような中
In [182]: slc1 = np.mgrid[slice(-1,2), slice(-1,2)]
In [183]: slc1
Out[183]:
array([[[-1, -1, -1],
[ 0, 0, 0],
[ 1, 1, 1]],
[[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]]])
In [177]: idx
Out[177]:
array([[1, 1],
[3, 3]], dtype=int32)
を道として生成するよう:
In [179]: slc=[np.mgrid[(slice(i[0]-1,i[0]+2), slice(i[1]-1,i[1]+2))] for i in idx]
In [180]: slc=np.hstack(slc) # np.concatenate(slc, axis=1)
In [181]: slc
Out[181]:
array([[[0, 0, 0],
[1, 1, 1],
[2, 2, 2],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4]],
[[0, 1, 2],
[0, 1, 2],
[0, 1, 2],
[2, 3, 4],
[2, 3, 4],
[2, 3, 4]]])
これはそれをしない(しかし、私はより直接的に行うことができますか?)一致する形状に非ゼロ値を複製
In [228]: slc2 = idx.T[:,:,None,None]+slc1[:,None,:,:]
In [229]: np.concatenate(list(slc2.transpose(1,0,2,3)),1)
Out[229]:
array([[[0, 0, 0],
[1, 1, 1],
[2, 2, 2],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4]],
[[0, 1, 2],
[0, 1, 2],
[0, 1, 2],
[2, 3, 4],
[2, 3, 4],
[2, 3, 4]]])
:最後の反復はまた、(ため)放送の動作なし
In [288]: pts = arr1[tuple(idx.T)]
In [289]: pts
Out[289]: array([ 2., 1.])
In [290]: pts1 = pts.repeat(3)[:,None].repeat(3,axis=1)
In [291]: pts1
Out[291]:
array([[ 2., 2., 2.],
[ 2., 2., 2.],
[ 2., 2., 2.],
[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]])
In [292]: np.add.at(N2,tuple(Out[229]), pts1)
pts1 = pts.repeat(3)[:,None]
。
これは、いくつかの関数にパックされ、いくつかの現実的なサイズの配列でタイムアウトすることができます。
ConwayのLIfeのためにこのコードで行われた複数のオフセットの合計は、おそらくあなたが得るほど速くなります:https://stackoverflow.com/questions/47648106/python-numpy-slicing-indepth-explnation私の直感は、配列が非常にまばらでない限り、あなたの選択肢が遅くなるということです。どちらの方法でも境界を処理すると複雑になります。 – hpaulj
すべての非ゼロ点を一度に追加するには、 '+ ='のバッファ化されていないバージョンである 'add.at'を使う必要があります。さもなければ、 'arr [1,1]'に対して '2 + 1'を得ることはありません。 'add.at'はバッファされたコードよりも遅く、スライスを使用しません。 – hpaulj
あなたの実際のユースケースのスパースタイの尺度は何ですか?ゼロ以外の割合? – Divakar