Python:一篇文章掌握Numpy的基本用法

前言

Numpy是一個開源的Python科學計算庫,它是python科學計算庫的基礎庫,許多其餘著名的科學計算庫如Pandas,Scikit-learn等都要用到Numpy庫的一些功能。vue

本文主要內容以下:python

  1. Numpy數組對象
  2. 建立ndarray數組
  3. Numpy的數值類型
  4. ndarray數組的屬性
  5. ndarray數組的切片和索引
  6. 處理數組形狀
  7. 數組的類型轉換
  8. numpy經常使用統計函數
  9. 數組的廣播

1 Numpy數組對象

Numpy中的多維數組稱爲ndarray,這是Numpy中最多見的數組對象。ndarray對象一般包含兩個部分:npm

  • ndarray數據自己
  • 描述數據的元數據

Numpy數組的優點數組

  • Numpy數組一般是由相同種類的元素組成的,即數組中的數據項的類型一致。這樣有一個好處,因爲知道數組元素的類型相同,因此能快速肯定存儲數據所需空間的大小。
  • Numpy數組可以運用向量化運算來處理整個數組,速度較快;而Python的列表則一般須要藉助循環語句遍歷列表,運行效率相對來講要差。
  • Numpy使用了優化過的C API,運算速度較快

關於向量化和標量化運算,對比下面的參考例子就能夠看出差別微信

  • 使用python的list進行循環遍歷運算
def pySum():
    a = list(range(10000))
    b = list(range(10000))
    c = []
    for i in range(len(a)):
        c.append(a[i]**2 + b[i]**2)

    return c
%timeit pySum()
10 loops, best of 3: 49.4 ms per loop
  • 使用numpy進行向量化運算
import numpy as np
def npSum():
    a = np.arange(10000)
    b = np.arange(10000)
    c = a**2 + b**2
    return c
%timeit npSum()
The slowest run took 262.56 times longer than the fastest. This could mean that an intermediate result is being cached.
1000 loops, best of 3: 128 µs per loop

從上面的運行結果能夠看出,numpy的向量化運算的效率要遠遠高於python的循環遍歷運算(效率相差好幾百倍)
(1ms=1000µs)markdown

2 建立ndarray數組

首先須要導入numpy庫,在導入numpy庫時一般使用「np」做爲簡寫,這也是Numpy官方倡導的寫法。app

固然,你也能夠選擇其餘簡寫的方式或者直接寫numpy,但仍是建議用「np」,這樣你的程序能和大都數人的程序保持一致。dom

import numpy as np

建立ndarray數組的方式有不少種,這裏介紹我使用的較多的幾種:函數

Method 1: 基於list或tupleoop

# 一維數組

# 基於list
arr1 = np.array([1,2,3,4])
print(arr1)

# 基於tuple
arr_tuple = np.array((1,2,3,4))
print(arr_tuple)

# 二維數組 (2*3)
arr2 = np.array([[1,2,4], [3,4,5]])
arr2
[1 2 3 4]
[1 2 3 4]
array([[1, 2, 4],
       [3, 4, 5]])

請注意:

  • 一維數組用print輸出的時候爲 [1 2 3 4],跟python的列表是有些差別的,沒有「,
  • 在建立二維數組時,在每一個子list外面還有一個」[]」,形式爲「[[list1], [list2]]

Method 2: 基於np.arange

# 一維數組
arr1 = np.arange(5)
print(arr1)

# 二維數組
arr2 = np.array([np.arange(3), np.arange(3)])
arr2
[0 1 2 3 4]
array([[0, 1, 2],
       [0, 1, 2]])

Method 3: 基於arange以及reshape建立多維數組

# 建立三維數組
arr = np.arange(24).reshape(2,3,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]]])
  • 請注意:arange的長度與ndarray的維度的乘積要相等,即 24 = 2X3X4

 

  • 其餘建立ndarray的方法,各位小夥伴們本身能夠研究下。

3 Numpy的數值類型

Numpy的數值類型以下:

每一種數據類型都有相應的數據轉換函數,參考示例以下:

np.int8(12.334)
12
np.float64(12)
12.0
np.float(True)
1.0
bool(1)
True

在建立ndarray數組時,能夠指定數值類型:

a = np.arange(5, dtype=float)
a
array([ 0.,  1.,  2.,  3.,  4.])
  • 請注意,複數不能轉換成爲整數類型或者浮點數,好比下面的代碼會運行出錯

# float(42 + 1j)

4 ndarray數組的屬性

  • dtype屬性,ndarray數組的數據類型,數據類型的種類,前面已描述。
np.arange(4, dtype=float)
array([ 0.,  1.,  2.,  3.])
# 'D'表示複數類型
np.arange(4, dtype='D')
array([ 0.+0.j,  1.+0.j,  2.+0.j,  3.+0.j])
np.array([1.22,3.45,6.779], dtype='int8')
array([1, 3, 6], dtype=int8)
  • ndim屬性,數組維度的數量
a = np.array([[1,2,3], [7,8,9]])
a.ndim
2
  • shape屬性,數組對象的尺度,對於矩陣,即n行m列,shape是一個元組(tuple)
a.shape
(2, 3)
  • size屬性用來保存元素的數量,至關於shape中nXm的值
a.size
6
  • itemsize屬性返回數組中各個元素所佔用的字節數大小。
a.itemsize
4
  • nbytes屬性,若是想知道整個數組所需的字節數量,可使用nbytes屬性。其值等於數組的size屬性值乘以itemsize屬性值。
a.nbytes
24
a.size*a.itemsize
24
  • T屬性,數組轉置
b = np.arange(24).reshape(4,6)
b
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]])
b.T
array([[ 0,  6, 12, 18],
       [ 1,  7, 13, 19],
       [ 2,  8, 14, 20],
       [ 3,  9, 15, 21],
       [ 4, 10, 16, 22],
       [ 5, 11, 17, 23]])
  • 複數的實部和虛部屬性,real和imag屬性
d = np.array([1.2+2j, 2+3j])
d
array([ 1.2+2.j,  2.0+3.j])

real屬性返回數組的實部

d.real
array([ 1.2,  2. ])

imag屬性返回數組的虛部

d.imag
array([ 2.,  3.])
  • flat屬性,返回一個numpy.flatiter對象,便可迭代的對象。
e = np.arange(6).reshape(2,3)
e
array([[0, 1, 2],
       [3, 4, 5]])
f = e.flat
f
<numpy.flatiter at 0x65eaca0>
for item in f:
    print(item)
0
1
2
3
4
5

可經過位置進行索引,以下:

f[2]
2
f[[1,4]]
array([1, 4])

也能夠進行賦值

e.flat=7
e
array([[7, 7, 7],
       [7, 7, 7]])
e.flat[[1,4]]=1
e
array([[7, 1, 7],
       [7, 1, 7]])

下圖是對ndarray各類屬性的一個小結

5 ndarray數組的切片和索引

  • 一維數組

一維數組的切片和索引與python的list索引相似。

a =  np.arange(7)
a
array([0, 1, 2, 3, 4, 5, 6])
a[1:4]
array([1, 2, 3])
# 每間隔2個取一個數
a[ : 6: 2]
array([0, 2, 4])
  • 二維數組的切片和索引,以下所示:

插播一條硬廣:技術文章轉發太多。本文涉及的代碼量比較多,如須要查看源代碼,請在微信公衆號「Python數據之道」(ID:PyDataRoad)後臺回覆關鍵字「2017026」。

6 處理數組形狀

6.1 形狀轉換

  • reshape()和resize()
b.reshape(4,3)
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])
b
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
b.resize(4,3)
b
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])

函數resize()的做用跟reshape()相似,可是會改變所做用的數組,至關於有inplace=True的效果

  • ravel()和flatten(),將多維數組轉換成一維數組,以下:
b.ravel()
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
b.flatten()
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
b
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])

二者的區別在於返回拷貝(copy)仍是返回視圖(view),flatten()返回一份拷貝,須要分配新的內存空間,對拷貝所作的修改不會影響原始矩陣,而ravel()返回的是視圖(view),會影響原始矩陣。

參考以下代碼:

  • 用tuple指定數組的形狀,以下:
b.shape=(2,6)
b
array([[ 0,  1, 20,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]])
  • 轉置

前面描述了數組轉置的屬性(T),也能夠經過transpose()函數來實現

