天天看點

numpy 索引多個_Numpy 筆記--Numpy 常用操作

本筆記來自于菜鳥教程,整理自己用到的部分,并更新一些例子。

Numpy 基本知識

NumPy(Numerical Python) 是 Python 語言的一個擴充程式庫,支援大量的次元數組與矩陣運算,此外也針對數組運算提供大量的數學函數庫,主要用于數組計算。

安裝

最簡單的是使用 Pip 安裝:

python -m pip install --user numpy
           

測試一下:

python -c "import numpy as np; print np.__version__"
           

列印出版本就沒問題了。

Ndarray

NumPy 最重要的一個特點是其 N 維數組對象 ndarray,它是一系列同類型資料的集合,以 0 下标為開始進行集合中元素的索引。ndarray 對象是用于存放同類型元素的多元數組。

numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
           

其中:

  • object: 數組或嵌套的數列
  • dtype: 數組元素的資料類型,可選
  • copy: 對象是否需要複制,可選
  • order: 建立數組的樣式,C為行方向,F為列方向,A為任意方向(預設)
  • subok: 預設傳回一個與基類類型一緻的數組
  • ndmin: 指定生成數組的最小次元

一般情況下前兩個參數是必須有的,其餘參數較少使用。如:

import numpy as np

np.array([1, 2, 3], dtype=np.int8)
           

ndarray 的屬性

numpy 中比較重要的 ndarray 對象屬性有:

  • ndarray.ndim: 秩,即軸的數量或次元的數量
  • ndarray.shape: 數組的次元,對于矩陣,n 行 m 列
  • ndarray.size: 數組元素的總個數,相當于 .shape 中 n*m 的值
  • ndarray.dtype: ndarray 對象的元素類型
  • ndarray.itemsize: ndarray 對象中每個元素的大小,以位元組為機關
  • ndarray.flags: ndarray 對象的記憶體資訊
  • ndarray.real: ndarray元素的實部
  • ndarray.imag: ndarray 元素的虛部
  • ndarray.data: 包含實際數組元素的緩沖區,由于一般通過數組的索引擷取元素,是以通常不需要使用這個屬性。

建立數組

常用建立數組的方式:

  • 從已有數組建立: numpy.asarray(a, dtype = None, order = None)
  • 未初始化數組:numpy.empty(shape, dtype = float, order = 'C')
  • 全0數組:numpy.zeros(shape, dtype = float, order = 'C')
  • 全1數組:numpy.ones(shape, dtype = None, order = 'C')
  • 數值範圍數組:numpy.arange(start, stop, step, dtype)
  • 等差序列數組:np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
  • 等比序列數組:np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
  • 對角數組:numpy.eye(N, M=None, k=0, dtype=, order='C')

其中: shape: 數組形狀

dtype: 資料類型 order: 有"C"和"F"兩個選項,分别代表,行優先和列優先,在計算機記憶體中的存儲元素的順序。

start: 起始值,預設為0 stop: 終止值(不包含)

step: 步長,預設為1 dtype: 傳回ndarray的資料類型,如果沒有提供,則會使用輸入資料的類型。

num: 要生成的等步長的樣本數量,預設為50

執行個體

numpy.asarray

# 後面預設引入 numpy
import numpy as np

x = [1, 2, 3]
a = np.asarray(x)
print a

x =  [(1,2,3),(4,5)] 
a = np.asarray(x, dtype =  float)  
print a
           

numpy.empty

numpy.empty(shape, dtype = float, order = 'C')

# empty 建立的數組未初始化,裡面的值是随機的
np.empty([3,2], dtype = int) 

array([[              0,        42832192],
       [140268302237152,         9392928],
       [140268278696400, 140268278694992]])
           

numpy.zeros

numpy.zeros(shape, dtype = float, order = 'C')

# 這裡比較好玩的是 shape 的 (5), (5,), [5] 得到的是一樣的
x = np.zeros((5,2), dtype = np.int) 
print(x)
           

numpy.ones

x = np.ones([2,2], dtype = int)
print(x)
           

numpy.arange

x = np.arange(5, dtype =  float)
print x
           

np.linspace

a = np.linspace(10, 20,  5, endpoint =  False)
           

np.logspace

