NumPy之:ndarray多維數組操做

簡介

NumPy一個很是重要的做用就是能夠進行多維數組的操做,多維數組對象也叫作ndarray。咱們能夠在ndarray的基礎上進行一系列複雜的數學運算。python

本文將會介紹一些基本常見的ndarray操做,你們能夠在數據分析中使用。數組

建立ndarray

建立ndarray有不少種方法,咱們可使用np.random來隨機生成數據:dom

import numpy as np
# Generate some random data
data = np.random.randn(2, 3)
data
array([[ 0.0929,  0.2817,  0.769 ],
       [ 1.2464,  1.0072, -1.2962]])

除了隨機建立以外,還能夠從list中建立:3d

data1 = [6, 7.5, 8, 0, 1]
arr1 = np.array(data1)
array([6. , 7.5, 8. , 0. , 1. ])

從list中建立多維數組:code

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

使用np.zeros建立初始值爲0的數組:對象

np.zeros(10)
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

建立2維數組:教程

np.zeros((3, 6))
array([[0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0.]])

使用empty建立3維數組:索引

np.empty((2, 3, 2))
array([[[0., 0.],
        [0., 0.],
        [0., 0.]],

       [[0., 0.],
        [0., 0.],
        [0., 0.]]])
注意,這裏咱們看到empty建立的數組值爲0,其實並非必定的,empty會從內存中隨機挑選空間來返回,並不能保證這些空間中沒有值。因此咱們在使用empty建立數組以後,在使用以前,還要記得初始化他們。

使用arange建立範圍類的數組:內存

np.arange(15)
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])

指定數組中元素的dtype:get

arr1 = np.array([1, 2, 3], dtype=np.float64)
arr2 = np.array([1, 2, 3], dtype=np.int32)

ndarray的屬性

能夠經過data.shape得到數組的形狀。

data.shape
(2, 3)

經過ndim獲取維數信息:

arr2.ndim
2

能夠經過data.dtype得到具體的數據類型。

data.dtype
dtype('float64')

ndarray中元素的類型轉換

在建立好一個類型的ndarray以後,還能夠對其進行轉換:

arr = np.array([1, 2, 3, 4, 5])
arr.dtype
dtype('int64')

float_arr = arr.astype(np.float64)
float_arr.dtype
dtype('float64')

上面咱們使用astype將int64類型的ndarray轉換成了float64類型的。

若是轉換類型的範圍不匹配,則會自動進行截斷操做:

arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
arr.astype(np.int32)

array([ 3, -1, -2,  0, 12, 10], dtype=int32)
注意,這裏是把小數截斷,並無向上或者向下取整。

ndarray的數學運算

數組能夠和常量進行運算,也能夠和數組進行運算:

arr = np.array([[1., 2., 3.], [4., 5., 6.]])

arr * arr

array([[ 1.,  4.,  9.],
       [16., 25., 36.]])

arr + 10

array([[11., 12., 13.],
       [14., 15., 16.]])

arr - arr

array([[0., 0., 0.],
       [0., 0., 0.]])

1 / arr

array([[1.    , 0.5   , 0.3333],
       [0.25  , 0.2   , 0.1667]])

arr ** 0.5

array([[1.    , 1.4142, 1.7321],
       [2.    , 2.2361, 2.4495]])

數組之間還能夠進行比較,比較的是數組中每一個元素的大小:

arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])

arr2 > arr

array([[False,  True, False],
       [ True, False,  True]])

index和切片

基本使用

先看下index和切片的基本使用,index基本上和普通數組的使用方式是同樣的,用來訪問數組中某一個元素。

切片要注意的是切片後返回的數組中的元素是原數組中元素的引用,修改切片的數組會影響到原數組。

# 構建一維數組
arr = np.arange(10)

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# index訪問
arr[5]
5

# 切片訪問
arr[5:8]
array([5, 6, 7])

# 切片修改
arr[5:8] = 12
array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])

# 切片能夠修改原數組的值
arr_slice = arr[5:8]
arr_slice[1] = 12345
arr

array([    0,     1,     2,     3,     4,    12, 12345,    12,     8,
           9])

# 構建二維數組
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr2d[2]

array([7, 8, 9])

# index 二維數組
arr2d[0][2]
3

# index二維數組
arr2d[0, 2]
3

# 構建三維數組
arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
arr3d

array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

# index三維數組
arr3d[0]

array([[1, 2, 3],
       [4, 5, 6]])

# copy是硬拷貝,和原數組的值相互不影響
old_values = arr3d[0].copy()
arr3d[0] = 42

arr3d

