45060


初めて質問いたします。初心者ですがよろしくお願いいたします。

（行いたい操作）  
まず、リストにnumpyで生成した行列を入れて、そのリストをfor文のコンテナとします。そして繰り返し処理でリストから取り出され変数に代入されている行列自身とは異なる行列（位置が異なれば行列の要素が一致しても構わない）をリストから一つランダム抽出して、その２つを表示するという操作をしたいです。

リストにはすべての要素が同じ行列が含まれても構いません（つまり１回の処理ごとに表示される２つの行列が同じでも構いません）。「今、リストから取り出されてfor文の変数に代入されている行列と同じ行列」を元のリストから一つ除いたリストから要素（行列）をランダムに一つ取り出すという操作をしたいのです。

以下、私の書いたコードなのですが、

[code]

    import numpy as np
    import random
    import copy
    
    a=np.zeros((2,2))
    b=np.ones((2,2))
    c=np.array([[2.,2.],[2.,2.]])
    d=np.array([[3.,3.],[3.,3.]])
    e=np.zeros((2,2))
    
    f=[a,b,c,d,e]
    
    for i in f:
        g=copy.copy(f)
        g.remove(i)
        h=random.choice(g)
        print(i,h)
    
[/code]

「今、for文の変数iに代入されている行列」を元のリスト(f)から除いたリスト(g)を作りたくて  
g.remove(i) としたのですが、

[code]

    ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
    
[/code]

とエラーが出てしまいます。行列の要素の比較のエラーだと思うのですが、要素としての行列をコンテナから削除するという方法がわかりません。要素が全て一致する行列が複数存在してもそのうち一つの行列だけリストから除けられればいいです。勉強を初めて日が浅いため稚拙なコードでございますが、何卒ご教示お願いいたします。


CC BY-SA 4.0
2018-06-25T10:00:41.743
45053
2018-06-25T14:38:02.173
2018-06-25T14:02:26.320
29063
29063
question
python numpy
行列が要素であるコンテナの、要素の除去の操作


NumPy array 同士の等価性比較には
[`numpy.array_equal()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.array_equal.html)
または
[`numpy.array_equiv()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.array_equiv.html#numpy.array_equiv)
を使います。Python の生のリストの
[`remove()`](https://docs.python.org/ja/3/tutorial/datastructures.html#more-
on-lists) メソッドは `==` で比較しており、NumPy array 同士を単に `==` で比較すると質問文にあるエラーが出ます。

そこで `==` の代わりに `numpy.array_equal()` を使うような `remove()`
関数を自作することになります。これはたとえば以下のように書けます。

[code]

    def np_arr_remove(lst, elem):
        for i, arr in enumerate(lst):
            if np.array_equal(arr, elem):
                del lst[i]
                return
        raise ValueError('np_arr_remove: {} is not in list'.format(elem))
    
[/code]

(ただし上の関数は Python の生のループを使っているのでサイズが極端に大きいリストに対しては遅いです。)


CC BY-SA 4.0
2018-06-25T11:34:42.113
45056
2018-06-25T14:38:02.173
2018-06-25T14:38:02.173
19110
19110
45053
answer


`for`文で`enumerate`を使えばインデクスも取得できるので、リストの要素を削除するのに`remove`ではなく`pop`が使えます。`pop`の方だとエラーが出ません。

[code]

    for i, arr in enumerate(f):
        g=copy.copy(f)
        g.pop(i)
        h=random.choice(g)
        print(arr, h)
    
[/code]

また、fをコピーしなくても、次のようにインデックスだけで処理することもできます。

[code]

    for i, arr in enumerate(f):
        l = list(range(len(f)))
        l.pop(i)
        h=random.choice(l)
        print(arr, f[h])
    
[/code]


CC BY-SA 4.0
2018-06-25T14:05:53.400
45060
2018-06-25T14:17:39.920
2018-06-25T14:17:39.920
15171
15171
45053
answer