a = np.logspace(1.0,  2.0, num = 10)
           

numpy.eye

numpy.eye(N, M=None, k=0, dtype=, order='C')

# 正常的方陣對角矩陣
x = np.eye(2, dtype=int)

array([[1, 0],
      [0, 1]])

# 生成非方陣
x = np.eye(2, 3, dtype=int)

array([[1, 0, 0],
       [0, 1, 0]])

# 非主對角線的對角矩陣,通過 k 值進行調整,預設為0
np.eye(3, dtype=int, k=1)

array([[0, 1, 0],
       [0, 0, 1],
       [0, 0, 0]])
           

Numpy 索引

基本的切片與索引

ndarray對象的内容可以通過索引或切片來通路和修改,與 Python 中 list 的切片操作一樣。ndarray 數組可以基于 0 - n 的下标進行索引,切片對象可以通過内置的 slice 函數,并設定 start, stop 及 step 參數進行,從原數組中切割出一個新數組。

import numpy as np

# 切片
a = np.arange(10)
s = slice(2, 7, 2)
print a[s]
print a[2:7:2]

# 索引
print a[5]
           

進階索引

NumPy 比一般的 Python 序列提供更多的索引方式。除了之前看到的用整數和切片的索引外,數組可以由整數數組索引、布爾索引及花式索引。

整數數組索引

import numpy as np 

x = np.array([[1,  2],  [3,  4],  [5,  6]])
# 取出索引(0,0), (1,1), (2,0) 三個位置的元素
y = x[[0,1,2],  [0,1,0]]  
print y
out: array([1, 4, 5])

# 更新版。。。
x = np.array([[  0,  1,  2 ],[  3,  4,  5 ],[  6,  7,  8 ],[  9,  10,  11 ]])  
rows = np.array([[0,0],[3,3]]) 
cols = np.array([[0,2],[0,2]]) 
print x[rows, cols]
out: [[ 0  2 ]
      [ 9 11 ]]
           

布爾索引

我們可以通過一個布爾數組來索引目标數組。而布爾數組可以通過布爾運算來擷取符合指定條件的元素的數組。

import numpy as np 

x = np.array([[  0,  1,  2 ],[  3,  4,  5 ],[  6,  7,  8 ],[  9,  10,  11 ]])  
# 擷取值大于5的元素
print (x[x >  5])
out: [ 6  7  8  9 10 11 ]
           

花式索引

花式索引指的是利用整數數組進行索引

。花式索引根據索引數組的值作為目标數組的某個軸的下标來取值。對于使用一維整型數組作為索引,如果目标是一維數組,那麼索引的結果就是對應位置的元素;如果目标是二維數組,那麼就是對應下标的行。

花式索引跟切片不一樣,它總是将資料複制到新數組中。
import numpy as np 

x=np.arange(32).reshape((8,4))

# 順序數組
print (x[[4,2,1,7]])

# 倒序索引
print (x[[-4,-2,-1,-7]])

# 多個索引數組
print (x[np.ix_([1,5,7,2],[0,3,1,2])])
           

數組操作

正常操作

Numpy 中包含了一些函數用于處理數組,大概可分為以下幾類:

  • 修改數組形狀
    • reshape numpy.reshape(arr, newshape, order='C')
    • flat
    • flatten
    • ravel
  • 翻轉數組
    • transpose
    • ndarray.T
    • rollaxis
    • swapaxes
  • 修改數組次元
    • broadcast
    • broadcast_to
    • expand_dims
    • squeeze
  • 連接配接數組
    • concatenate
    • stack
    • hstack
    • vstack
  • 分割數組
    • split
    • hsplit
    • vsplit
  • 數組元素的添加與删除
    • resize
    • append
    • insert
    • delete
    • unique

修改數組形狀

reshape

numpy.reshape 函數可以在不改變資料的條件下修改形狀, numpy.reshape(arr, newshape, order='C')

import numpy as np

x = np.arange(8)
print x.shape, x
y = x.reshape(2,4)
print y.shape, y
           

numpy.ndarray.flat

numpy.ndarray.flat 是一個數組元素疊代器,

将數組轉換為1-D的疊代器

. 執行個體如下:

import numpy as np

a = np.arange(9).reshape(3,3)
for row in a:
    print row