array([[[42, 42, 42],
        [42, 42, 42]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

arr3d[0] = old_values
arr3d

array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

# index 三維數組
arr3d[1, 0]

array([7, 8, 9])

x = arr3d[1]
x

array([[ 7,  8,  9],
       [10, 11, 12]])

x[0]

array([7, 8, 9])

index with slice

slice還能夠做爲index使用,做爲index使用表示的就是一個index範圍值。

做爲index表示的slice能夠有多種形式。

有頭有尾的,表示index從1開始到6-1結束:

arr[1:6]
array([ 1,  2,  3,  4, 64])

無頭有尾的,表示index從0開始,到尾-1結束:

arr2d[:2]
array([[1, 2, 3],
       [4, 5, 6]])

有頭無尾的,表示從頭開始,到全部的數據結束:

arr2d[:2, 1:]
array([[2, 3],
       [5, 6]])
arr2d[1, :2]
array([4, 5])

boolean index

index還可使用boolean值,表示是否選擇這一個index的數據。

咱們先看下怎麼構建一個boolean類型的數組:

names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
names == 'Bob'

array([ True, False, False,  True, False, False, False])

上面咱們經過比較的方式返回了一個只包含True和False的數組。

這個數組能夠做爲index值來訪問數組:

#  構建一個7 * 4 的數組
data = np.random.randn(7, 4)

array([[ 0.275 ,  0.2289,  1.3529,  0.8864],
       [-2.0016, -0.3718,  1.669 , -0.4386],
       [-0.5397,  0.477 ,  3.2489, -1.0212],
       [-0.5771,  0.1241,  0.3026,  0.5238],
       [ 0.0009,  1.3438, -0.7135, -0.8312],
       [-2.3702, -1.8608, -0.8608,  0.5601],
       [-1.2659,  0.1198, -1.0635,  0.3329]])

# 經過boolean數組來訪問:
data[names == 'Bob']
array([[ 0.275 ,  0.2289,  1.3529,  0.8864],
       [-0.5771,  0.1241,  0.3026,  0.5238]])

在索引行的時候,還能夠索引列:

data[names == 'Bob', 3]
array([0.8864, 0.5238])

能夠用 ~符號來取反:

data[~(names == 'Bob')]
array([[-2.0016, -0.3718,  1.669 , -0.4386],
       [-0.5397,  0.477 ,  3.2489, -1.0212],
       [ 0.0009,  1.3438, -0.7135, -0.8312],
       [-2.3702, -1.8608, -0.8608,  0.5601],
       [-1.2659,  0.1198, -1.0635,  0.3329]])

咱們能夠經過布爾型數組設置值,在實際的項目中很是有用:

data[data < 0] = 0
array([[0.275 , 0.2289, 1.3529, 0.8864],
       [0.    , 0.    , 1.669 , 0.    ],
       [0.    , 0.477 , 3.2489, 0.    ],
       [0.    , 0.1241, 0.3026, 0.5238],
       [0.0009, 1.3438, 0.    , 0.    ],
       [0.    , 0.    , 0.    , 0.5601],
       [0.    , 0.1198, 0.    , 0.3329]])
data[names != 'Joe'] = 7
array([[7.    , 7.    , 7.    , 7.    ],
       [0.    , 0.    , 1.669 , 0.    ],
       [7.    , 7.    , 7.    , 7.    ],
       [7.    , 7.    , 7.    , 7.    ],
       [7.    , 7.    , 7.    , 7.    ],
       [0.    , 0.    , 0.    , 0.5601],
       [0.    , 0.1198, 0.    , 0.3329]])

Fancy indexing

Fancy indexing也叫作花式索引,它是指使用一個整數數組來進行索引。

舉個例子,咱們先建立一個 8 * 4的數組:

arr = np.empty((8, 4))
for i in range(8):
    arr[i] = i
arr
array([[0., 0., 0., 0.],
       [1., 1., 1., 1.],
       [2., 2., 2., 2.],
       [3., 3., 3., 3.],
       [4., 4., 4., 4.],
       [5., 5., 5., 5.],
       [6., 6., 6., 6.],
       [7., 7., 7., 7.]])

而後使用一個整數數組來索引,那麼將會以指定的順序來選擇行:

arr[[4, 3, 0, 6]]
array([[4., 4., 4., 4.],
       [3., 3., 3., 3.],
       [0., 0., 0., 0.],
       [6., 6., 6., 6.]])

還可使用負值來索引:

arr[[-3, -5, -7]]
array([[5., 5., 5., 5.],
       [3., 3., 3., 3.],
       [1., 1., 1., 1.]])

花式索引還能夠組合來使用:

arr = np.arange(32).reshape((8, 4))
arr
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23],
       [24, 25, 26, 27],
       [28, 29, 30, 31]])

上面咱們構建了一個8 * 4的數組。

arr[[1, 5, 7, 2], [0, 3, 1, 2]]
array([ 4, 23, 29, 10])

而後取他們的第2列的第一個值,第6列的第三個值等等。最後獲得一個1維的數組。

數組變換

咱們能夠在不一樣維度的數組之間進行變換,還能夠轉換數組的軸。

reshape方法能夠將數組轉換成爲任意的形狀:

arr = np.arange(15).reshape((3, 5))
arr
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])

數組還提供了一個T命令,能夠將數組的軸進行對調:

arr.T
array([[ 0,  5, 10],
       [ 1,  6, 11],
       [ 2,  7, 12],
       [ 3,  8, 13],
       [ 4,  9, 14]])

對於高維數組,可使用transpose來進行軸的轉置:

arr = np.arange(16).reshape((2, 2, 4))
arr
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])
        
arr.transpose((1, 0, 2))
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],

       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])

上面的transpose((1, 0, 2)) 怎麼理解呢?

其含義是將x,y軸對調,z軸保持不變。

上面咱們經過使用reshape((2, 2, 4))方法建立了一個3維,也就是3個軸的數組。 其shape是 2 2 4 。

先看下對應關係:

(0,0)-》 [ 0, 1, 2, 3]

(0,1)-》 [ 4, 5, 6, 7]

(1,0)-》 [ 8, 9, 10, 11]

(1,1)-》 [12, 13, 14, 15]

轉換以後:

(0,0)-》 [ 0, 1, 2, 3]

(0,1)-》 [ 8, 9, 10, 11]

(1,0)-》[ 4, 5, 6, 7]

(1,1)-》 [12, 13, 14, 15]

因而獲得了咱們上面的的結果。

多維數組的軸轉換可能比較複雜,你們多多理解。

還可使用 swapaxes 來交換兩個軸,上面的例子能夠重寫爲:

arr.swapaxes(0,1)

本文已收錄於 http://www.flydean.com/09-python-numpy-ndarray/

最通俗的解讀,最深入的乾貨,最簡潔的教程,衆多你不知道的小技巧等你來發現!

歡迎關注個人公衆號:「程序那些事」,懂技術,更懂你!

相關文章
相關標籤/搜索