b.transpose()
array([[ 0,  6],
       [ 1,  7],
       [20,  8],
       [ 3,  9],
       [ 4, 10],
       [ 5, 11]])

6.2 堆疊數組

b
array([[ 0,  1, 20,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]])
c = b*2
c
array([[ 0,  2, 40,  6,  8, 10],
       [12, 14, 16, 18, 20, 22]])
  • 水平疊加

hstack()

np.hstack((b,c))
array([[ 0,  1, 20,  3,  4,  5,  0,  2, 40,  6,  8, 10],
       [ 6,  7,  8,  9, 10, 11, 12, 14, 16, 18, 20, 22]])

column_stack()函數以列方式對數組進行疊加,功能相似hstack()

np.column_stack((b,c))
array([[ 0,  1, 20,  3,  4,  5,  0,  2, 40,  6,  8, 10],
       [ 6,  7,  8,  9, 10, 11, 12, 14, 16, 18, 20, 22]])
  • 垂直疊加

vstack()

np.vstack((b,c))
array([[ 0,  1, 20,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [ 0,  2, 40,  6,  8, 10],
       [12, 14, 16, 18, 20, 22]])

row_stack()函數以行方式對數組進行疊加,功能相似vstack()

np.row_stack((b,c))
array([[ 0,  1, 20,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [ 0,  2, 40,  6,  8, 10],
       [12, 14, 16, 18, 20, 22]])
  • concatenate()方法,經過設置axis的值來設置疊加方向

axis=1時,沿水平方向疊加

axis=0時,沿垂直方向疊加

np.concatenate((b,c),axis=1)
array([[ 0,  1, 20,  3,  4,  5,  0,  2, 40,  6,  8, 10],
       [ 6,  7,  8,  9, 10, 11, 12, 14, 16, 18, 20, 22]])
np.concatenate((b,c),axis=0)
array([[ 0,  1, 20,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [ 0,  2, 40,  6,  8, 10],
       [12, 14, 16, 18, 20, 22]])

因爲針對數組的軸爲0或1的方向常常會混淆,經過示意圖,或許能夠更好的理解。

關於數組的軸方向示意圖,以及疊加的示意圖,以下:

深度疊加

這個有點燒腦,舉個例子以下,本身能夠體會下:

arr_dstack = np.dstack((b,c))
print(arr_dstack.shape)
arr_dstack
(2, 6, 2)

array([[[ 0,  0],
        [ 1,  2],
        [20, 40],
        [ 3,  6],
        [ 4,  8],
        [ 5, 10]],

       [[ 6, 12],
        [ 7, 14],
        [ 8, 16],
        [ 9, 18],
        [10, 20],
        [11, 22]]])

疊加前,b和c均是shape爲(2,6)的二維數組,疊加後,arr_dstack是shape爲(2,6,2)的三維數組。

深度疊加的示意圖以下:

6.3 數組的拆分

跟數組的疊加相似,數組的拆分能夠分爲橫向拆分、縱向拆分以及深度拆分。

涉及的函數爲 hsplit()、vsplit()、dsplit() 以及split()

b
array([[ 0,  1, 20,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]])
  • 沿橫向軸拆分(axis=1)
np.hsplit(b, 2)
[array([[ 0,  1, 20],
        [ 6,  7,  8]]), array([[ 3,  4,  5],
        [ 9, 10, 11]])]
np.split(b,2, axis=1)
[array([[ 0,  1, 20],
        [ 6,  7,  8]]), array([[ 3,  4,  5],
        [ 9, 10, 11]])]
  • 沿縱向軸拆分(axis=0)
np.vsplit(b, 2)
[array([[ 0,  1, 20,  3,  4,  5]]), array([[ 6,  7,  8,  9, 10, 11]])]
np.split(b,2,axis=0)
[array([[ 0,  1, 20,  3,  4,  5]]), array([[ 6,  7,  8,  9, 10, 11]])]
  • 深度拆分
arr_dstack
array([[[ 0,  0],
        [ 1,  2],
        [20, 40],
        [ 3,  6],
        [ 4,  8],
        [ 5, 10]],

       [[ 6, 12],
        [ 7, 14],
        [ 8, 16],
        [ 9, 18],
        [10, 20],
        [11, 22]]])
np.dsplit(arr_dstack,2)
[array([[[ 0],
         [ 1],
         [20],
         [ 3],
         [ 4],
         [ 5]],

        [[ 6],
         [ 7],
         [ 8],
         [ 9],
         [10],
         [11]]]), array([[[ 0],
         [ 2],
         [40],
         [ 6],
         [ 8],
         [10]],

        [[12],
         [14],
         [16],
         [18],
         [20],
         [22]]])]

拆分的結果是原來的三維數組拆分紅爲兩個二維數組。

這個燒腦的拆分過程能夠自行分析下~~

7 數組的類型轉換

  • 數組轉換成list,使用tolist()
b
array([[ 0,  1, 20,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]])
b.tolist()
[[0, 1, 20, 3, 4, 5], [6, 7, 8, 9, 10, 11]]
  • 轉換成指定類型,astype()函數
b.astype(float)
array([[  0.,   1.,  20.,   3.,   4.,   5.],
       [  6.,   7.,   8.,   9.,  10.,  11.]])

8 numpy經常使用統計函數

經常使用的函數以下:

請注意函數在使用時須要指定axis軸的方向,若不指定,默認統計整個數組。

  • np.sum(),返回求和
  • np.mean(),返回均值
  • np.max(),返回最大值
  • np.min(),返回最小值
  • np.ptp(),數組沿指定軸返回最大值減去最小值,即(max-min)
  • np.std(),返回標準誤差(standard deviation)
  • np.var(),返回方差(variance)
  • np.cumsum(),返回累加值
  • np.cumprod(),返回累乘積值
b
array([[ 0,  1, 20,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]])
np.max(b)
20
# 沿axis=1軸方向統計
np.max(b,axis=1)
array([20, 11])
# 沿axis=0軸方向統計
np.max(b,axis=0)
array([ 6,  7, 20,  9, 10, 11])
np.min(b)
0
  • np.ptp(),返回整個數組的最大值減去最小值,以下:
np.ptp(b)
20
# 沿axis=0軸方向
np.ptp(b, axis=0)
array([ 6,  6, 12,  6,  6,  6])
# 沿axis=1軸方向
np.ptp(b, axis=1)
array([20,  5])
  • np.cumsum(),沿指定軸方向進行累加
b.resize(4,3)
b
array([[ 0,  1, 20],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])
np.cumsum(b, axis=1)
array([[ 0,  1, 21],
       [ 3,  7, 12],
       [ 6, 13, 21],
       [ 9, 19, 30]], dtype=int32)
np.cumsum(b, axis=0)
array([[ 0,  1, 20],
       [ 3,  5, 25],
       [ 9, 12, 33],
       [18, 22, 44]], dtype=int32)
  • np.cumprod(),沿指定軸方向進行累乘積 (Return the cumulative product of the elements along the given axis)
np.cumprod(b,axis=1)
array([[  0,   0,   0],
       [  3,  12,  60],
       [  6,  42, 336],
       [  9,  90, 990]], dtype=int32)
np.cumprod(b,axis=0)
array([[   0,    1,   20],
       [   0,    4,  100],
       [   0,   28,  800],
       [   0,  280, 8800]], dtype=int32)

9 數組的廣播

當數組跟一個標量進行數學運算時,標量須要根據數組的形狀進行擴展,而後執行運算。

這個擴展的過程稱爲「廣播(broadcasting)」

b
array([[ 0,  1, 20],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])
d = b + 2
d
array([[ 2,  3, 22],
       [ 5,  6,  7],
       [ 8,  9, 10],
       [11, 12, 13]])

寫在最後

numpy涵蓋的內容實際上是很是豐富的,本文僅僅介紹了numpy一些經常使用的基本功能,算是對numpy的一個入門級的簡單的較爲全面的描述。

numpy官方的《Numpy Reference》文檔,光頁面數量就有1500+頁,如想要系統的學習numpy,建議仔細閱讀官方的參考文檔,可在其官方網站進行查閱。固然,資料都是英文版的,可能看起來難度稍微大點,看習慣了就好。

本文涉及的代碼量比較多,如須要查看源代碼,請在微信公衆號「Python數據之道」(ID:PyDataRoad)後臺回覆關鍵字「2017026」。

相關文章
相關標籤/搜索