Можливо, цей приклад з 12 різними значеннями масиву допоможе:
In [207]: x=np.arange(12).reshape(3,4).copy()
In [208]: x.flags
Out[208]:
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
...
In [209]: x.T.flags
Out[209]:
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : False
...
Ці C order
значення в тому порядку , що вони були зроблені в. Транспоновану з них не є
In [212]: x.reshape(12,) # same as x.ravel()
Out[212]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
In [213]: x.T.reshape(12,)
Out[213]: array([ 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11])
Ви можете отримати 1d перегляд обох
In [214]: x1=x.T
In [217]: x.shape=(12,)
форму x
також можна змінити.
In [220]: x1.shape=(12,)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-220-cf2b1a308253> in <module>()
----> 1 x1.shape=(12,)
AttributeError: incompatible shape for a non-contiguous array
Але форму транспонування не можна змінити. Значення data
все ще знаходиться в 0,1,2,3,4...
порядку, доступ до якого неможливий, як 0,4,8...
у масиві 1d.
Але копію x1
можна змінити:
In [227]: x2=x1.copy()
In [228]: x2.flags
Out[228]:
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
...
In [229]: x2.shape=(12,)
Перегляд strides
може також допомогти. Кроки - це те, наскільки далеко (у байтах) потрібно пройти крок, щоб перейти до наступного значення. Для двовимірного масиву буде 2 значення кроку:
In [233]: x=np.arange(12).reshape(3,4).copy()
In [234]: x.strides
Out[234]: (16, 4)
Щоб перейти до наступного рядка, виконайте крок 16 байт, лише наступний стовпець 4.
In [235]: x1.strides
Out[235]: (4, 16)
Транспонування просто перемикає порядок кроків. Наступний рядок - лише 4 байти - тобто наступне число.
In [236]: x.shape=(12,)
In [237]: x.strides
Out[237]: (4,)
Зміна форми також змінює кроки - просто переходьте буфер за 4 байти за раз.
In [238]: x2=x1.copy()
In [239]: x2.strides
Out[239]: (12, 4)
Незважаючи на те, x2
виглядає так само , як x1
це має свій власний буфер даних, зі значеннями в іншому порядку. Наступний стовпець тепер має 4 байти, тоді як наступний рядок - 12 (3 * 4).
In [240]: x2.shape=(12,)
In [241]: x2.strides
Out[241]: (4,)
І як і у випадку x
, зміна форми на 1d зменшує кроки до (4,)
.
Адже x1
, маючи дані в 0,1,2,...
порядку, немає 1-го кроку, який дав би 0,4,8...
.
__array_interface__
є ще одним корисним способом відображення інформації про масив:
In [242]: x1.__array_interface__
Out[242]:
{'strides': (4, 16),
'typestr': '<i4',
'shape': (4, 3),
'version': 3,
'data': (163336056, False),
'descr': [('', '<i4')]}
Адреса x1
буфера даних буде такою ж, як і для x
, з якою він надає дані. x2
має іншу адресу буфера.
Ви також можете поекспериментувати з додаванням order='F'
параметра до команд copy
і reshape
.