https://docs.scipy.org/doc/nu...html
ndarrays可使用標準Python x[obj]
語法對其進行索引 ,其中x
是數組,obj
是選擇方式。有三種可用的索引:字段訪問,基本切片,高級索引。到底是哪個取決於obj
。python
注意
在Python中,x[(exp1, exp2, ..., expN)]
至關於x[exp1, exp2, ..., expN];
後者只是前者的語法糖。
基本切片將 Python 的切片基本概念擴展到 N 維。當obj
是一個slice對象(由括號內的start:stop:step
符號構造)、整數或切片對象和整數的元組時,會發生基本切片。也包括省略號(三個點)和newaxis對象。數組
從版本1.15.0開始不推薦使用:爲了保持向後兼容Numeric
中的常見用法,若是選擇對象是包含 slice 對象、省略號,或 newaxis 對象的任何非 nararray 和非元組序列(例如 list),則也會啓動基本切片,但不適用於整數數組或其餘嵌入序列。安全
使用 N 個整數進行索引的最簡單狀況返回表示相應項的數組標量。正如在 Python 中,全部下標是從零開始:對我個索引你,取值範圍爲 $$ 0 \le n_i < d_i $$ 其中d_i是 個人陣列的形狀的個元素。負指數被解釋爲從數組的末尾開始計數(即,若是 n_i <0,則意味着n_i + d_i)。函數
基本切片生成的全部數組始終 是原始數組的視圖。佈局
序列切片的標準規則適用於基於每維的基本切片(包括使用步驟索引)。要記住的一些有用的概念包括:優化
基本切片語法是i:j:k其中我是起始索引, j是中止索引,而且ķ是步驟 $$ k \neq 0 $$ 。這將選擇米元件(在對應的尺寸)與索引值我,i,i+k,...,1 +(m - 1)k, 其中 $$ m = q +(r \ neq0)$$和 q 和 r 是經過j-i 除 k 所得到的商和餘數: $$ j - i = qk + r $$,所以 $$ i +(m - 1)k <j $$。code
例htm
>>> >>> x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> x[1:7:2] array([1, 3, 5])
負i和j被解釋爲n + i和n + j,其中 n是相應維度中的元素數量。負k使得踩踏指向更小的指數。對象
例
>>> >>> x[-2:10] array([8, 9]) >>> x[-3:3:-1] array([7, 6, 5, 4])
假設n是要切片的維度中的元素數。而後,若是我沒有給出其默認值爲0 K> 0和 N - 1爲ķ<0 。若是沒有給出j,則對於k> 0 ,默認爲n ; 對於k <0,默認爲-n-1。若是沒有給出k,則默認爲1.注意, 與此相同,表示沿此軸選擇全部索引。:::
例
>>> >>> x[5:] array([5, 6, 7, 8, 9])
若是選擇元組中的對象數小於 N,則:假定任何後續維。
例
>>> >>> x = np.array([[[1],[2],[3]], [[4],[5],[6]]]) >>> x.shape (2, 3, 1) >>> x[1:2] array([[[4], [5], [6]]])
Ellipsis擴展爲:製做與長度相同的選擇元組所需的對象數x.ndim。可能只存在一個省略號。
例
>>> >>> x[...,0] array([[1, 2, 3], [4, 5, 6]])
newaxis選擇元組中的每一個對象用於將所得選擇的維度擴展一個單位長度維度。添加的維度是newaxis 對象在選擇元組中的位置。
例
>>> >>> x[:,np.newaxis,:,:].shape (2, 1, 3, 1)
整數i返回相同的值,i:i+1 除了返回的對象的維度減小1.特別是,具備第p個元素的整數(和全部其餘條目:)的選擇元組返回具備維度的相應子數組N - 1。若是N = 1, 則返回的對象是數組標量。Scalars中解釋了這些對象。
若是選擇元組具備:除做爲切片對象的第p個條目以外的 全部條目i:j:k,則返回的數組具備經過鏈接由元素i,i + k,...,i +的整數索引返回的子數組造成的維N. m - 1)k <j,
:切片元組中具備多個非條目的基本切片,就像使用單個非:條目重複應用切片同樣,其中:連續地獲取非條目(全部其餘非:條目被替換:)。所以, 在基本切片下的x[ind1,...,ind2,:]行爲xind1。
警告
對於高級索引,上述狀況並不是如此。
您可使用切片來設置數組中的值,可是(與列表不一樣)您永遠不會增加數組。要設置的值的大小 必須(可廣播)爲與其相同的形狀 。x[obj] = valuex[obj]
注意
請記住,切片元組老是能夠構造爲obj 並在x[obj]符號中使用。能夠在構造中使用切片對象來代替[start:stop:step] 符號。例如,x[1:10:5,::-1]也能夠實現爲。這對於構造適用於任意維數組的通用代碼很是有用。obj = (slice(1,10,5), slice(None,None,-1)); x[obj]
numpy.newaxis
該newaxis對象可用於全部切片操做,以建立長度爲1的軸。newaxis是'None'的別名,'None'能夠用來代替相同的結果。
當選擇對象obj是非元組序列對象,ndarray(數據類型爲整數或bool)或具備至少一個序列對象或ndarray(數據類型爲integer或bool)的元組時,將觸發高級索引。高級索引有兩種類型:整數和布爾值。
高級索引始終返回數據的副本(與返回視圖的基本切片造成對比)。
警告
高級索引的定義意味着x[(1,2,3),]根本不一樣於x[(1,2,3)]。後者至關於x[1,2,3]觸發基本選擇,而前者將觸發高級索引。必定要明白爲何會這樣。
同時認識到x[[1,2,3]]將觸發高級索引,而因爲上面提到的不推薦的數字兼容性, x[[1,2,slice(None)]]將觸發基本切片。
整數數組索引容許根據數組的N維索引選擇數組中的任意項。每一個整數數組表示該維度的許多索引。
當索引包含儘量多的整數數組時,索引的數組具備維度,索引是直接的,但與切片不一樣。
高級索引始終做爲一個廣播和迭代:
result[i_1, ..., i_M] == x[ind_1[i_1, ..., i_M], ind_2[i_1, ..., i_M], ..., ind_N[i_1, ..., i_M]]
請注意,結果形狀與(廣播)索引數組形狀相同。ind_1, ..., ind_N
例
從每一行開始,應選擇一個特定元素。行索引是just ,列索引指定要爲相應行選擇的元素。將二者結合使用可使用高級索引解決任務:0, 1, 2
>>> >>> x = np.array([[1, 2], [3, 4], [5, 6]]) >>> x[[0, 1, 2], [0, 1, 0]] array([1, 4, 5])
爲了實現相似於上面的基本切片的行爲,可使用廣播。該功能ix_能夠幫助這種廣播。經過示例能夠最好地理解這一點。
例
從4x3陣列中,應使用高級索引選擇角元素。所以,列是其中之一的全部元素和行是須要選擇的行。要使用高級索引,須要明確選擇全部元素。使用前面解釋的方法能夠寫:0, 2
>>> >>> x = array([[ 0, 1, 2], ... [ 3, 4, 5], ... [ 6, 7, 8], ... [ 9, 10, 11]]) >>> rows = np.array([[0, 0], ... [3, 3]], dtype=np.intp) >>> columns = np.array([[0, 2], ... [0, 2]], dtype=np.intp) >>> x[rows, columns] array([[ 0, 2], [ 9, 11]])
可是,因爲上面的索引數組只是重複自身,所以可使用廣播(比較諸如此類的操做 )來簡化:rows[:, np.newaxis] + columns
>>> >>> rows = np.array([0, 3], dtype=np.intp) >>> columns = np.array([0, 2], dtype=np.intp) >>> rows[:, np.newaxis] array([[0], [3]]) >>> x[rows[:, np.newaxis], columns] array([[ 0, 2], [ 9, 11]])
這種廣播也可使用如下功能實現ix_:
>>> >>> x[np.ix_(rows, columns)] array([[ 0, 2], [ 9, 11]])
請注意,若是沒有np.ix_調用,只會選擇對角線元素,如上例所示。對於使用多個高級索引進行索引,這個差別是最重要的。
結合高級索引和基本索引
當至少有一個slice(:),省略號(...)或newaxis 索引(或者數組的維度多於高級索引)時,行爲可能會更復雜。這就像鏈接每一個高級索引元素的索引結果同樣
在最簡單的狀況下,只有一個單一的指標先進。單個高級索引能夠例如替換切片,而且結果數組將是相同的,可是,它是副本而且能夠具備不一樣的存儲器佈局。當可能時,切片是優選的。
例
>>> >>> x[1:2, 1:3] array([[4, 5]]) >>> x[1:2, [1, 2]] array([[4, 5]])
瞭解狀況的最簡單方法多是考慮結果形狀。索引操做分爲兩部分,即由基本索引(不包括整數)定義的子空間和來自高級索引部分的子空間。須要區分兩種索引組合:
高級索引由切片分隔,Ellipsis或newaxis。例如。x[arr1, :, arr2]
高級索引彼此相鄰。例如但不是 由於在這方面是一個高級索引。x[..., arr1, arr2, :] x[arr1, :, 1]1
在第一種狀況下,高級索引操做產生的維度首先出如今結果數組中,而後是子空間維度。在第二種狀況下,高級索引操做的維度將插入到結果數組中與初始數組中相同的位置(後一種邏輯使簡單的高級索引行爲就像切片同樣)。
例
假設x.shape爲(10,20,30)而且ind是(2,3,4)形索引intp數組,則其形狀爲(10,2,3,4,30),由於(20,)形子空間已被替換具備(2,3,4)形的廣播索引子空間。若是咱們讓i,j,k循環遍佈(2,3,4)形子空間 。此示例產生的結果與。result = x[...,ind,:]result[...,i,j,k,:] = x[...,ind[i,j,k],:]x.take(ind, axis=-2)
例
設x.shape(10,20,30,40,50)並假設ind_1 並ind_2能夠廣播到形狀(2,3,4)。而後 x[:,ind_1,ind_2]具備形狀(10,2,3,4,40,50),由於來自X的(20,30)形子空間已經被索引的(2,3,4)子空間替換。可是,它 x[:,ind_1,:,ind_2]具備形狀(2,3,4,10,30,50),由於在索引子空間中沒有明確的位置,因此它在開頭就被添加了。始終可使用 .transpose()在任何須要的位置移動子空間。請注意,此示例沒法使用複製take。
當obj是布爾類型的數組對象時,會發生此高級索引,例如可能從比較運算符返回。x[obj.nonzero()]如上所述,單個布爾索引數組實際上與obj.nonzero()返回obj.ndim顯示objTrue元素的整數索引數組的元組(長度)相同。可是,它更快。obj.shape == x.shape
若是,返回一個1維數組,該數組填充了與obj 值對應的x元素。搜索順序爲行主,C風格。若是物鏡具備在該外側是的邊界的條目值X,則索引錯誤將被提升。若是obj小於x,則與填充它相同。obj.ndim == x.ndimx[obj]TrueTrueFalse
例
一個常見的用例是過濾所需的元素值。例如,可能但願從陣列中選擇非NaN的全部條目:
>>> >>> x = np.array([[1., 2.], [np.nan, 3.], [np.nan, np.nan]]) >>> x[~np.isnan(x)] array([ 1., 2., 3.])
或者但願爲全部負面元素添加常量:
>>> >>> x = np.array([1., -1., -2., 3]) >>> x[x < 0] += 20 >>> x array([ 1., 19., 18., 3.])
一般,若是索引包括布爾數組,則結果將與插入obj.nonzero()相同位置並使用上述整數數組索引機制相同。 至關於 。x[ind_1, boolean_array, ind_2]x[(ind_1,) + boolean_array.nonzero() + (ind_2,)]
若是隻有一個布爾數組且沒有整數索引數組,則這是直截了當的。必須注意確保布爾索引具備與其應該使用的維度徹底相同的維度。
例
從數組中,選擇總和小於或等於2的全部行:
>>> >>> x = np.array([[0, 1], [1, 1], [2, 2]]) >>> rowsum = x.sum(-1) >>> x[rowsum <= 2, :] array([[0, 1], [1, 1]])
但若是rowsum還有兩個維度:
>>> >>> rowsum = x.sum(-1, keepdims=True) >>> rowsum.shape (3, 1) >>> x[rowsum <= 2, :] # fails IndexError: too many indices >>> x[rowsum <= 2] array([0, 1])
因爲額外的維度,最後一個只給出了第一個元素。比較rowsum.nonzero()以瞭解此示例。
經過obj.nonzero()類比能夠最好地理解組合多個布爾索引數組或布爾與整數索引數組 。該函數ix_ 還支持布爾數組,而且能夠毫無心外地工做。
例
使用布爾索引選擇加起來爲偶數的全部行。同時,應使用高級整數索引選擇列0和2。使用該ix_功能能夠經過如下方式完成:
>>> >>> x = array([[ 0, 1, 2], ... [ 3, 4, 5], ... [ 6, 7, 8], ... [ 9, 10, 11]]) >>> rows = (x.sum(-1) % 2) == 0 >>> rows array([False, True, False, True]) >>> columns = [0, 2] >>> x[np.ix_(rows, columns)] array([[ 3, 5], [ 9, 11]])
沒有np.ix_呼叫或只選擇對角線元素。
或者沒有np.ix_(比較整數數組示例):
>>> >>> rows = rows.nonzero()[0] >>> x[rows[:, np.newaxis], columns] array([[ 3, 5], [ 9, 11]])
這些是一些詳細的註釋,對於平常索引(無特定順序)並不重要:
本機NumPy索引類型intp可能與默認的整數數組類型不一樣。intp是足以安全索引任何數組的最小數據類型; 對於高級索引,它可能比其餘類型更快。
對於高級分配,一般不保證迭代順序。這意味着若是元素設置不止一次,則沒法預測最終結果。
空(元組)索引是零維數組的完整標量索引。 若是是零維則x[()]返回標量,不然返回x視圖。另外一方面,x[...]老是返回一個視圖。
若是索引中存在零維數組而且它是完整的整數索引,則結果將是標量而不是零維數組。(不會觸發高級索引。)
當存在省略號(...)但沒有大小(即替換爲零 :)時,結果仍將始終爲數組。若是沒有高級索引,則爲視圖,不然爲副本。
nonzero布爾數組的等價性不適用於零維布爾數組。
當高級索引操做的結果沒有元素但單個索引超出範圍時,是否IndexError引起了未定義(例如,超出範圍)。x[[], [123]]123
當在賦值期間發生轉換錯誤時(例如,使用字符串序列更新數值數組),被分配的數組可能最終處於不可預測的部分更新狀態。可是,若是發生任何其餘錯誤(例如超出範圍索引),則陣列將保持不變。
高級索引結果的內存佈局針對每一個索引操做進行了優化,而且不能假設特定的內存順序。
當使用一個子類(尤爲是其操縱它的形狀),默認ndarray.__setitem__行爲會調用__getitem__的 基本索引而不是先進的索引。對於這樣的子類,最好ndarray.__setitem__使用基類 ndarray視圖調用數據。若是子類不返回視圖,則必須執行此操做__getitem__。
現場訪問
也能夠看看
數據類型對象(dtype),標量
若是ndarray對象是結構化數組 ,則能夠經過使用字符串索引數組來訪問數組的字段,相似於字典。
索引x['field-name']返回數組的新視圖,該視圖與x具備相同的形狀(當字段是子數組時除外)可是數據類型x.dtype['field-name']而且僅包含指定字段中的部分數據。還 記錄陣列標量能夠被「索引」這種方式。
索引到結構化數組也可使用字段名稱列表來完成, 例如 x[['field-name1','field-name2']]。從NumPy 1.16開始,這將返回僅包含這些字段的視圖。在舊版本的numpy中它返回了一個副本。有關多字段索引的詳細信息,請參閱結構化陣列的用戶指南部分。
若是訪問的字段是子數組,則子數組的尺寸將附加到結果的形狀。
例
>>> >>> x = np.zeros((2,2), dtype=[('a', np.int32), ('b', np.float64, (3,3))]) >>> x['a'].shape (2, 2) >>> x['a'].dtype dtype('int32') >>> x['b'].shape (2, 2, 3, 3) >>> x['b'].dtype dtype('float64')
x.flat返回一個迭代器,它將遍歷整個數組(以C-contiguous樣式,最後一個索引變化最快)。只要選擇對象不是元組,也可使用基本切片或高級索引對此迭代器對象創建索引。這應該從x.flat一維視圖的事實中清楚。它能夠用於具備1維C風格平面索引的整數索引。所以,任何返回數組的形狀都是整數索引對象的形狀。