out: [0 1 2]
     [3 4 5]
     [6 7 8]

# 如果用 flat
for ele in a.flat:
    print ele

out :
    0
    1
    2
    3
    4
    5
    6
    7
    8
           

numpy.ndarray.flatten

numpy.ndarray.flatten 将數組的副本轉換為一維,并傳回.傳回一份數組拷貝,對拷貝所做的修改不會影響原始數組,格式如下:

ndarray.flatten(order='C')

其中 order:'C' -- 按行,'F' -- 按列,'A' -- 原順序,'K' -- 元素在記憶體中的出現順序。這個也适用于上面的其他 order選項。

import numpy as np

a = np.arange(8).reshape(2,4)
print a.flatten()
# 可以看出,flat 傳回的是一個一維疊代器,而flatten傳回的是一個一維數組,并且是新的副本
out: [0 1 2 3 4 5 6 7]
           

numpy.ravel

numpy.ravel() 展平的數組元素,順序通常是"C風格",傳回的是數組視圖(view,有點類似 C/C++引用reference的意味),修改會影響原始數組。看起來它和 flatten很像。

首先聲明兩者所要實作的功能是一緻的(将多元數組降位一維)。這點從兩個單詞的意也可以看出來,ravel(散開,解開),flatten(變平)。兩者的差別在于傳回拷貝(copy)還是傳回視圖(view),numpy.flatten()傳回一份拷貝,對拷貝所做的修改不會影響(reflects)原始矩陣,而numpy.ravel()傳回的是視圖(view,也頗有幾分C/C++引用reference的意味),會影響(reflects)原始矩陣。

格式為 : numpy.ravel(a, order='C')

import numpy as np

a = np.arange(8).reshape(2,4)
b = a.flatten()
c = a.ravel()
print b
out: array([0, 1, 2, 3, 4, 5, 6, 7])
print c
out: array([0, 1, 2, 3, 4, 5, 6, 7])

c[0] = 1
print a
# 看到對c的修改,在a上也生效了,但是b沒變
out: array([[1, 1, 2, 3], [4, 5, 6, 7]])
print b
out: array([0, 1, 2, 3, 4, 5, 6, 7])
print c
out: array([1, 1, 2, 3, 4, 5, 6, 7])
           

翻轉數組

numpy.transpose 與 ndarray.T

numpy.transpose 函數用于對換數組的次元,如形狀 (2,3,4) transpose 後就變成 (4,3,2)。ndarray.T 和它的功能一緻。transpose的格式為:numpy.transpose(arr, axes)

import numpy as np

a = np.arange(120).reshape(2,3,4, 5)
b = np.transpose(a)
print b.shape
out:  (5, 4, 3, 2)
c = a.T
print c.shape
           

numpy.swapaxes

numpy.swapaxes 函數用于交換數組的兩個軸,格式為:numpy.swapaxes(arr, axis1, axis2)

import numpy as np

a = np.arange(24).reshape(2,3,4)
b = np.swapaxes(a, 1, 2)
print b.shape
out: (2, 4, 3)
           

numpy.rollaxis

numpy.rollaxis 函數向後滾動特定的軸到一個特定位置,格式為:numpy.rollaxis(arr, axis, start)

mport numpy as np

a = np.arange(120).reshape(2,3,4, 5)
# 直覺上了解就是在形狀元組中的第二個次元4插入到指定位置(預設為0)。
b = np.rollaxis(a, 2)
print b.shape
out: (4, 2, 3, 5)
# 通過第三個參數指定插入的位置
b = np.rollaxis(a, 3, 1)
print b.shape
out: (2, 5, 3, 4)
           

修改數組的次元

numpy.broadcast

numpy.broadcast 用于模仿廣播的對象,它傳回一個對象,該對象封裝了将一個數組廣播到另一個數組的結果。該函數使用兩個數組作為輸入參數,如下執行個體:

import numpy as np

x = np.array([[1], [2], [3]])
y = np.array([4, 5, 6])
# 對y 廣播 x
b = np.broadcast(x,y)
print b
           

numpy.broadcast_to

numpy.broadcast_to 函數将數組廣播到新形狀。它在原始數組上傳回隻讀視圖。 它通常不連續。 如果新形狀不符合 NumPy 的廣播規則,該函數可能會抛出ValueError。格式為:numpy.broadcast_to(array, shape, subok)

