列表理解或 map() 或 for 循环访问前一行来操作数组
List comprehension or map() or for loop for accessing previous row to manipulate array
假设我有一个数组(numpy 数组)A = [[1, 2, 3], [0, 0, 0], [0, 0, 0]]
,我想将零行操作成 [2, 3, 1], [3, 1, 2]
,所以最终数组是 A = [[1, 2, 3], [2, 3, 1], [3, 1, 2]]
我可以使用如下所示的 for 循环来完成此操作:
a = np.array([[1, 2, 3],[0, 0, 0],[0, 0, 0]])
for i in xrange(1,3):
a[i]=np.concatenate([a[i-1][1:], a[i-1][:1]], axis=1)
获取上一行,连接[1:]和[:1],分配结果作为下一行。
我有很多这样的循环,我想知道我是否可以摆脱 for 循环,从而获得更快的速度(也许?)。有没有办法使用列表理解或地图来做到这一点?除了第一行之外,我的 A 数组不必是零行的 nxn,它可以只是 A = [1, 2, 3, ..., n]
如果有一种方法我可以 创建 使用 A 的 nx3 数组作为初学者,继续获取前一行并将它的 [m:]
和 [:m]
连接起来。 (任意米)
或者是的,也许 for 循环是执行此类操作的 only/correct 方式。我想知道是不是。
for 循环是最简单的方法,列表理解或映射不会获得太多速度。但是您可以使用 roll
而不是串联:
a = numpy.array([1, 2, 3])
a = numpy.vstack([numpy.roll(a, -i) for i in xrange(3)])
我建议使用 python zip
内置 function.You 的方法可以将您的数组与其自身连接起来,然后您只需挑选每 3 个跟随的元素!
>>> A=np.arange(1,4)
>>> B=np.concatenate((A,A))
>>> B
array([1, 2, 3, 1, 2, 3])
>>> np.array(zip(B,B[1:],B[2:])[:-1])
array([[1, 2, 3],
[2, 3, 1],
[3, 1, 2]])
您可以将此方法用于更长的数组:
>>> A=np.arange(1,6)
>>> B=np.concatenate((A,A))
>>> np.array(zip(B,B[1:],B[2:])[:-1])
array([[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 1],
[5, 1, 2],
[1, 2, 3],
[2, 3, 4]])
>>>
这是避免 Python 中循环的解决方案。
您可以通过创建一个索引数组来获得所需的输出,您可以使用它来索引您的原始数组:
In [40]:
a = np.arange(1, 4)
i = np.arange(len(a))
indexer = i - np.atleast_2d(i).T
a[indexer]
Out[40]:
array([[1, 2, 3],
[3, 1, 2],
[2, 3, 1]])
这适用于任何 a
。 indexer
数组是所需输出的大小,是使用广播创建的。在这种情况下,它看起来像
array([[ 0, 1, 2],
[-1, 0, 1],
[-2, -1, 0]])
以下是与循环方法的一些时间比较,表明它要快得多:
In [69]:
%%timeit
a = np.arange(1, 11)
i = np.arange(0, len(a), step_size)
indexer = i - np.atleast_2d(i).T
a[indexer]
10000 loops, best of 3: 14.7 µs per loop
In [70]:
%%timeit
a = numpy.arange(1, 11)
a = numpy.vstack([numpy.roll(a, -i) for i in xrange(len(a))])
10000 loops, best of 3: 143 µs per loop
In [71]:
%%timeit
a = np.arange(1, 101)
i = np.arange(0, len(a), step_size)
indexer = i - np.atleast_2d(i).T
a[indexer]
10000 loops, best of 3: 80 µs per loop
In [72]:
%%timeit
a = numpy.arange(1, 101)
a = numpy.vstack([numpy.roll(a, -i) for i in xrange(len(a))])
1000 loops, best of 3: 1.44 ms per loop
这样还有一个好处就是可以重复使用indexer
以同样的方式操作其他相同长度的数组。如果你真的想要,你也可以将它写入磁盘。
对于任意步长 m
,您可以执行以下操作:
In [61]:
m = 2
a = np.arange(1, 4)
i = np.arange(len(a))
indexer = (i - m * np.atleast_2d(i).T) % len(a)
a[indexer]
Out[61]:
array([[1, 2, 3],
[2, 3, 1],
[3, 1, 2]])
假设我有一个数组(numpy 数组)A = [[1, 2, 3], [0, 0, 0], [0, 0, 0]]
,我想将零行操作成 [2, 3, 1], [3, 1, 2]
,所以最终数组是 A = [[1, 2, 3], [2, 3, 1], [3, 1, 2]]
我可以使用如下所示的 for 循环来完成此操作:
a = np.array([[1, 2, 3],[0, 0, 0],[0, 0, 0]])
for i in xrange(1,3):
a[i]=np.concatenate([a[i-1][1:], a[i-1][:1]], axis=1)
获取上一行,连接[1:]和[:1],分配结果作为下一行。
我有很多这样的循环,我想知道我是否可以摆脱 for 循环,从而获得更快的速度(也许?)。有没有办法使用列表理解或地图来做到这一点?除了第一行之外,我的 A 数组不必是零行的 nxn,它可以只是 A = [1, 2, 3, ..., n]
如果有一种方法我可以 创建 使用 A 的 nx3 数组作为初学者,继续获取前一行并将它的 [m:]
和 [:m]
连接起来。 (任意米)
或者是的,也许 for 循环是执行此类操作的 only/correct 方式。我想知道是不是。
for 循环是最简单的方法,列表理解或映射不会获得太多速度。但是您可以使用 roll
而不是串联:
a = numpy.array([1, 2, 3])
a = numpy.vstack([numpy.roll(a, -i) for i in xrange(3)])
我建议使用 python zip
内置 function.You 的方法可以将您的数组与其自身连接起来,然后您只需挑选每 3 个跟随的元素!
>>> A=np.arange(1,4)
>>> B=np.concatenate((A,A))
>>> B
array([1, 2, 3, 1, 2, 3])
>>> np.array(zip(B,B[1:],B[2:])[:-1])
array([[1, 2, 3],
[2, 3, 1],
[3, 1, 2]])
您可以将此方法用于更长的数组:
>>> A=np.arange(1,6)
>>> B=np.concatenate((A,A))
>>> np.array(zip(B,B[1:],B[2:])[:-1])
array([[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 1],
[5, 1, 2],
[1, 2, 3],
[2, 3, 4]])
>>>
这是避免 Python 中循环的解决方案。 您可以通过创建一个索引数组来获得所需的输出,您可以使用它来索引您的原始数组:
In [40]:
a = np.arange(1, 4)
i = np.arange(len(a))
indexer = i - np.atleast_2d(i).T
a[indexer]
Out[40]:
array([[1, 2, 3],
[3, 1, 2],
[2, 3, 1]])
这适用于任何 a
。 indexer
数组是所需输出的大小,是使用广播创建的。在这种情况下,它看起来像
array([[ 0, 1, 2],
[-1, 0, 1],
[-2, -1, 0]])
以下是与循环方法的一些时间比较,表明它要快得多:
In [69]:
%%timeit
a = np.arange(1, 11)
i = np.arange(0, len(a), step_size)
indexer = i - np.atleast_2d(i).T
a[indexer]
10000 loops, best of 3: 14.7 µs per loop
In [70]:
%%timeit
a = numpy.arange(1, 11)
a = numpy.vstack([numpy.roll(a, -i) for i in xrange(len(a))])
10000 loops, best of 3: 143 µs per loop
In [71]:
%%timeit
a = np.arange(1, 101)
i = np.arange(0, len(a), step_size)
indexer = i - np.atleast_2d(i).T
a[indexer]
10000 loops, best of 3: 80 µs per loop
In [72]:
%%timeit
a = numpy.arange(1, 101)
a = numpy.vstack([numpy.roll(a, -i) for i in xrange(len(a))])
1000 loops, best of 3: 1.44 ms per loop
这样还有一个好处就是可以重复使用indexer
以同样的方式操作其他相同长度的数组。如果你真的想要,你也可以将它写入磁盘。
对于任意步长 m
,您可以执行以下操作:
In [61]:
m = 2
a = np.arange(1, 4)
i = np.arange(len(a))
indexer = (i - m * np.atleast_2d(i).T) % len(a)
a[indexer]
Out[61]:
array([[1, 2, 3],
[2, 3, 1],
[3, 1, 2]])