資料:https://stackoverflow.com/questions/22053050/difference-between-numpy-array-shape-r-1-and-r
這篇文章是我偶然點開的stackoverflow上的一個問題,是關於numpy中的array對象的。numpy在python、機器學習界的重要地位不用多說了吧。在此把這個回答翻譯領悟一下,以供學習。
注:僅為學習目的翻譯,作者是Gareth Rees,可能會有我自己的修改。
For learning purposes only !!!
看待NumPy arrays的最好方式是把它分為兩個部分,一個數據緩沖區包含了一塊raw elements(原始元素),以及一個view(我叫它視窗)來描述解釋數據緩沖區。
例如如果我們創建一個包含12個整型數的數組 a :
>>> a = numpy.arange(12) >>> a array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
則 a 包含了一個數據緩沖區,儲存成如下的樣子:
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
以及一個視窗,定義了怎樣解釋數據:
>>> a.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
>>> a.dtype
dtype('int64')
>>> a.itemsize
8
>>> a.strides
(8,)
>>> a.shape
(12,)
在這里,shape=(12,)意味着這個數組僅僅被一個索引支配:從0到11。從概念上講,假如我們使用這個單獨的索引給 a 打上標簽,那么 a 將看起來像這樣:
i= 0 1 2 3 4 5 6 7 8 9 10 11 ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
reshape一個數組的操作不會改變數據緩沖區,而是創建一個新的解釋數據的視窗。
>>> b = a.reshape((3, 4))
上面的操作創建了一個和 a 擁有同一個數據緩沖區的 b ,但是現在它被兩個索引所支配(two-dimensions indexed)。一個從0到2,一個從0到3,假如我們給數據打上標簽,b 看起來會像這樣:
i= 0 0 0 0 1 1 1 1 2 2 2 2 j= 0 1 2 3 0 1 2 3 0 1 2 3 ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
這也意味着:
>>> b[2,1] 9
第二個索引比第一個索引變化的快,假如想反過來,可以使用下面的參數創造一個數組 c
>>> c = a.reshape((3, 4), order='F')
補充:order='F'或者order='C'表示數組的索引方式分別像C語言或者Fortran,'C'是缺省值
這樣會產生一個有如下索引的數組:
i= 0 1 2 0 1 2 0 1 2 0 1 2 j= 0 0 0 1 1 1 2 2 2 3 3 3 ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
意味着
>>> c[2,1] 5
有了前面的鋪墊,就很容易理解下面一個例子了:
>>> d = a.reshape((12, 1))
數組 d 被兩個索引支配,第一個索引從0到11,第二個索引始終為0:
i= 0 1 2 3 4 5 6 7 8 9 10 11 j= 0 0 0 0 0 0 0 0 0 0 0 0 ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
所以:
>>> d[10,0] 10
一個展平的一維數組從某種意義上來說是自由的,所以我們完全可以自己定義每一維的大小:
>>> e = a.reshape((1, 2, 1, 6, 1))
上面的操作創建了一個這樣的數組:
i= 0 0 0 0 0 0 0 0 0 0 0 0 j= 0 0 0 0 0 0 1 1 1 1 1 1 k= 0 0 0 0 0 0 0 0 0 0 0 0 l= 0 1 2 3 4 5 0 1 2 3 4 5 m= 0 0 0 0 0 0 0 0 0 0 0 0 ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
所以:
>>> e[0,1,0,0,0] 6