import numpy as np

a = np.arange(4).reshape(1,4)
print (np.broadcast_to(a,(4,4)))
           

numpy.expand_dims

numpy.expand_dims 函數通過在指定位置插入新的軸來擴充數組形狀,函數格式: numpy.expand_dims(arr, axis)

import numpy as np

x = np.array(([1,2],[3,4]))
y = np.expand_dims(x, axis = 1)

print y.shape
out: (2, 1, 2)
           

numpy.squeeze

numpy.squeeze 函數從給定數組的形狀中删除一維的條目,函數格式:numpy.squeeze(arr, axis),預設删除全部。

import numpy as np

x = np.arange(9).reshape(1,1,3,3)
y = np.squeeze(x)
print y.shape
out: (3, 3)
y = np.squeeze(x, axis=0)
y.shape
out: (1, 3, 3)
           

連接配接數組

numpy.concatenate

numpy.concatenate 函數用于沿指定軸連接配接相同形狀的兩個或多個數組,格式如下: numpy.concatenate((a1, a2, ...), axis)

import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
print (np.concatenate((a,b), axis=0))
out: [[1 2]
      [3 4]
      [5 6]
      [7 8]]
print (np.concatenate((a,b),axis = 1))
out: [[1 2 5 6]
      [3 4 7 8]]
           

numpy.stack

numpy.stack 函數用于沿新軸連接配接數組序列,格式如下: numpy.stack(arrays, axis)

它與 numpy.concatenate 的差別主要是 stack 會增加一個次元,給我的感覺它就像把兩個數組堆疊在一起,而 concatenate 是連接配接構成一個新的數組。

import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])

print (np.stack((a,b),0))
out: [[[1 2]
        [3 4]]
      [[5 6]
        [7 8]]]

print (np.stack((a,b),1))
out: [[[1 2]
        [5 6]]
      [[3 4]
        [7 8]]]
           

numpy.hstack

numpy.hstack 是 numpy.stack 函數的變體,它通過水準堆疊來生成數組。

import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])

# 可以看到,這個的結果和 np.concatenate((a,b),axis = 1) 是一樣的
print np.hstack((a,b))
out: [[1 2 5 6]
      [3 4 7 8]]
           

numpy.vstack

numpy.vstack 是 numpy.stack 函數的變體,它通過垂直堆疊來生成數組。

import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])

# 和 np.concatenate((a,b),axis = 0) 一緻
print np.vstack((a,b))
out: [[1 2]
      [3 4]
      [5 6]
      [7 8]]
           

分個數組

numpy.split

numpy.split 函數沿特定的軸将數組分割為子數組,格式如下:numpy.split(ary, indices_or_sections, axis)

import numpy as np

a = np.arange(9)
print np.split(a,3)
out: [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]

# 通過數組指定切割位置
print np.split(a, [4, 7])
out: [array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]
           

numpy.hsplit

numpy.hsplit 函數用于水準分割數組,通過指定要傳回的相同形狀的數組數量來拆分原數組。

import numpy as np

a = np.arange(9)
np.hsplit(a, 2)
Out[121]: [array([0, 1, 2, 3]), array([4, 5, 6, 7])]

np.hsplit(a, 4)
out: [array([0, 1]), array([2, 3]), array([4, 5]), array([6, 7])]
           

numpy.vsplit

numpy.vsplit 沿着垂直軸分割,其分割方式與hsplit用法相同。

import numpy as np

a = np.arange(16).reshape(4,4)
print np.vsplit(a,2)
out: [array([[0, 1, 2, 3],
            [4, 5, 6, 7]]), 
      array([[ 8,  9, 10, 11 ],
            [12, 13, 14, 15]])]
           

數組元素的添加與删除

numpy.resize

numpy.resize 函數傳回指定大小的新數組。 如果新數組大小大于原始大小,則包含原始數組中的元素的副本。 格式為:numpy.resize(arr, shape)

import numpy as np

a = np.array([[1,2,3],[4,5,6]])
print np.resize(a, (3,2))
out: array([[1, 2],
            [3, 4],
            [5, 6]])

