2

小さな例で説明しましょう。

>>> x = np.array([[1,2], [3,4], [5,6], [7,8]])
>>> x
array([[1, 2],
       [3, 4],
       [5, 6],
       [7, 8]])

フォームを持つ新しい配列が必要です

array([[0, 0, 1, 2, 3, 4],
       [1, 2, 3, 4, 5, 6],
       [3, 4, 5, 6, 7, 8],
       [5, 6, 7, 8, 0, 0]])

ここでは、コンテキストのサイズは +/-1 ですが、変数のままにしたいと思います。

これまでのところ、元の配列にゼロを追加しています。

>>> y = np.concatenate((np.zeros((1, 2)), x, np.zeros((1, 2))), axis=0)
>>> y
array([[ 0.,  0.],
       [ 1.,  2.],
       [ 3.,  4.],
       [ 5.,  6.],
       [ 7.,  8.],
       [ 0.,  0.]])

そして、新しいサイズの行を読み取って、値を新しい配列に入れます。

>>> z = np.empty((x.shape[0], x.shape[1]*3))
>>> for i in range(x.shape[0]): z[i] = y[i:i+3].flatten()

そのようなものは機能しますが、遅く、醜く、非Pythonicだと思います。この再配置を行うためのより良い方法を考えられますか? インプレースっぽいソリューションのための追加のサムアップ:)

4

2 に答える 2

2

を使用するオプションがありますが、stride_tricksこれが最良の答えであるとは言いません。「最も効率的な方法」ですが、読みやすさと火遊びを考慮すると、その方法が常に最善であるとは限らないためです。

# We make it flat (and copy if necessary) to be on the safe side, and because
# it is more obvious this way with stride tricks (or my function below):
y = y.ravel()

# the new shape is (y.shape[0]//2-2, 6). When looking at the raveled y, the first
# dimension takes steps of 2 elements (so y.strides[0]*2) and the second is
# just the old one:
z = np.lib.stride_tricks.as_strided(y, shape=(y.shape[0]//2-2, 6),
                                       strides=(y.strides[0]*2, y.strides[0]))

zこれは単なるビューであることに注意してz.copy()ください。編集する前に予期しないことを避けるために使用してください。そうしないと、この例では、いずれかを編集するとすべての 1 が変更されます。利点として、これを「インプレース」で意味する場合、要素を変更できるようにyなり、z変更も行われます。

この魔法をもっと使いたい場合は、 https://gist.github.com/3430219rolling_windowから私の関数をチェックしてください。これは最後の行を次のように置き換えます:

# 6 values long window, but only every 2nd step on the original array:
z = rolling_window(y, 6, asteps=2)

重要: np.lib.stride_tricks.as_strided通常、それ自体は安全ではなく、セグメンテーション違反を引き起こす可能性があるため、注意して使用する必要があります。

于 2012-08-23T19:55:41.983 に答える
1

インデックス作成が機能するはずです:

y = np.concatenate(([0, 0], x.flat, [0, 0]))  # or use np.pad with NumPy 1.7
i = np.tile(np.arange(6), (4, 1)) + np.arange(4)[:, None] * 2
z = y[i]

必要に応じて、明らかにこれは適切です。

これがどのように機能するかを確認するには、iインデックス配列を見てください。

array([[ 0,  1,  2,  3,  4,  5],
       [ 2,  3,  4,  5,  6,  7],
       [ 4,  5,  6,  7,  8,  9],
       [ 6,  7,  8,  9, 10, 11]])

柔軟にする:

context = 1
h, w = x.shape
zeros = np.zeros((context, w), dtype=x.dtype)
y = np.concatenate((zeros, x, zeros), axis=0).flat
i = np.tile(np.arange(w + 2 * context * w), (h, 1)) + np.arange(h)[:, None] * w
z = y[i]
于 2012-08-23T19:35:15.160 に答える