5

配列があり、その配列内の要素がその配列内の他の要素以上であるかどうかを確認したいと思います。forループを2つ実行することもできますが、配列の長さが10,000以上であるため、非常に遅いプログラムが作成されました。とにかく私はこれをより速くすることができますか?

[編集]私はそれが私が見ている要素の後に来る要素以上であるかどうかを確認するためにそれを必要とするだけです、そしてもしそうなら、私はそれがインデックスであるかを知る必要があります。

[編集]現在の解決策は私が必要としているものに対して機能していないので、私は私の問題をより明確に再説明するつもりです。まず、ここにいくつかのコードがあります

x=linspace(-10, 10, 10000)
t=linspace(0,5,10000)

u=np.exp(-x**2)

k=u*t+x

そこで、x配列を取得し、それをガウス分布に入れてその高さを取得します。次に、その高さに基づいて、そのx値が空間を伝播する速度を取得します。これはkで求められます。私の問題は、ガウス関数がいつ二重値関数になるか(つまり、ショックが発生するか)を見つける必要があるということです。argmaxソリューションを実行する場合、ゼロに非常に近いため、常にkの最後の値を取得します。関数でdouble値を与える要素の後に、最初の値が必要です。

[編集]小さな例

x=[0,1,2,3,4,5,6,7,8,9,10] #Input 
k=[0,1,2,3,4,5,6,5,4,10] #adjusted for speed

output I want
in this case, 5 is the first number that goes above a number that comes after it.
So I need to know the index of where 5 is located and possibly the index 
of the number that it is greater than
4

3 に答える 3

5

後の値よりも大きい最初の値は、必然的に極小値の最小値に対応します。

k = np.array([0,1,2,3,4,5,6,5,4,10])
lm_i = np.where(np.diff(np.sign(np.diff(k))) > 0)[0] + 1
mlm = np.min(k[lm_i])
mlm_i = lm_i[np.argmin(k[lm_i])]

後の値より大きい最初の値のインデックスは、その最小局所最小値より大きい最初のインデックスです。

i = np.where(k > mlm)[0][0]

解のプロット

(グラフが接線で水平線と交差しているように見えることは無視してください。これは単なる表示上のアーティファクトです。)

ワンライナーとして:

np.where(k > np.min(k[np.where(np.diff(np.sign(np.diff(k))) > 0)[0] + 1]))[0][0]

これは約であることに注意してください。完全にベクトル化されているため、ルートのソリューションよりも 1000 倍高速です。

%timeit np.where(k > np.min(k[np.where(np.diff(np.sign(np.diff(k))) > 0)[0] + 1]))[0][0]
1000 loops, best of 3: 228 us per loop
于 2013-03-11T16:35:46.740 に答える
3

ecatmur よりも約 25% 高速なベクトル化されたソリューション:

np.where(k > np.min(k[np.where(np.diff(k) < 0)[0][0]:]))[0][0]

単純なアプローチ:

next(i for i in np.arange(len(arr)) if arr[i:].argmin() != 0)
于 2013-03-11T15:09:31.833 に答える
2

編集 実際には、10,000アイテムの配列で操作するよりも、10,000アイテムのpython forループを使用する方が安価です::

In [14]: np.where(np.array([True if np.all(k[:j] <= k[j]) else
                            False for j in xrange(len(k))]) == 0)
Out[14]: (array([5129, 5130, 5131, ..., 6324, 6325, 6326]),)

In [15]: %timeit np.where(np.array([True if np.all(k[:j] <= k[j]) else
                                    False for j in xrange(len(k))]) == 0)
1 loops, best of 3: 201 ms per loop

メモリに関する限りコストがかかりますが、ブロードキャストを使用して検索をベクトル化できます。もしあなたがそうするなら:

>>> k <= k[:, None]
array([[ True, False, False, ..., False, False, False],
       [ True,  True, False, ..., False, False, False],
       [ True,  True,  True, ..., False, False, False],
       ..., 
       [ True,  True,  True, ...,  True, False, False],
       [ True,  True,  True, ...,  True,  True, False],
       [ True,  True,  True, ...,  True,  True,  True]], dtype=bool)

戻り値は bool の配列で、位置にあるアイテムが より小さいか等しい[i, j]かを示します。次のように使用できる場合:k[j]k[i]np.cumprod

>>> np.cumprod(k <= k[:, None], axis=1)
array([[1, 0, 0, ..., 0, 0, 0],
       [1, 1, 0, ..., 0, 0, 0],
       [1, 1, 1, ..., 0, 0, 0],
       ..., 
       [1, 1, 1, ..., 1, 0, 0],
       [1, 1, 1, ..., 1, 1, 0],
       [1, 1, 1, ..., 1, 1, 1]])

ここで、 item in positionは、が 内のすべてのアイテムより小さいか等しい[i, j]かを示します。その行列の対角を取る場合:k[j]k[:i]

>>> np.cumprod(k <= k[:, None], axis=1)[np.diag_indices(k.shape[0])]
array([1, 1, 1, ..., 1, 1, 1])

位置の項目は、その前にあるすべての項目よりも小さいか等しい[i]かを示します。k[i]その配列がゼロの場所を見つけます。

>>> np.where(np.cumprod(k <= k[:, None],
...                     axis=1)[np.diag_indices(k.shape[0])] == 0)
(array([5129, 5130, 5131, ..., 6324, 6325, 6326]),)

希望の条件を満たすすべての値のインデックスが得られます。

最初のものだけに興味がある場合:

>>> np.argmax(np.cumprod(k <= k[:, None],
...                      axis=1)[np.diag_indices(k.shape[0])] == 0)
5129

これは軽い操作ではありませんが、すべてのブール配列に適合するメモリがあれば、あまり長く待たされることはありません。

In [3]: %timeit np.argmax(np.cumprod(k <= k[:, None],
                                     axis=1)[np.diag_indices(k.shape[0])] == 0)
1 loops, best of 3: 948 ms per loop
于 2013-03-11T16:23:39.040 に答える