# 最後一行的 [1, 2, 3] 就是元素副本填充得到的
print np.resize(a,(3,3))
out: [[1 2 3]
      [4 5 6]
      [1 2 3]]
           

numpy.append

numpy.append 函數在數組的末尾添加值。 追加操作會配置設定整個數組,并把原來的數組複制到新數組中。 此外,輸入數組的次元必須比對否則将生成ValueError。

append 函數傳回的始終是一個一維數組

。格式為:numpy.append(arr, values, axis=None)

import numpy as np

a = np.array([[1,2,3],[4,5,6]])
print np.append(a, [7,8,9])
out: array([1, 2, 3, 4, 5, 6, 7, 8, 9])

# 沿軸 0 添加元素
np.append(a, [[7,8,9]],axis = 0)
out: array([[1, 2, 3],
            [4, 5, 6],
            [7, 8, 9]])

# 軸 1
np.append(a, [[5,5,5],[7,8,9]],axis = 1)
out: array([[1, 2, 3, 5, 5, 5],
            [4, 5, 6, 7, 8, 9]])
           

numpy.insert

numpy.insert 函數在給定索引之前,沿給定軸在輸入數組中插入值。 如果值的類型轉換為要插入,則它與輸入數組不同。 插入沒有原地的,函數會傳回一個新數組。 此外,如果未提供軸,則輸入數組會被展開。格式為:numpy.insert(arr, obj, values, axis)

import numpy as np

a = np.array([[1,2],[3,4],[5,6]])
np.insert(a,3,[11,12])
out: array([ 1,  2,  3, 11, 12,  4,  5,  6 ])
           

numpy.delete

numpy.delete 函數傳回從輸入數組中删除指定子數組的新數組。 與 insert() 函數的情況一樣,如果未提供軸參數,則輸入數組将展開。格式為:Numpy.delete(arr, obj, axis)

import numpy as np

a = np.arange(12).reshape(3,4)
np.delete(a,5)
out: [ 0  1  2  3  4  6  7  8  9 10 11 ]
           

numpy.unique

numpy.unique 函數用于去除數組中的重複元素。格式為:numpy.unique(arr, return_index, return_inverse, return_counts)

import numpy as np

a = np.array([5,2,6,2,7,5,6,8,2,9])
np.unique(a)
out: [2 5 6 7 8 9]
           

NumPy 線性代數

NumPy 提供了線性代數函數庫 linalg,該庫包含了線性代數所需的所有功能。除此之外,Numpy 空間下也有一些常見操作。

  • numpy.dot() 兩個數組的點積,即元素對應相乘。
  • vdot 兩個向量的點積
  • inner 兩個數組的内積
  • matmul 兩個數組的矩陣積
  • determinant 數組的行列式
  • solve 求解線性矩陣方程
  • inv 計算矩陣的乘法逆矩陣

numpy.dot()

numpy.dot() 對于兩個一維的數組,計算的是這兩個數組對應下标元素的乘積和(數學上稱之為内積);對于二維數組,計算的是兩個數組的矩陣乘積。

import numpy as np

a = np.array([1,2])
b = np.array([3,4])

np.dot(a, b)
out: 11

a = np.array([[1,2],[3,4]])
b = np.array([[11,12],[13,14]])
np.dot(a,b)
out: [[37 40]
      [85 92]]
           

numpy.vdot()

numpy.vdot() 函數是兩個向量的點積。 如果第一個參數是複數,那麼它的共轭複數會用于計算。 如果參數是多元數組,它會被展開。

import numpy as np 

a = np.array([[1,2],[3,4]]) 
b = np.array([[11,12],[13,14]]) 
np.vdot(a,b)
out: 130
           

numpy.matmul

numpy.matmul 函數傳回兩個數組的矩陣乘積。 雖然它傳回二維數組的正常乘積,但如果任一參數的維數大于2,則将其視為存在于最後兩個索引的矩陣的棧,并進行相應廣播。另一方面,如果任一參數是一維數組,則通過在其次元上附加 1 來将其提升為矩陣,并在乘法之後被去除。對于二維數組,它就是矩陣乘法:

import numpy as np 

a = [[1,0],[0,1]] 
b = [[4,1],[2,2]] 
np.matmul(a,b)
out: [[4  1] 
      [2  2]]