10

次のようなリストのリストで構成されるマトリックスがあるとします。

>>> LoL=[list(range(10)) for i in range(10)]
>>> LoL
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]

また、同じ構造のnumpy行列が次のように呼ばれていると仮定しLoLaます。

>>> LoLa=np.array(LoL)

numpyを使用すると、次のようにこの行列の部分行列を取得できます。

>>> LoLa[1:4,2:5]
array([[2, 3, 4],
       [2, 3, 4],
       [2, 3, 4]])

次のように、純粋なPythonでnumpyマトリックススライスを複製できます。

>>> r=(1,4)
>>> s=(2,5)
>>> [LoL[i][s[0]:s[1]] for i in range(len(LoL))][r[0]:r[1]]
[[2, 3, 4], [2, 3, 4], [2, 3, 4]] 

これは、世界で最も読みやすいものでも、最も効率的なものでもありません:-)

質問:(純粋なPythonで)任意の行列をサブ行列としてスライスする簡単な方法はありますか?

4

4 に答える 4

15
In [74]: [row[2:5] for row in LoL[1:4]]
Out[74]: [[2, 3, 4], [2, 3, 4], [2, 3, 4]]

次のサブクラスを定義することで、NumPyの構文を模倣することもできますlist

class LoL(list):
    def __init__(self, *args):
        list.__init__(self, *args)
    def __getitem__(self, item):
        try:
            return list.__getitem__(self, item)
        except TypeError:
            rows, cols = item
            return [row[cols] for row in self[rows]]

lol = LoL([list(range(10)) for i in range(10)])
print(lol[1:4, 2:5])

また、

[[2, 3, 4], [2, 3, 4], [2, 3, 4]]

サブクラスを使用してLoLも、速度テストには勝ちません。

In [85]: %timeit [row[2:5] for row in x[1:4]]
1000000 loops, best of 3: 538 ns per loop
In [82]: %timeit lol[1:4, 2:5]
100000 loops, best of 3: 3.07 us per loop

しかし、速度がすべてではありません。読みやすさがより重要な場合があります。

于 2013-03-27T01:46:15.883 に答える
5

1つは、オブジェクトを直接使用できるためslice、読みやすさとパフォーマンスの両方に少し役立ちます。

r = slice(1,4)
s = slice(2,5)
[LoL[i][s] for i in range(len(LoL))[r]]

また、リストのリストを直接繰り返す場合は、次のように記述できます。

[row[s] for row in LoL[r]]
于 2013-03-27T01:49:19.703 に答える
1

これを行う、

submat = [[mat [i] [j] for j in range(index1、index2)] for i in range(index3、index4)]

サブマットは、元の大きな行列の長方形(index3==index1およびindex2==index4の場合は正方形)のチャンクになります。

于 2014-09-11T22:51:27.087 に答える
0

簡単かどうかはわかりませんが、アイデアをテーブルに投げさせてください。

from itertools import product
r = (1+1, 4+1)
s = (2+1, 5+1)
array = [LoL[i][j] for i,j in product(range(*r), range(*s))]

これは、必要な部分行列のフラット化されたバージョンです。

于 2013-03-27T01:59:32.840 に答える