假设我有一个由列表组成的矩阵,如下所示:
>>> 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]]
我也假设我有一个名为LoLa
的相同结构的numpy矩阵:
>>> 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中)将任意矩阵切割为子矩阵?
答案 0 :(得分:13)
In [74]: [row[2:5] for row in LoL[1:4]]
Out[74]: [[2, 3, 4], [2, 3, 4], [2, 3, 4]]
你也可以通过定义list
的子类来模仿NumPy的语法:
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
但速度并非一切 - 有时可读性更重要。
答案 1 :(得分:5)
首先,您可以直接使用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]]
答案 2 :(得分:1)
这样做,
submat = [[mat [i] [j] for j in range(index1,index2)] for i in range(index3,index4)]
submat将是原始大矩阵的矩形(正方形,如果index3 == index1和index2 == index4)。
答案 3 :(得分: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))]
这是你想要的子矩阵的扁平化版本。