web-dev-qa-db-ja.com

numpyインデックス配列の値をリストの値に置き換えます

Numpy配列とリストがあるとします:

>>> a = np.array([1,2,2,1]).reshape(2,2)
>>> a
array([[1, 2],
       [2, 1]])
>>> b = [0, 10]

配列の値を置き換えて、1を0に、2を10に置き換えたいと思います。

ここで同様の問題が見つかりました- http://mail.python.org/pipermail//tutor/2011-September/085392.html

しかし、このソリューションを使用して:

for x in np.nditer(a):
    if x==1:
        x[...]=x=0
    Elif x==2:
        x[...]=x=10

エラーをスローします:

ValueError: assignment destination is read-only

Numpy配列に実際に書き込むことができないためだと思います。

追伸numpy配列の実際のサイズは514 x 504で、リストのサイズは8です。

19
abudis

値を1つずつ置き換える代わりに、次のように配列全体を再マップすることができます。

import numpy as np
a = np.array([1,2,2,1]).reshape(2,2)
# palette must be given in sorted order
palette = [1, 2]
# key gives the new values you wish palette to be mapped to.
key = np.array([0, 10])
index = np.digitize(a.ravel(), palette, right=True)
print(key[index].reshape(a.shape))

利回り

[[ 0 10]
 [10  0]]

上記のアイデアに対するクレジットは@JoshAdelに送られます 。私の元の答えよりもはるかに高速です:

import numpy as np
import random
palette = np.arange(8)
key = palette**2
a = np.array([random.choice(palette) for i in range(514*504)]).reshape(514,504)

def using_unique():
    palette, index = np.unique(a, return_inverse=True)
    return key[index].reshape(a.shape)

def using_digitize():
    index = np.digitize(a.ravel(), palette, right=True)
    return key[index].reshape(a.shape)

if __name__ == '__main__':
    assert np.allclose(using_unique(), using_digitize())

この方法で2つのバージョンのベンチマークを行いました。

In [107]: %timeit using_unique()
10 loops, best of 3: 35.6 ms per loop
In [112]: %timeit using_digitize()
100 loops, best of 3: 5.14 ms per loop
19
unutbu

まあ、あなたが必要なのは

a[a==2] = 10 #replace all 2's with 10's
30
alex_jordan

Numpyの読み取り専用配列は書き込み可能にできます。

nArray.flags.writeable = True

これにより、次のような割り当て操作が可能になります。

nArray[nArray == 10] = 9999 # replace all 10's with 9999's

本当の問題は割り当て自体ではなく、書き込み可能なフラグでした。

22
DorinPopescu

np.choose(idx, vals)を使用することもできます。ここで、idxは、valsのどの値をその場所に配置するかを示すインデックスの配列です。ただし、インデックスは0ベースでなければなりません。また、idxが整数データ型であることを確認してください。だからあなたはする必要があります:

np.choose(a.astype(np.int32) - 1, b)
0
jns

Numpy関数placeを使用した別のソリューションを見つけました。 (ドキュメント ここ

あなたの例でそれを使用する:

>>> a = np.array([1,2,2,1]).reshape(2,2)
>>> a
array([[1, 2],
   [2, 1]])
>>> np.place(a, a==1, 0)
>>> np.place(a, a==2, 10)
>>> a
array([[ 0, 10],
       [10,  0]])
0
Linda

フラグを設定することも、マスクを使用して値を変更することもできませんでした。最後に、配列のコピーを作成しました。

a2 = np.copy(a)
0
Paul Bendevis