简单切片形成父数组的视图。视图的步幅通常是父数组步长的倍数。
给定带有步幅(s0, s1)
的2d父数组,带有步幅(s0+s1)
的1D数组给出父数组对角线的视图。
有没有办法在顶级Python / numpy中创建这样的视图?提前谢谢。
答案 0 :(得分:2)
使用as_strided
我可以做你想做的事:
In [298]: X=np.eye(5)
In [299]: X.strides
Out[299]: (40, 8)
In [300]: np.lib.stride_tricks.as_strided(X,shape=(5,),strides=(48,))
Out[300]: array([ 1., 1., 1., 1., 1.])
虽然有些人认为as_strided
离“胆量”更近了一步。比大多数numpy
Python代码。
我可以通过对展平数组进行索引来实现同样的跨越:
In [311]: X.ravel()[::6]
Out[311]: array([ 1., 2., 3., 4., 5.])
(此处X
值已通过view
测试更改。
答案 1 :(得分:2)
如果您使用的是numpy 1.9或更高版本,并且只读视图就足够了,您可以使用numpy.diagonal
。文档字符串表示在numpy的某个未来版本中,numpy.diagonal
将返回读/写视图,但这对您现在没有帮助。如果您需要读/写视图,@ hpaulj建议使用as_strided
将起作用。我建议像
diag = as_strided(a, shape=(min(a.shape),), strides=(sum(a.strides),))
请务必阅读as_strided
docstring的“注释”部分。
答案 2 :(得分:0)
对于适用于2个以上维度的版本:
import numpy as np
def diagonal_view(array, axis1=0, axis2=1):
"""Return a view of the array diagonal."""
assert array.ndim >= 2
axis1, axis2 = min([axis1, axis2]), max([axis1, axis2])
shape = list(array.shape)
new = min([shape[axis1], shape[axis2]])
shape.pop(axis1)
shape.pop(axis2 - 1)
shape.append(new)
strides = list(array.strides)
new = strides[axis1] + strides[axis2]
strides.pop(axis1)
strides.pop(axis2 - 1)
strides.append(new)
diag = np.lib.stride_tricks.as_strided(array, shape=shape, strides=strides)
return diag
def test_diagonal_view():
# test correspondence with np.diagonal
for array in [
np.random.randn(10, 4),
np.random.randn(10, 4).T,
np.random.randn(10, 4, 8),
np.random.randn(10, 4, 8).T,
np.random.randn(10, 4, 8).swapaxes(0, 1),
np.random.randn(3, 4, 8, 5),
np.random.randn(3, 4, 8, 5).swapaxes(0, 2),
]:
for axis1 in range(array.ndim):
for axis2 in range(array.ndim):
if axis1 != axis2:
result = diagonal_view(array, axis1=axis1, axis2=axis2)
# compare with np.diagonal
reference = np.diagonal(array, axis1=axis1, axis2=axis2)
np.testing.assert_array_equal(result, reference)
# test that this is a modifiable view
result += 1
reference = np.diagonal(array, axis1=axis1, axis2=axis2)
np.testing.assert_array_equal(result, reference)
test_diagonal_view()