import numpy as np
def using_tile_and_stride():
arr = np.tile(np.array([10,20,30,0,0,0], dtype='float'), (4,1))
row_stride, col_stride = arr.strides
arr.strides = row_stride-col_stride, col_stride
return arr
In [108]: using_tile_and_stride()
Out[108]:
array([[ 10., 20., 30., 0., 0., 0.],
[ 0., 10., 20., 30., 0., 0.],
[ 0., 0., 10., 20., 30., 0.],
[ 0., 0., 0., 10., 20., 30.]])
inne, wolniejsze alternatywy obejmują:
import numpy as np
import numpy.lib.stride_tricks as stride
def using_put():
arr = np.zeros((4,6), dtype='float')
a, b, c = 10, 20, 30
nrows, ncols = arr.shape
ind = (np.arange(3) + np.arange(0,(ncols+1)*nrows,ncols+1)[:,np.newaxis]).ravel()
arr.put(ind, [a, b, c])
return arr
def using_strides():
return np.flipud(stride.as_strided(
np.array([0, 0, 0, 10, 20, 30, 0, 0, 0], dtype='float'),
shape=(4, 6), strides = (8, 8)))
Jeśli używasz using_tile_and_stride
pamiętać, że tablica jest odpowiednia tylko dla tylko do odczytu. W przeciwnym razie, jeśli były, aby spróbować zmodyfikować tablicę, może być zaskoczony, gdy wiele miejsca array zmienić jednocześnie:
In [32]: arr = using_tile_and_stride()
In [33]: arr[0, -1] = 100
In [34]: arr
Out[34]:
array([[ 10., 20., 30., 0., 100.],
[ 100., 10., 20., 30., 0.],
[ 0., 0., 10., 20., 30.],
[ 30., 0., 0., 10., 20.]])
Można to obejść przez powrót np.ascontiguousarray(arr)
zamiast tylko arr
, ale potem using_tile_and_stride
byłby wolniejszy niż using_put
. Więc jeśli chcesz zmodyfikować tablicę, lepszym wyborem będzie using_put
.
Jest to świetne rozwiązanie. Spośród wszystkich proponowanych rozwiązań, ma dobrą równowagę pomiędzy prostotą a wydajnością. Chciałbym, żeby funkcja numagowała diag pozwalała mi określić, która super/sub diagonalna chcę zaktualizować, a następnie zwróć widok przekątnej. Byłoby to wówczas najbardziej intuicyjne i najszybsze. –